Avatar billede kroning Nybegynder
15. januar 2008 - 14:36 Der er 10 kommentarer og
1 løsning

TComboBoxEx er langsom

Jeg bruger Delphi 7

Jeg bruger .Items.Add() i TComboBoxEx til at indsætte tekster, desværre er TComboBoxEx ca. 4 gange som langsom som TComboBox.
Noget der har en løsning på hvordan man får mere fart på TComboBoxEx?
Avatar billede hrc Mester
15. januar 2008 - 22:58 #1
Du kender sikkert BeginUpdate og EndUpdate, ikke? Det speeder tingene op med en faktor 2. Det hurtigste var om du kunne arbejde med et "vindue" som i TListView hvor den let kan sættes op til at vise et udsnit af en bagvedliggende liste. Et TListView går normaæt i koma når der kommer flere end 1000 linjer. Med et vindue var der ingen begrænsning for man skulle kun koncentrere sig om at vise de, ja de der skulle vises. Hvis man kan samme med TComboBoxEx er det klar løsningen - men jeg prøver lige at kigge på komponenten.
Avatar billede hrc Mester
15. januar 2008 - 23:52 #2
Det er nu ikke fordi det giver den store forskel at lave Begin- og EndUpdate. Ved indsættelse af 10000 linjer tog det stort set samme tid (1s)

Hvis du kender antallet først mener jeg der er en capacity-property du kan sætte. Den har godtnok aldrig hjulpet mig, men hjælpen skriver at det går hurtigere.

Har også skimmet hele arvehierarkiet igennem og sådan en TCollectionItem nedarver mange gange. Jeg kan umiddelbart ikke se hvor der er noget at hente. Der bliver ikke fyret events af når man indsætter og der er ingen synlig virkning ved brugen af Begin-/EndUpdate.

På den anden side synes jeg heller ikke den yder så dårligt. Jeg indsatte 10000 linjer og det tog under 1 sekund. Hvor mange linjer sætter du ind? Hvor lange er de enkelte linjer? Hvor kopierer du fra, en TStringList?
Avatar billede kroning Nybegynder
16. januar 2008 - 01:46 #3
Der indsættes ca. 33000 linier som nok i gennemsnit er 50 tegn lange. De kommer fra en database (MySQL) men når de skal indsættes er det fra en TStringList men jeg har prøvet lidt forskellig og resultatet er det samme, det er selve indsættelsen af data i boxen der tager tiden, f.eks. tager dette næsten den samme tid (8 sekunder):

ComboBoxEx1.Items.BeginUpdate;
  for i:=1 to 33000 do
    ComboBoxEx1.Items.Add('jwsos  jde je doeo d jfj jowij jd woijoijdoije dwef efe');
ComboBoxEx1.Items.EndUpdate;

Det er en lang række navne der indsættes og det virker på den måde at når brugeren begynder at indtaste et navn så foreslår TComboBoxEx de navne der er passer til det indtastede således at man ikke behøver at indtaste hele navnet. Jeg kan ikke komme på andre muligheder en TComboBoxEx til at løse denne opgave.
Avatar billede kroning Nybegynder
16. januar 2008 - 05:57 #4
Jeg kan oplyse at det kun tager 63 milisekunder at putte de samme 33000 strenge ind i en TStringList;
Avatar billede hrc Mester
16. januar 2008 - 09:03 #5
Hvad med en TEdit hvor du laver opslaget i en bagvedliggende TStringList. Jeg har denne løsning ved mine postnumre.

procedure TfrmePostBy.ePostByKeyPress(Sender: TObject; var Key: Char);
var
  Edit : TEdit;
begin
  if Key >= #32 then
    if not (char(CharUpper(PChar(Key))) in ['A'..'Z','Æ','Ø','Å',#32]) then
      Key := #0;

  if ord(Key) = VK_BACK then
  begin
    Edit := Sender as TEdit;
    if Edit.SelLength > 0 then
    begin
      if Edit.SelStart > 0 then
        Edit.SelStart := Edit.SelStart - 1;
      Edit.SelLength := MaxInt;
      if Edit.SelStart = 0 then
      begin
        Edit.Text := '';
        ePostNr.Text := '';
        Key := #0;
      end;
    end;
  end;
end;

procedure TfrmePostBy.ePostNrChange(Sender: TObject);
var
  Index : integer;
  SelStart : integer;
begin
  if fSkip then // Mutex da jeg ellers trigger events i den anden TEdit
    exit;

  SelStart := ePostNr.SelStart;

  fPostData := nil;
  Index := DM.PostList.IndexByPostnrNearest(ePostNr.Text);
  if Index >= 0 then
    fPostData := DM.PostList[Index];

  if assigned(fPostData) then
  begin
    fSkip := true;
    try
      ePostNr.Text := fPostData.PostNr;
      ePostNr.SelStart := SelStart;
      ePostNr.SelLength := MaxInt;
      ePostBy.Text := fPostData.PostBy;
    finally
      fSkip := false;
    end;
  end;
end;

procedure TfrmePostBy.ePostNrEnter(Sender: TObject);
begin
  DM.PostList.SortByPostNr;
end;
Avatar billede kroning Nybegynder
16. januar 2008 - 11:07 #6
Brugerne vil ikke undvære den drop down liste der kommer frem efterhånden som man indtaster et navn så TEdit løsningen kan desværre ikke bruges her.
Avatar billede hrc Mester
16. januar 2008 - 12:35 #7
Bruger du assign() til at kopiere fra stringlisten? Må formode at den metode er den hurtigste...
Avatar billede kroning Nybegynder
16. januar 2008 - 15:53 #8
Jeg tror jeg har prøvet alle muligheder, .text:=, .Commatext:=, assign osv.
Måske skulle man prøve at lave en selv, eller også må folk købe en hurtigere computer hvis de syntes det går for langsom.
Men en hjemmelavet en burde jo kunne laves så det kun tager de 63 milisekunder i stedet for 6-8 sekunder, strengene jeg henter fra MySQL er sorteret i alfabetisk orden. Eller det kan faktisk laves så det tager 0 sekunder ved bare at linke til den TStringList der allerede indeholder alle strengene.
Avatar billede hrc Mester
17. januar 2008 - 14:31 #9
Hvad med at skjule at du fylder i listen vha. en tråd? Det er ikke det kønneste men det kan jo være brugerne ikke er nået ned til comboen inden de 8 sekunder.

Hvis du skal linke til den bagvedliggende liste må du vist i gang med at nedarve en TComboBox. Det kan være der er nogle "protected" attributter og metoder du kan bruge.
Avatar billede kroning Nybegynder
18. januar 2008 - 20:14 #10
Jeg tror jeg vil prøve at arbejde lidt med at fylde listen vha. en tråd.
Smid et svar.
Avatar billede hrc Mester
18. januar 2008 - 22:50 #11
ok.
Avatar billede Ny bruger Nybegynder

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.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester