2009-03-20 21 views
6

Mam dość złożoną i dużą aplikację, która ładuje i ładuje dane. Czy istnieje szybki sposób dodawania elementów do ComboBox, które nie trwają tak długo? Na moim P3 3.2ghz poniższy fragment zajmuje zaledwie sekundę, by dodać około 32 000 elementów. (MasterCIList to StringList o łańcuchach zwykle o długości 20-30 bajtów).Delphi Dodawanie elementów do prędkości ComboBox

with LookupComboBox do 
begin 
    Items.BeginUpdate; 
    Items.Clear; 
    for i := 0 to MasterCIList.Count - 1 do 
    Items.Add(MasterCIList[i]); 
    Items.EndUpdate; 
end; 

wiercenia w głąb VCL, wydaje się, że w TComboBoxStrings.Add, istnieje wezwanie do Wynik: = SendMessage (ComboBox.Handle, CB_ADDSTRING, 0 Longint (PChar (Y)));

Zgaduję, że to naprawdę zajmuje czas (w porządku, wiem, że to jest). Czy istnieje inny sposób na wypełnienie przedmiotów, które jest szybsze? Czy są dostępne wszystkie skrzynki combox wysokiej prędkości? Mam komponenty TMS, ale wydają się być rozszerzeniami TComboBox.

Na przykład mam PlusMemo, które wydaje się być całkowitym przerobem TMemo. Mogę z łatwością dodać milion linii w ciągu sekundy do PlusMemo. TMemo, nie sądzę.

Dziękuję bardzo za poświęcony czas!

+4

Nie jest to odpowiedź, ale dlaczego miałbyś chcieć 32 000 przedmiotów w pudełku? To okropny sposób przechowywania tak dużej ilości danych. –

Odpowiedz

1

być może cmb.Items.Assign (myStringList) pomoże.

Oto szalony pomysł: nie próbowałem go, ale możesz sprawdzić, czy istnieje sposób na wirtualne załadowanie combobox poprzez ustawienie liczby elementów, a następnie rysunek właściciela. przepraszam za ten zwariowany pomysł, ale myślę, że słyszałem o tym, że jest to jakoś dostępne. nieistotne: tak się dzieje w Palm OS ... gdzie szybszym sposobem załadowania comboboxa jest nie załadowanie wszystkiego ... ;-)

Brak odpowiedzi, ale dlaczego chciałbyś 32 000 przedmiotów w pudełku złożonym? To okropny sposób przechowywania tak dużej ilości danych.

zgadzam się; to jest zła praktyka ...

17

Przepraszam, jeśli jestem uciążliwy, ale wątpię, czy TComboBox z 32 000 pozycji jest nawet zdatny do użytku "- powiedziałbym, że jest powód, dlaczego jest wolny: nigdy nie miało to zrobić :)

Czy istnieje możliwość filtrowania danych i ładowania tylko podzestawu? Aby być bardziej konkretnym, w konkretnej aplikacji bazodanowej, nad którą pracowałem, użytkownik może wyszukać osobę. Pozwoliliśmy użytkownikowi wpisać co najmniej 3 lub 4 znaki nazwy, a dopiero potem zaczynamy zwracać wyniki w polu listy. Znacznie zwiększyło to użyteczność formularza wyszukiwania, a także znacznie przyspieszyło cały proces.

Czy byłbyś w stanie zastosować podobne podejście?

Albo, z zupełnie innej strony, być może mógłbyś rzucić okiem na komponent VirtualTreeView --- albo do bezpośredniego użycia, albo do inspiracji.

+0

To dobra wskazówka. Może dodać ciągi w module obsługi OnDropDown, filtrowane, aby rozpocząć od znaków, które zostały już wprowadzone. W ten sposób użytkownik ma wpływ na opóźnienie. W każdym razie lista odnośników z 32000 pozycji jest bezużyteczna, nawet jeśli jest natychmiast wypełniona. – mghie

3

Zgadzam się, że 32K pozycji jest śmieszna kwota mieć w combobox ... Mając na uwadze powyższe, można spróbować dodać elementy do TStringList a potem użyć kombinacji Rozpocznij/EndUpdate i AddStrings:

SL := TStringList.Create; 
try 
    // Add your items to the stringlist 
    ComboBox.Items.BeginUpdate; 
    try 
    ComboBox.Items.AddStrings(YourStringList); 
    finally 
    ComboBox.Items.EndUpdate; 
    end; 
finally 
    SL.Free; 
end; 

