ListView (oä.) & CheckBox
-
Hallo,
ich möchte gern Daten in einer Tabellarischen Liste verwalten. Nun möchte ich gern pro Satz, 3 Dinge in der Tabelle haben. zuerst eine Checkbox, dann einen Text, und dann wieder eine CheckBox. Nun habe ich diese CheckListBox ausprobiert. Leider habe ich nur die erste Checkbox zur Verfügung.
Mit ListView (Style vsList) habe ich auch etwas experimentiert. Aber eine CheckBox habe ich nicht sauber integrieren können.
Konkrete Frage:
Wie bekomme ich Elemente, wie CheckBoxen z.B. (vielleicht auch Edits ... aber Checkboxen wären mir wichtig) in eine Tabellarische Form integriert? Leider bin ich hier im Forum nicht fündig geworden. Vielleicht hat jemand einen hilfreichen Link?zur Info: Ich benutze den Borland C++ Builder 6 Pro
Danke
-
Hallo
einfache Methode :
du verwendest TStringGrid, um die Daten darzustellen. ALs Wert für die Bool-Werte (die du in den CHeckboxen verändern willst) gibst du erstmal "Ja"/"Nein" aus. Wenn dann ein Eintrag ausgewählt wird, stellt du die Werte des Eintrages in seperaten CheckBoxen dar, wo sie geändert werden können. Ist die Änderung fertig, aktualisierst du das StringGrid.komplizierte Mehtode :
Nennt sich Inplace-Editor. Du verwendest wieder TStringGrid. Dann erstellst du für jeden Eintrag eine CHeckBox im StringGridTCheckBox *NewCheckBox = new TCheckBox(Form); NewCheckBox->Name = x; // Eindeutiger Name, um Control wiederzufinden NewCheckBox->Parent = StringGrid;
Das komplizierte ist die Positionierung der CheckBoxen. Die mußt du über das Event OnDrawCell des StringGrids machen. Dort bekommst du einen Bereich für die gerade darzustellende Zelle. Du überprüfts, ob die Zelle eine CheckBox sein soll, suchst die CheckBox des Eintrages und weist ihr den Zellbereich als Bounds zu.
bis bald
akari
-
Danke
Das erste wäre auch ne Möglichkeit gewesen, welche mir eingefallen ist. Aber erstens müßte ich die Daten dann seperat mitführen, und jedesmal das StringGrid aktualisieren. Ausserdem sähe es nicht wirklich schön aus, wenn ich eine extra checkbox platziere. Professioneller wäre es doch die Checkbox in der Tabelle zu platzieren.
Dann verwaltet mir die Tabelle im allgemeinen die Daten allein, und ich muß mich nicht um das hin und her kopieren kümmern, wenn sich was ändert.
Die 2. Lösung hört sich ja gar net verkehrt. Vielleicht ist das der Ansstoß, den ich brauchte. Geht das auch mit nem Listview?
-
Hallo
Die 2. Lösung hört sich ja gar net verkehrt. Vielleicht ist das der Ansstoß, den ich brauchte. Geht das auch mit nem Listview?
Sollte auch mit TListView gehen. Da brauchst du die On..CustomDraw-Events. Allerdings kenne ich mich mit TListVIew nicht so gut aus.
Denke dran das du für alle nicht sichtbaren EInträge auch die Checkboxen unsiochtbar machen mußt.
Außerdem wirkt sich die dynamische Erschaffung von Controls (>20) negativ auf die Performance aus.
Überleg also, ob es denn Aufwand wert ist. Die erste Methode ist zwar langweiliger, aber wirklich einfacher.bis bald
akari
-
Danke erst mal, ich werde es mal in einer freien Minute testen.
Es sieht halt doch deutlich schöner aus, wenn alles sauber beieinander ist, und ich die Checkboxen im Eintrag selbst auswählen kann. Aber das ist geschmackssache.
-
Hallo
Aber das ist geschmackssache
Eher eine Frage der Programmier-Fähigkeit
bis bald
akari
-
Ja, daran scheiterts meist
-
Hallo
das eleganteste ist eine Kombination beider Varianten : Zuerst stellst du die Daten der Einträge wie in Variante 1 dar. Wenn dann ein Eintrag ausgewählt wird, erstellst du wie in Variante 2 eine Checkbox für diesen Eintrag. Wenn vorher ein Eintrag ausgewählt war, mußt du vorher noch die CheckBox des alten Eintrages bestimmen, den Wert der CheckBox speichern und die CheckBox löschen.
bis bald
akari
-
akari schrieb:
......
komplizierte Mehtode :
Nennt sich Inplace-Editor. Du verwendest wieder TStringGrid. Dann erstellst du für jeden Eintrag eine CHeckBox im StringGridTCheckBox *NewCheckBox = new TCheckBox(Form); NewCheckBox->Name = x; // Eindeutiger Name, um Control wiederzufinden NewCheckBox->Parent = StringGrid;
Das komplizierte ist die Positionierung der CheckBoxen. Die mußt du über das Event OnDrawCell des StringGrids machen.
Dort bekommst du einen Bereich für die gerade darzustellende Zelle. Du überprüfts, ob die Zelle eine CheckBox sein soll,
suchst die CheckBox des Eintrages und weist ihr den Zellbereich als Bounds zu.bis bald
akariIch habe jetzt das Problem, wenn ich auf die CheckBox im StringGrid klicke wird kein Hacken gesetzt und auch kein OnKlick-Ereignis ausgelöst.
Und wie kann ich auf die Eigenschaften der CheckBox zugreifen.
Nach dem das Objekt erzeugt wurde.Gruß Marco
void __fastcall TForm1::StringGrid2DrawCell(TObject *Sender, int ACol, int ARow, TRect &Rect, TGridDrawState State) { if((ACol == 2)&&(ARow>0)){ TCheckBox *NewCheckBox = new TCheckBox(Form1); NewCheckBox->Parent = StringGrid2; NewCheckBox->Checked = true; NewCheckBox->OnClick = &CheckBox1Click; NewCheckBox->OnMouseDown = &CheckBox1MouseDown; NewCheckBox->Top = Rect.Top; NewCheckBox->Width = 15; } } //--------------------------------------------------------------------------- void __fastcall TForm1::CheckBox1Click(TObject *Sender) { ShowMessage("Test"); }
-
Lass mal die &-Zeichen vor den Eventmethoden weg.
NewCheckBox->OnClick = CheckBox1Click; NewCheckBox->OnMouseDown = CheckBox1MouseDown;
-
Hallo Braunstein,
Das hat leider keinerlei Wirkung gezeigt.
Es wird aber das onMouseDown-Ereigniss ausgelöst.
Es wird aber kein Hacken gesetzt und auch nicht das onClick-Ereigniss ausgelöst.Gruß Marco
-
Hi,
das OnClick-Event greift auch nicht, nimm dafür MouseDown.
Noch was anderes, es ist in jedem Fall besser, die NewCheckBoxen nicht im Ereignis DrawCell zu erstellen.
Bei jedem Zeichnen des Gitters werden neue CheckBoxen erzeugt, ohne die alten zu löschen.Versuchs mal so:
in *.h-Datei:
TCheckBox *NewCheckBox; void __fastcall NewCheckBoxMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y);
in *.cpp-Datei:
void __fastcall TForm::FormActivate(TObject *Sender) { for (int i=1; i < StringGrid1->RowCount; i++) { NewCheckBox = new TCheckBox(this); NewCheckBox->Name = "chBox" + IntToStr(i); NewCheckBox->Parent = StringGrid1; NewCheckBox->Checked = true; NewCheckBox->Enabled = true; NewCheckBox->OnMouseDown = NewCheckBoxMouseDown; NewCheckBox->Caption = "chBox" + IntToStr(i); } } //--------------------------------------------------------------------------- void __fastcall TForm::StringGrid1DrawCell(TObject *Sender, int Col, int Row, TRect &Rect, TGridDrawState State) { if(Col == 2 && Row > 0 ){ // 3.Spalte, in allen Zeilen ausser 1. TCheckBox* chBox; for(int i=0; i < ComponentCount; i++) { // ist es eine TCheckBox-Komponente ? if (Components[i]->ClassNameIs("TCheckBox")) { chBox = (TCheckBox*)Components[i]; if (chBox->Name == "chBox" + IntToStr(Row)) { chBox->Top = Rect.Top; chBox->Height = Rect.Bottom - Rect.Top; chBox->Left = Rect.Left; chBox->Width = Rect.Right - Rect.Left; } } } } } //--------------------------------------------------------------------------- void __fastcall TForm::NewCheckBoxMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { TCheckBox* chBox; chBox = static_cast<TCheckBox*>( Sender ); if (chBox) chBox->Checked =! chBox->Checked; } //--------------------------------------------------------------------------- void __fastcall TForm::FormClose(TObject *Sender, TCloseAction &Action) { delete NewCheckBox; } //---------------------------------------------------------------------------
Edit: Wenn du zur Laufzeit die Anzahl der NewCheckBox ändern willst, nimm zur
Verwaltung der NewCheckBox-Kompos ein TList; macht sich sehr gut.mfg
kpeter
-
Hi kpeter,
Danke das Beispiel funktioniert soweit.
Ich weis leider nicht wie du das meinst mit dem TList-Object.
Gruß Marco
-
Hi,
das mit dem TList sollte eine Anregung gewesen sein.
Knapp gesagt, speicherst du im TList indiziert Referenzen auf Objekte, in dem Fall
auf deine ComboBoxen.
Du kannst gezielt und schnell auf sie zugreifen.mfg
kpeter
-
Hi,
Das mit der Tlist war eine sehr gute Idee.
Danke noch mal für die HilfeGruß Marco