2009-03-20 3 views
6

Tôi có một ứng dụng khá phức tạp và lớn tay tải và tải dữ liệu. Có cách nào nhanh chóng để thêm các mục vào ComboBox không mất quá nhiều thời gian? Trên P3 3.2ghz của tôi, đoạn mã sau chỉ mất một giây để thêm khoảng 32.000 mục. (MasterCIList là một StringList với các chuỗi thường dài 20 - 30 byte).Delphi Thêm các mục vào tốc độ ComboBox

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

Khoan xuống VCL, dường như trong TComboBoxStrings.Add, có một cuộc gọi đến Result: = SendMessage (ComboBox.Handle, CB_ADDSTRING, 0, Longint (PChar (S)));

Tôi đoán điều này thực sự đang chiếm thời gian (okay, tôi biết là vậy). Có cách nào khác để điền các mục nhanh hơn không? Có hộp combox tốc độ cao nào không? Tôi có các thành phần TMS nhưng chúng dường như là phần mở rộng của TComboBox.

Ví dụ, tôi có PlusMemo mà có vẻ là tổng số viết lại của TMemo. Tôi có thể dễ dàng thêm một triệu dòng trong một giây để một PlusMemo. Một TMemo, tôi không nghĩ vậy.

Cảm ơn bạn rất nhiều vì đã dành thời gian!

+4

Không phải là câu trả lời, nhưng tại sao bạn muốn 32.000 mục trong hộp tổ hợp? Đó là một cách khủng khiếp để lưu trữ nhiều dữ liệu. –

Trả lời

1

có lẽ cmb.Items.Assign (myStringList) sẽ trợ giúp.

đây là một ý tưởng hoang dã: tôi chưa thử nhưng bạn có thể kiểm tra xem có cách nào tải hầu hết các combobox bằng cách đặt số lượng mục và sau đó vẽ chủ sở hữu. xin vui lòng tha thứ cho ý tưởng điên rồ này nhưng tôi nghĩ rằng tôi đã nghe nói về điều này đang có sẵn bằng cách nào đó. không liên quan: đây là cách nó được thực hiện trong Palm OS ... nơi cách tải nhanh hơn combobox là không tải tất cả ... ;-)

Không phải câu trả lời, nhưng tại sao bạn muốn 32.000 mục trong hộp tổ hợp? Đó là một cách khủng khiếp để lưu trữ nhiều dữ liệu.

tôi đồng ý; đó là một thực tế xấu ...

17

Xin lỗi nếu tôi là một mối phiền toái, nhưng tôi nghi ngờ một TComboBox với 32.000 mục thậm chí từ xa '' có thể sử dụng '' --- tôi muốn nói có lý do tại sao nó chậm: không bao giờ có ý định làm điều này :)

Có khả năng lọc dữ liệu và chỉ tải một tập hợp con không? Để cụ thể hơn, trong một ứng dụng cơ sở dữ liệu cụ thể mà tôi đã làm việc, người dùng có thể tìm kiếm một người. Chúng tôi cho phép người dùng nhập ít nhất 3 hoặc 4 ký tự của tên và chỉ sau đó bắt đầu trả lại kết quả trong hộp danh sách. Điều này đã làm tăng khả năng sử dụng của biểu mẫu tìm kiếm, cũng tăng tốc đáng kể toàn bộ quá trình.

Bạn có thể thực hiện theo một cách tiếp cận tương tự không?

Hoặc, trên một cách hoàn toàn khác, có lẽ bạn có thể xem qua thành phần VirtualTreeView --- hoặc để sử dụng trực tiếp hoặc cho cảm hứng.

+0

Đó là một mẹo hay. Có thể thêm các chuỗi trong trình xử lý OnDropDown, được lọc để bắt đầu với các ký tự đã được nhập. Bằng cách đó, người dùng có ảnh hưởng đến sự chậm trễ. Trong mọi trường hợp, một danh sách tra cứu với 32.000 mục không sử dụng được, ngay cả khi được điền ngay lập tức. – mghie

3