Kod się kompiluje, ale nie przetestowałem go dalej; Nigdy nie czułem potrzeby dodawania więcej niż kilkudziesięciu przedmiotów do combobox lub listbox. Jeśli potrzebnych będzie więcej elementów, znajdę sposób filtrowania przed zapełnieniem listy, aby było mniej elementów.

Po prostu z czystej ciekawości, jak można się spodziewać, że użytkownik przejdzie przez tak wiele elementów, aby podjąć decyzję?

1

To znowu ja. Dodaję 32 000 przedmiotów, bo muszę. To jedna z wielu kontrolek w mojej aplikacji, która ma "wiele" elementów. Potrzebuję wielu przedmiotów. Działa dobrze wyglądając. Idealnie w rzeczywistości. Po prostu staram się zoptymalizować rzeczy. Użytkownicy uważają, że wszystko jest w porządku, ponieważ są w logicznej kolejności.

Wszystko, co do tej pory wydawałem się z Assign i AddStrings jest to, że ostatecznie trafiają do Add przy wywołaniu SendMessage. Więc dalej będę wyglądać.

Dzięki za opinię.

+1

Po pierwsze, opublikowanie "odpowiedzi" w ten sposób jest błędne. Edytuj swój oryginalny wpis. Po drugie, programowałem od ponad 20 lat, aplikacje Win dla 15+, zrobiłem kilka wyjątkowo skomplikowanych aplikacji i nigdy nie znalazłem potrzeby na nawet 1K elementów w comboboxie. Ale życzę powodzenia (i użytkownikom Twojej aplikacji). –

+0

Zgadzam się z Kenem. Aby było jasne - dobrze jest opublikować odpowiedź, jeśli jest to naprawdę odpowiedź na twoje pytanie. Jeśli masz komentarz, po prostu edytuj swoje pytanie. – Argalatyr

0

Być może można użyć silnika bazy danych na zapleczu i użyć komponentu obsługującego dane. Wtedy rzeczy będą znacznie szybsze i użyteczne. Być może, jeśli spróbujesz opisać, co spróbujesz osiągnąć, pomożemy ci dalej. W każdym razie twój projekt interfejsu użytkownika to, powiedzmy, nieparzysty. A do tego być może Embarcadero forums pomoże ci lepiej.

0

Wdrażam to w inny sposób. Najpierw usunąłem formant combobox i przejąłem kontrolę pola tekstowego i przydzieliłem autouzupełnianie do niestandardowego źródła, w którym niestandardowy zbiór łańcuchów źródłowych to 32k items. Otrzymuję wybraną wartość z nowego zapytania dotyczącego sprawdzania poprawności kontroli.

Może więc zastąpić funkcję combobox. Głównie o 32k pozycji ludzi nie przewijać ale zachować wejściem naciśnięcia klawiszy i przechwycony przez nasz zwyczaj auto kompletne źródło ..

1

korzystanie backgroundworker dodawania MasterCIList items.after kompletne elementy dodając używać tylko AddStrings.

procedure TForm2.BackgroundWorker1Work(Worker: TBackgroundWorker); 
var 
    I: Integer; 
begin 
    MasterCIList.BeginUpdate; 
    try 
    MasterCIList.Capacity := 32 * 1024; // if derminate count of items 
    for I := 1 to 32 * 1024 do 
    begin 
     MasterCIList.Add(IntToStr(I)); 
     { if need progess } 
     if I mod 300 = 0 then 
     Worker.ReportProgress((I * 100) div MasterCIList.Capacity); 
     { if need cancelable } 
     if (I mod 100 = 0) and Worker.CancellationPending then 
     Break; 

    end; 

    finally 
    MasterCIList.EndUpdate; 
    end; 

end; 

procedure TForm2.BackgroundWorker1WorkComplete(Worker: TBackgroundWorker; 
    Cancelled: Boolean); 
begin 

    LookupComboBox.Items.AddStrings(MasterCIList); 


// AddStrings use beginupdate..endupdate in itself 

end; 
2
var 
    Buffer: TStringList; 
begin 
    Buffer := TStringList.Create; 

    try 
    // --> Add items to Buffer here <-- 

    ComboBox.Items := Buffer; 
    finally 
    FreeAndNil(Buffer); 
    end; 
end; 

To najszybszy sposób odkryliśmy zaktualizować kontrolę wzrokową.

VCL powoduje, że BeginUpdate, Clear i EndUpdate wewnętrznie.

Jeśli mi nie wierzysz, zrób to.

Powiązane problemy