31. januar 2006 - 14:54Der er
3 kommentarer og 1 løsning
Vise data i tabel
Jeg er lidt i tvivl om hvordan jeg gør det nedenstående bedst, så jeg håber at "ekspertene" herinde kan hjælpe :-)
Sagen er den at der til mit program bliver sendt en pakke med en klump data (fornavn, efternavn, email og telefonnummer) via TCP. Disse data vil jeg gerne havde sat ind i en tabel i det øjeblik de modtages (en række pr. datasæt).
Når så næste datasæt modtages skal dette også indsættes i tabellen. Men problemet nu er at de skal sorteres efter f.eks. efternavn. Hvordan kan det klares i Delphi?
Det skal desuden være sådan at hvis jeg klikker på en række, skal det være muligt at arbejde på de data i den række jeg markerede.
Hvordan laves alt dette mest effektivt i Delphi 2005? Hovedsageligt leder jeg efter ideer til hvordan det gøres, så jeg forventer ikke at al koden leveret på et sølvfad :)
I dette særtema om aspekter af AI ser vi på skiftet fra sprogmodeller til AI-agenter, og hvordan virksomheder kan navigere i spændet mellem teknologisk hastighed og behovet for menneskelig kontrol.
1. Er der een eller flere records i dit input-datasæt ? 2 Du skriver tabel, men er det en flad fil, eller en database, og i givet fald hvilken ?
Det nemmeste ville være at gemme dem i en tabel i en database, f.eks. MySQL. Al sorteringen af data kan klares af database-systemet, så du skal koncentrere dig om brugerinterfacet.
Den ikke SQL-baserede løsning er, at bruge en TListView komponent, hvor du laver sortering på kolonnerne.
Hver person-objekt kan så hægtes på TListItem.Data property'en så du har objektets data ved hånden hvis du eksempelvis dobbeltklikker på linien.
Ved rettelse af en linie kan du enten lave en rettedialog eller lade TEdit'er flyde ovenpå felterne i TListView'et. Det sidste er ret besværligt.
Dine person-objekter kan du enten lade hænge på dit listview og slette dem via OnDeletion-eventet og/eller have dem i en TObjectList parallelt med listview'et.
-------------------------------------------------------------- Din TPerson ville jeg lave i retning af dette (Unitten forst): --------------------------------------------------------------
type TPerson = class private fFornavn : string; fEfternavn : string; ... public // Opret vha. dine dataklumper constructor Create(aStream : TStream); overload; // Opret via en dialog i programmet constructor Create(aFornavn, aEfternavn, aAdresse, aPostnr, aEmail, aTlf : string); overload; property Fornavn : string read fFornavn; property Efternavn : string read fEfternavn; ... function Edit(aOwner : TComponent) : boolean; // Til at rette personen procedure FillListItem(aListItem : TListItem); // Til at hægte sig på listviewet end;
// Egentlig ikke nodvendig, men jeg plejer at tage den med. TPersonList = class(TObjectList) private public property Item[const aIndex : integer] : TPerson read GetPerson; default; procedure FillListView(aListView : TListView); end;
implementation
{ TPerson }
...
// Fyld én record i listview procedure TPerson.FillListItem(aListItem : TListItem); begin aListItem.SubItems.Clear; aListItem.Data := self; // Hægt objektet på listitem'et. aListItem.Caption := fFornavn + ' ' + fEfternavn; aListItem.SubItems.Add(fEMail); aListItem.SubItems.Add(fTlf); end;
{ TPersonList }
...
// Listens "Fyld alle data i listviewet" ser således ud: procedure TPersonList.FillListView(aListView : TListView); var i : integer; begin aListView.Items.BeginUpdate; try aListView.Items.Clear; for i := 0 to Count - 1 do Item[i].FillListItem(aListView.Items.Add); finally aListView.Items.EndUpdate; end; end;
----------------------- Skelettet til din form: -----------------------
Når du så har et TPerson-objekt klar til visning i dit listview:
procedure TForm1.DataReadyEllerSaadanNoget(aStream : TStream); var Person : TPerson; ListItem : TListItem; begin // Person-objektet ved hvordan det skal håndtere din dataklump Person := TPerson.Create(aStream); // Opret listitem ListItem := ListView1.Items.Add; // Person-objektet ved hvordan det skal præsentere din dataklump i et listview Person.FillListItem(ListItem); end;
Dit listview har en OnColumnClick og en OnCompare som du skal bruge til sortering (i øvrigt lavet pænere i .NET):
TForm1 = class(TForm) private fColumnClicked : integer; // Hvilken kolonne blev klikket fSortAscending : boolean; // Hvilken retning skal der sorteres public end;
procedure TForm1.ListView1ColumnClick(Sender: TObject; Column: TListColumn); begin if fColumnClicked = Column.Index then fSortAscending := not fSortAscending else begin fColumnClicked := Column.Index; fSortAscending := true; end; // Sæt eventuelle sorteringspile her (Sender as TListView).AlphaSort; end;
procedure TForm1.ListView1Compare(Sender: TObject; Item1, Item2: TListItem; Data: Integer; var Compare: Integer); var p1, p2 : TPerson; begin p1 := Item1.Data; p2 := Item2.Data; case fColumnClicked of 0 : begin Compare := CompareStr(p1.Efternavn, p2.Efternavn); if Compare = 0 then // Jensen = Jensen, prøv fornavn Compare := CompareStr(p1.Fornavn, p2.Fornavn); end; 1 : Compare := CompareStr(p1.Email, p2.Email); 2 : Compare := CompareStr(p1.Tlf, p2.Tlf); end; if not fSortAscending then // Vend sorteringsorden Compare := -Compare; end;
Endelig så kan du få ListView'et til at slette objektet når du sletter en linie:
// Hvis du har en parallel liste til dine personer procedure TForm1.ListView1Deletion(Sender: TObject; Item: TListItem); var Person : TPerson; begin // Den korte up‘dagogiske version er : fPersonList.Remove(Item.Data); Person := Item.Data; fPersonList.Remove(Person); end;
// Hvis listviewet er "listen" procedure TForm1.ListView1Deletion(Sender: TObject; Item: TListItem); var Person : TPerson; begin // Den korte up‘dagogiske version er : TPerson(Item.Data).Free; Person := Item.Data; Person.Free; end;
fs-manden: ad1. Det der kommer ind via TCP er en buffer indeholdende et recordsæt bestående af 4 "variable" (fornavn, efternavn, email og telefonnummer). ad2. Jeg bare have smidt data'ene ind i en tabel så de kan ses. Der skal ikke arbejdes med data'ene som sådan, man skal blot kunne markere, indlæse og slette fra tabellen.
Hvordan ville du evt. klare det hvis du smed data'ene i en database først (hvilken databasetype ville du anvende)?
Du skal bare sprøge om der er noget der driller. Det er en løsningsmodel jeg har brugt utallige gange og den virker for mig; især efter jeg fandt TObjectList'en.
Hvis det er lidt uoverskueligt så skyldes det at jeg pakker lidt meget sammen i en "post".
Der er: - Brugen af data objekter (som ved hvordan de læses fra en strem og derefter præsenteres. - Brugen af TObjectList - Brugen af TListView (incl. sortering af kolonner)
- Endelig muligheden for at bruge "konceptet" med TObjectList eller glemme den.
Der er mange ting.
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.