Tôi đồng ý rằng 32K mục là một số tiền vô lý để có trong một combobox ... Điều đó đang được nói, bạn có thể thử thêm các mục vào một TStringList đầu tiên và sau đó sử dụng một sự kết hợp của Begin/EndUpdate và 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; 

Mã biên dịch, nhưng tôi đã không kiểm tra thêm nữa; Tôi chưa bao giờ cảm thấy cần phải thêm nhiều hơn một vài chục mục vào một combobox hoặc listbox. Nếu cần thêm bất kỳ mục nào khác, tôi tìm cách lọc trước khi điền danh sách để có ít mục hơn.

Chỉ vì tò mò, bạn kỳ vọng người dùng sắp xếp bao nhiêu mục để đưa ra quyết định?

1

Đó là tôi một lần nữa. Tôi đang thêm 32.000 mặt hàng do tôi cần. Đó là một trong nhiều điều khiển trong ứng dụng của tôi có "rất nhiều" mục. Tôi cần phải có nhiều mặt hàng. Nó hoạt động tốt chỉ tìm kiếm những thứ lên. Hoàn hảo trong thực tế. Tôi chỉ đang cố gắng tối ưu hóa mọi thứ. Những người sử dụng tìm thấy những điều tốt đẹp vì họ đang ở trong một trật tự hợp lý nhất định.

Mọi thứ tôi có vẻ cho đến nay với Chỉ định và AddStrings là cuối cùng chúng sẽ kết thúc trong Thêm bằng cuộc gọi SendMessage. Vì vậy, tôi sẽ tiếp tục tìm kiếm.

Cảm ơn phản hồi.

+1

Trước tiên, đăng một "câu trả lời" như thế này là sai. Chỉnh sửa bài đăng gốc của bạn. Thứ hai, một lần nữa, tôi đã lập trình được hơn 20 năm, ứng dụng Win cho 15+, đã thực hiện một số ứng dụng cực kỳ phức tạp và chưa bao giờ tìm thấy nhu cầu cho các mục ngay cả 1K trong combobox. Nhưng chúc bạn may mắn (và người dùng ứng dụng của bạn). –

+0

Đồng ý với Ken. Để được rõ ràng - nó là tốt để gửi một câu trả lời nếu nó thực sự là một câu trả lời cho câu hỏi của bạn. Nếu bạn có nhận xét thì chỉ cần chỉnh sửa câu hỏi của bạn. – Argalatyr

0

Có lẽ bạn có thể sử dụng công cụ cơ sở dữ liệu trong phần cuối và sử dụng thành phần nhận biết dữ liệu. Sau đó, mọi thứ sẽ nhanh hơn nhiều có thể sử dụng được. Có lẽ nếu bạn cố gắng mô tả những gì bạn cố gắng hoàn thành, chúng tôi sẽ giúp bạn thêm. Trong mọi trường hợp, thiết kế giao diện người dùng của bạn, giả sử, lẻ. Và điều này có lẽ là Embarcadero forums sẽ giúp bạn tốt hơn.

0

Tôi triển khai tính năng này theo cách khác. Đầu tiên tôi gỡ bỏ điều khiển combobox và kiểm soát hộp văn bản và gán nó tự động hoàn thành vào nguồn tùy chỉnh nơi tập hợp chuỗi nguồn tùy chỉnh là 32k items.I nhận giá trị đã chọn từ truy vấn mới về kiểm soát xác thực.

Vì vậy, nó có thể thay thế chức năng combobox. Chủ yếu là về 32k mục người không cuộn nhưng họ tiếp tục nhập nét chính và được bắt nguồn bởi nguồn tự động hoàn chỉnh tùy chỉnh của chúng tôi ..

1

sử dụng backgroundworker để thêm mục MasterCIList.au khi hoàn thành việc thêm mục chỉ sử dụng 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; 

Đây là cách nhanh nhất chúng tôi đã tìm thấy để cập nhật một điều khiển trực quan.

VCL sẽ BeginUpdate, Clear và EndUpdate nội bộ.

Nếu bạn không tin tôi, hãy chỉnh sửa.