Дублекат Вкладок В Tabcontrol После Обновления Listview

Тема в разделе "Delphi - Компоненты", создана пользователем Shouldercannon, 10 окт 2014.

  1. Shouldercannon

    Shouldercannon Well-Known Member

    Регистрация:
    25 май 2010
    Сообщения:
    125
    Симпатии:
    0
    Доброго времени суток!
    Пытаюсь реализовать работу с вкладками TabControl
    Код (Delphi):
    unit frm_Main;

    ...

    var
    FormMain: TFormMain;

    implementation

    uses frm_2;

    {$R *.dfm}

    procedure TFormMain.Button1Click(Sender: TObject);
    var
    i: Integer;
    Item: TListItem;
    begin
    LVUsers.Clear;

    for i := 0 to 4 do
    begin
    Item := LVUsers.Items.Add;
    Item.Caption := '';
    Item.SubItems.Add(Format('Name: %d', [i])); // Name
    Item.SubItems.Add(Format('30%d', [i])); // Room
    Item.SubItems.Add(IntToStr(i)); // ID
    Item.SubItems.Add('0'); // Icon
    Item.ImageIndex := 0;
    end;
    end;

    procedure TFormMain.LVUsersDblClick(Sender: TObject);
    begin
    if LVUsers.Selected = nil then Exit;
    Form2.ProcAddTab(LVUsers.Items[LVUsers.ItemIndex], True, True);
    end

    end.



    unit frm_2;

    interface

    uses
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
    Dialogs, Menus, StdCtrls, ComCtrls, ToolWin, ExtCtrls, Contnrs;

    type
    TTabData = class(TObject)
    public
    UserID: Integer;
    Nick: string;
    TempMessage: string;
    end;

    TTabDataList = class(TObjectList)
    private
    function GetTab(Index: Integer): TTabData;
    public
    function AddTab(UserID: Integer; Nick, TempMessage: string): TTabData;
    property Tabs[Index: Integer]: TTabData read GetTab; default;
    end;

    type
    TForm2 = class(TForm)
    ...
    private
    { Private declarations }
    public
    { Public declarations }
    procedure ProcAddTab(Usr: TListItem; ChangeTab, ShowForm: Boolean);
    end;

    var
    Form2: TForm2;
    TabList: TTabDataList;
    tbInd: Integer;
    UserData: TTabData;

    implementation

    uses frm_Main;

    {$R *.dfm}

    function TTabDataList.AddTab(UserID: Integer; Nick, TempMessage: string): TTabData;
    begin
    Result := TTabData.Create;
    Result.UserID := UserID;
    Result.Nick := Nick;
    Result.TempMessage := TempMessage;
    inherited Add(Result);
    end;

    function TTabDataList.GetTab(Index: Integer): TTabData;
    begin
    Result := inherited Items[Index] as TTabData;
    end;

    procedure TForm2.FormCreate(Sender: TObject);
    begin
    TabList := TTabDataList.Create(True); // TabList сам уничтожтит элемент при удалении
    end;

    procedure TForm2.FormDestroy(Sender: TObject);
    begin
    FreeAndNil(TabList);
    end;

    procedure TForm2.ProcAddTab(Usr: TListItem; ChangeTab, ShowForm: Boolean);
    var
    UsrData: TTabData;
    i: Integer;
    begin
    UsrData := Usr.Data;

    if (UsrData = nil) then // Нет такого пользователя
    begin
    // Создаем, добавляем в список TabList
    UsrData := TabList.AddTab(StrToInt(Usr.SubItems[2]), Usr.SubItems[0], '');
    // Связываем с элементом в LVUsers
    Usr.Data := UsrData;
    end;
    // Ищем пользователя на вкладках
    i := TabControl1.Tabs.IndexOfObject(UsrData);

    if (i < 0) then // Нет вкладки с таким пользователем, добавляем новую вкдадку - здесь дыра
    begin
    i := TabControl1.Tabs.Add(UsrData.Nick);
    // Связываем c конкретной вкладкой
    TabControl1.Tabs.Objects[i] := UsrData;
    end;

    if ChangeTab then
    begin
    // Сделаем вкладку активной
    TabControl1.TabIndex := i;
    end;
    // Покажем форму если разрешено
    if ShowForm then
    begin
    Self.WindowState := wsNormal;
    Self.Show;
    end;
    end;

    end.
    Нашёл один недостаток. Если пересоздать список пользователей в ListView и кликать по этим записям, то в TabControl появляться дубликаты уже имеющихся/открытых вкладок.
    Тут
    Код (Delphi):
     // Ищем пользователя на вкладках
    i := TabControl1.Tabs.IndexOfObject(UsrData);
    отладчик показывает одинаковые данные до обновления и после обновления списка пользователей при проверке выбранной записи
    (0, 'Name: 0', '')
    (0, 'Name: 0', '')

    В чём проблема? Это можно исправить?
     
  2. -master-

    -master- Well-Known Member

    Регистрация:
    14 янв 2012
    Сообщения:
    629
    Симпатии:
    18
    как проверяются на тождество 2 объекта?
     
  3. Shouldercannon

    Shouldercannon Well-Known Member

    Регистрация:
    25 май 2010
    Сообщения:
    125
    Симпатии:
    0
    Проверка на тождество отсутствует
     
  4. -master-

    -master- Well-Known Member

    Регистрация:
    14 янв 2012
    Сообщения:
    629
    Симпатии:
    18
    TabControl1.Tabs.IndexOfObject(UsrData);

    а это что?
     
  5. Shouldercannon

    Shouldercannon Well-Known Member

    Регистрация:
    25 май 2010
    Сообщения:
    125
    Симпатии:
    0
    В TForm2.ProcAddTab передается TListItem, взятое из TListView.Items. Там же потом извлекается Data. Так вот, что же храниться в Data? А там храниться ссылка на область памяти. Той самой памяти, которая заполняется в AddTab и отдается потом в TabControl1.Tabs.Objects. При нажатии Button1 срабатывает LVUsers.Clear; TListView очищается и, соответственно, очищаются все Data. При последующем срабатывании ProcAddTab данных в Data нет. А раз так, то выполняется условие (UsrData = nil), заново выделяется и заполняется данными память в AddTab, идет сравнение по IndexOfObject и оно не срабатывает т.к. хоть данные и одинаковые, но это не те же данные, а поэтому IndexOfObject возвращает -1. Это очень хорошо видно, если под отладчиком в ProcAddTab вызвать Pointer(UsrData) и посмотреть что там будет для каждой записи при первом заполнении LVUsers и потом при перезаполнении LVUsers.

    Короче, IndexOfObject не срабатывает потому, что мы сравниваем разные экземпляры класса TTabData. И хоть они заполнены одинаковыми данными, это все-равно разные экземпляры.
     
  6. -master-

    -master- Well-Known Member

    Регистрация:
    14 янв 2012
    Сообщения:
    629
    Симпатии:
    18
    в этой строке происходит та самая проверка

    поэтому надо вам посмотреть в книгу, где и как она делается
     
Загрузка...
Похожие Темы - Дублекат Вкладок Tabcontrol
  1. hosm
    Ответов:
    0
    Просмотров:
    4.215

Поделиться этой страницей