21. februar 2003 - 07:44Der er
17 kommentarer og 1 løsning
Adressere variable object-variabler i C++ Builder 5
Jeg har problemer med følgende problemstilling:
Jeg husker at VB6 er muligt at lave noget der kaldes control arrays, hvor man laver et array af objekter på en form.
Er dette muligt i C++ builder.
Eksempel:
for (int i=0; i < 3; i++) { ListBox{i}->Items->Add("Noget tekst"); }
Koden "ListBox{i}" fungerer jo ikke, men er min tankegang klar? I for-løkken vil jeg have 3 listboxe som jeg tilføjer en linie til, automatisk vha. af løkkens-tællevariabel.
Jeg har aldrig arbejdet med C++ Builder, men rent C++-mæssigt bør det være muligt. C++ Builder må tilbyde dig en type, der beskriver dine listboxe, ellers kan du ikke referere til dem fra din kode. Lad os lade som om C++ Builder typen hedder CBListBox. Så laver du
og så smider du adressen på hver af dine tre list boxe ind i den vector, og så itererer du igennem vector'en, og kalder Add-metoden (eller hvad den nu kommer til at hedde i C++ Builder).
På denne måde laver du dit eget control array. Det er så muligt at C++ Builder selv understøtter control arrays direkte, men som sagt, jeg aner intet om C++ Builder.
Ups, jeg har kun defineret vector-typen, ikke nogen instans. Så husk at lave en instans af CBListBoxVector. Det er så ind i denne instans du skal smide adressen på hver af dine tre list boxe.
Øhh jeg tror jeg ved hvad du mener men jeg startede på C++ for ca. 2 uger siden. Hvordan laver du en instans af vektoren??? ListBoxe i Builder er af typen TListBox og ændre jeg din linie efter den type, får jeg ingen kompiler-fejl, så noget må jo virke :)
Controller på en form kan refereres vha. af formens Components og Controls list. De holder referencer til hhv. controller eget (owner) af formen og controller der rent visuelt er børn af formen (parent). Det er begge lister du kan tilgå i en for-løkke.
Hvis du ønkser at samholde et antal controller (som er det dit spørgsmål går på), kan du ganske simpelt benytte en TList. Denne kan du så bruge i stil med dit eget eksempel...
OK, jeg skal forsøge efter bedste hukommelse (det er lææænge siden jeg har brugt BCB). Til at starte med kan du bare glemme Components og Controls (som iøvrigt er member af TForm, som er den klasse alle dine normale forms arver fra).
Nå.. Når du har smidt de controller (feks. tre listbokse LB1, LB2, LB3) på din form kan du (eksempelvis i formens OnCreate) smide dem ind i en TList således:
FList = new TList(this); /* jeg kan altså ikke huske denne, men det er std ctor for din TList */
for ( int idx = 0; idx < FList->Count; idx++ ) FList->Items[idx] ... /* er slet ikke sikker på syntaxen her. Afhængig af hvad du vil skal du bruge en typecast, idét FList's items "tror" de er af typen *TObject. */
Det var det.. husk at slette din FList igen når du ikke har brug for den længere.
Jeg har været for hurtig på aftrækkeren. TList ctor'en har ingen parametre. Derfor:
I din klasses (formens) "private:" lav en TList FList;
I din klasses OnCreate (eller lignende sted) lav en: FList = new TList;
I din klasses OnDestroy lav en: delete FList;
Det skulle være det.
Hvis du ikke ønsker besværet med en TList, kan du vælge at placere dine controls på eksempelvis et TPanel. På denne måde bliver dine controls automatisk stoppet ind i TPanel'ets Controls. Så kan du fange dem således:
for ( int idx = 0; idx < Panel->ControlCount; idx++ ) ShowMessage(Panel->Controls[idx]->ClassName());
... og så skal du iøvrigt lige være lidt "opfindsom" med pointere i ovenstående kode. Jeg er vandt til at arbejde med VCL'et i Delphi. (TList FList burde selvfølgelig erklæres som TList *FList)
Ok - nu tror jeg at jeg er tæt på at få det til at fungere :)
Jeg bruger som sagt Borland C++ Builder 5.
Jeg forsøger i øjeblikket med en TPanel kaldet Panel1. I denne eksisterer der 3stk TListBox med navnene LB1, LB2 og LB3.
Jeg forsøger at eksperimentere med de pointere.
Det sidste problem ligger vistnok i for-løkken hvor jeg skal arbejde dynamisk med de 3 listboxe.
Men jeg kan ikke blot skrive:
for (int idx=0; idx < Panel1->ControlCount; idx++) { Panel1->Controls[idx]->Items->Add("Hej"); }
Den siger at items ikke er medlem af TPanel. Skal jeg typecaste noget her, eller ...??
Men fair nok, så prøver jeg det her istedet:
TListBox *FLB; // Denne deklareres globalt
for (int idx=0; idx < Panel1->ControlCount; idx++) { FLB = new TListBox(Panel1->Controls[idx]); FLB->Items->Add("hej"); delete FLB; }
Ved klik på min TButton som det hele ved, kommer en error frem: ... raised exception class EInvalidOperation with message 'Control '' has no parent window'.
Du bør (og vil!) ikke indsætte ting direkte i Controls-listen. Det jeg skrev var at du ENTEN skal bruge et TPanel eller en TList. Ved TPanel gælder det at dine controller du på design-time dropper på formen, automatisk bliver en del af TPanel's Controls[]. Ved TList skal du gøre det selv...
Hvis du dynamisk vil placere tre listboxe på et eksisterende TPanel, gør således:
for (int idx=0; idx < 3; idx++) { FLB = new TListBox(DinForm); FLB->Parent = DitPanel; FLB->Items->Add("hej"); }
Formen DinForm er nu owner af dine listbokse, hvilket betyder at den er ansvarlig for at deallokerer dem igen. DitPanel er parent, hvilket betyder at rent visuelt tilhører dine controls DitPanel (hvilket iøvrigt er grunde til fejlbekskeden).
Du har nu tre FLB'ere på dit panel (det er muligt du ikke kan se dem på formen lige med det samme, men der er der). Som en ekstra bonus behøver du ikke selv slette dem igen, idet formen selv gør det.
Jeg tror du har mistforstået hvad det er jeg forsøger at gøre.
Jeg vil ikke automatisk oprette nogle komponenter - jeg vil arbejde med dem dynamisk.
Jeg vil kunne addressere til mine tre listboxe via en for-løkke.
Forresten bør jeg nok nævne at det med pointere og ting - er et kapitel jeg endnu ikke er noget til endnu... Jeg er total newbie i C++...
Derfor skal jeg bruge hele eksempler af kode, ikke småstykker :)
Lad os tage en helt anden problemstilling:
Jeg har flere ComboBoxe på min form. Samtidig har ligeså mange edit-felter(TEdit). Hvordan er det muligt at få noget data ind i det edit-felt som ligger lige ved siden af hver combobox ?? Hver par af combobox og edit-felt har samme Tag ...
Pointere er en essentiel del af C(++), som du bør tage fat på i en fart. Specielt i sammenhæng med BCB's VCL er de meget brugte. Alle de steder du ser en * og en -> har du fat i pointere.
Ok... så du har på design-time placeret tre listboxe på et TPanel, er det korrekt? Hvis det er de eneste controller på panelet, kan du adressere dem således:
for ( int idx = 0; idx < Panel->ControlCount; idx++ ) { TListBox *L; L = (TListBox*)Panel->Controls[idx]; L->Items->Add("Hej"); }
Mht. til dine comboboxe er der flere muligheder. Den bedste løsning afhænger af flere ting. Hvis du alligevel har valt at benytte Tag-proptertien, kan du vælge at placere adressen på edit-boksen i tag'en på combo'en. Så behøver du ikke "lede" efter den. Prøv følgende:
Combo->Tag = (int)Edit;
Så burde der stå et eller andet i Combo.Tag, som du kan brug som følger:
TEdit *E; E = (TEdit*)Combo->Tag; E->Text = "Hej";
Igen snakker vi pointere og fæle typecasts. Derfor: lær dem at kende hurtigst muligt :)
Operatoren "new" allokerer plads til en ny "dims" på heapen og returnerer en.. you guessed it.. pointer til starten af det nys allokerede. Og jo, du kommer til at bruge new mange, mange gange...
Jeg takker mange gange for din tålmodighed - min var nemlig ved at løbe ud :)
Men nu fungerer det med TList og det med TPanel endelig. Dog synes jeg det er lettere at bruge en TList, det gør ikke noget man selv skal smide elementerne ind i den.
Men jeg ser nu kraften i sproget - takker mange gange.
Det er nu sjovt at læse igen :) Fattede hat dengang - på 2. semester :P
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.