Tabcontrol Object im Tab speichern

Rund um die LCL und andere Komponenten

Tabcontrol Object im Tab speichern

Beitragvon gtmind.de » 27. Mär 2018, 12:58 Tabcontrol Object im Tab speichern

Hallo allerseits,
ich versuche gerade den Tabs im Tabcontol IDs mitzugeben. Quellcode funktioniert in Delphi.

Code: Alles auswählen
 
//Object:
type
  TFid = class
  public
    id: Integer;
    constructor Create(fid: Integer);
  end;
 
......
 
constructor TFid.Create(fid: Integer);
begin
  id := fid;
end;
 
//TabControl in einer Schleife füllen
  .....
  Qu.Open;
  i := 0;
  while not Qu.Eof do
  begin
    i := tc.Tabs.AddObject(
      Qu.FieldByName('VAL').Value,
      TFid.Create(TStringField(Qu.FieldByName('COL')).AsInteger)
      );
 
    //ShowMessage(IntToStr(i)+' === '+IntToStr(TFid(tc.Tabs.Objects[i]).id));
    inc(i);
    Qu.Next;
  end;
  tc.EndUpdate;
 
// Tabcontrol auslesen
procedure TfrmSolutions.tcChange(Sender: TObject);
begin
  ShowMessage(tc.Tabs.ValueFromIndex[tc.TabIndex]);
end;
 
.

ergibt immer 0. Egal welcher Wert im Object ist (war?)

Gruß Gerald
Auch aus Steinen, die einem in den Weg gelegt werden, kann man etwas schönes bauen.
gtmind.de
 
Beiträge: 8
Registriert: 27. Feb 2011, 16:23
Wohnort: Dessau-Roßlau
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.4.z) | 
CPU-Target: AMD 32/64 bit
Nach oben

Beitragvon theo » 27. Mär 2018, 17:41 Re: Tabcontrol Object im Tab speichern

Geht nicht, afaik.
S.a.
http://forum.lazarus.freepascal.org/ind ... ic=13131.0

Eine separate Liste halten.
theo
 
Beiträge: 8059
Registriert: 11. Sep 2006, 18:01

Beitragvon gtmind.de » 27. Mär 2018, 18:02 Re: Tabcontrol Object im Tab speichern

In Delphi keine Problem ... habe schon auf ComboBox umgestellt :roll: :cry:
Auch aus Steinen, die einem in den Weg gelegt werden, kann man etwas schönes bauen.
gtmind.de
 
Beiträge: 8
Registriert: 27. Feb 2011, 16:23
Wohnort: Dessau-Roßlau
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.4.z) | 
CPU-Target: AMD 32/64 bit
Nach oben

Beitragvon wp_xyz » 27. Mär 2018, 18:20 Re: Tabcontrol Object im Tab speichern

Du bringst hier etwas durcheinander:
(1) Wenn du Zusatzinformation per TStrings.ValueFromIndex auslesen willst, muss die Information vorher via TStrings.Add('Name=Wert') in die Liste geschrieben worden sein. Das Argument des Add-Aufrufs ist aber gerade der Text, der auf dem Tab-Reiter steht, also "Name=Wert" - das willst du sicher nicht.

(2) Du schreibst die Zusatzinformation per TStrings.AddObject('name', Zusatzinfo_als_TObject) in die StringListe. Das wäre normalerweise OK, wenn die Zusatzinformation über TStrings.Objects[index] ausgelesen werden würde. Aber hier funktioniert auch das nicht, weil das eingehängte Objekt bereits intern verwendet wird. Um das zu sehen, klicke ein TabControl aufs Formular, füge im Designmodus ein paar Tabs hinzu und schreibe folgenden OnChange-Event-Handler:
Code: Alles auswählen
procedure TForm1.TabControl1Change(Sender: TObject);
var
  tabObj: TObject;
begin
  tabObj := TabControl1.Tabs.Objects[TabControl1.TabIndex];
  if tabObj = nil then
    ShowMessage('NIL')
  else
    ShowMessage(tabObj.Classname + / ' + TWinControl(tabObj).Caption);
end; 

Bei jedem Klick wird "TabSheet/<Name des Tabs>" ausgegeben, obwohl eigentlich bewusst gar kein TTabSheet als Objekt an die Tabs gehängt worden ist. Meiner Meinung nach ist TTabControl hier sehr schlecht programmiert, weil Einhängen von Zusatzinformationen unterbunden wird.

Wenn du einen zusätzlichen Integer zu jedem Tab speichern möchtest, fallen mir folgende Möglichkeiten ein:

(1) ein separates Array (oder TList oder TIntegerList, o.ä) außerhalb des TTabControl anlegen und dort den Integer speichern. Du musst natürlich dafür sorgen, dass die Tab-Liste und die Integer-Liste synchron bleiben.

(2) Eine andere, sehr hackermäßige Variante geht davon aus, dass alle GUI-Elemente bei einem String, der ein #0 enthält, die folgenden Zeichen nicht mehr anzeigen. Daher könntest du die Zusatzinformation einfach nach einer #0 mit in die Tab-Beschriftung packen:
Code: Alles auswählen
  while not Qu.Eof do
  begin
    tc.Tabs.Add(
      Qu.FieldByName('VAL').Value + #0 + IntToStr(Qu.FieldByName('COL')).AsInteger));
...

Später beim Auslesen:
Code: Alles auswählen
procedure TfrmSolutions.tcChange(Sender: TObject);
var
  s, info: String;
  p: Integer;
begin
  s := tc.Tabs[tc.TabIndex];
  p := pos(#0, s);
  if p > 0 then begin
    info := copy(s, p+1, MaxInt);
    s := copy(s, 1, p-1);
  end else
    info := '';
 ShowMessage(s + LineEnding + 'ZusatzInfo: ' + info);
end;

Ich bin nicht sicher, ob sich alle Widgetsets so verhalten wie das von mir verwendete Windows. Und wie alle Hackerlösungen kann das irgendwann nicht mehr funktionieren.

(3) Die richtige Stelle, einen Integer einem Objekt mitzugeben, wäre die Allzweck-Eigenschaft "Tag". Nur: vordergründig erzeugt TTabControl keine separaten Objekte für die Tabs. Aber wie wir oben gesehen haben, ist das nicht richtig. Es wird für jeden Tab ein TTabsheet erzeugt und in den Objects[] der Tab-Strings abgelegt. Damit kommt man auf diese
Weise an das "Tag" zum Schreiben
Code: Alles auswählen
var
  tabsheet: TTabSheet;
  i: Integer;
...
  while not Qu.Eof do
  begin
    i := tc.Tabs.Add(Qu.FieldByName('VAL').Value);
    tabsheet := TTabSheet(tc.Tabs.Objects[i]);
    tabsheet.Tag := Qu.FieldByName('COL')).AsInteger);
  ...

und so zum Auslesen
Code: Alles auswählen
var
  tabsheet: TTabsheet;
begin
  tabsheet := TTabSheet(tc.Tabs.Objects[tc.TabIndex])
  ShowMessage(IntToStr(tabsheet.Tag));

Auch das gefällt mir nicht, weil das TTabControl offenbar sehr schlampig programmiert ist und sich irgendwann sicher jemand der Komponente annehmen wird - als Folge ist nicht garantiert, dass es weiterhin ein verstecktes TabSheet geben wird.

Also? Ich würde Variante 1 nehmen.
wp_xyz
 
Beiträge: 2651
Registriert: 8. Apr 2011, 08:01

• Themenende •

Zurück zu Komponenten und Packages



Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 3 Gäste

cron
porpoises-institution
accuracy-worried