smilefreeware Δημοσ. 4 Σεπτεμβρίου 2010 Δημοσ. 4 Σεπτεμβρίου 2010 Ο γρηγορότερος τρόπος που έχω βρει για να προσθέσω text items σε ListBox είναι ο παρακάτω : LB: TListBox; AR : ARRAY OF STRING procedure LIST_ADD; VAR N:INTEGER; S:STRING; MS:TMEMORYSTREAM; BEGIN S:=''; FOR N:=1 TO ITEMS DO S:=S+AR[N]+#10; MS:=TMEMORYSTREAM.Create; MS.Position:=0; MS.WriteBuffer(S[1],LENGTH(S)); MS.Position:=0; LB.Items.LoadFromStream(MS); MS.Free; END; Με λίγα λόγια αντι να κάνω add ένα-ένα τα items, τα βάζω όλα μαζί σε ένα string μαζί με αλλαγή σειράς (#10) και φορτώνω το ListBox με LoadFromStream. Υπάρχει γρηγορότερος τρόπος ? (Βάζω λίστα με 130.000 items περίπου και αργεί)
bnvdarklord Δημοσ. 4 Σεπτεμβρίου 2010 Δημοσ. 4 Σεπτεμβρίου 2010 Νομίζω μπορείς να πεις ListBox.Items.Add(string) για να προσθεσεις ενα αντικειμενο.
smilefreeware Δημοσ. 5 Σεπτεμβρίου 2010 Μέλος Δημοσ. 5 Σεπτεμβρίου 2010 Νομίζω μπορείς να πειςListBox.Items.Add(string) για να προσθεσεις ενα αντικειμενο. Αυτός είναι ο πιο αργός τρόπος. Καλύτερος είναι αυτός που γράφεις αλλά με LB.Items.BeginUpdate πριν αρχίσεις τα add και στο τέλος LB.Items.EndUpdate Και τέλος πιο γρήγορος αυτός που έγραψα εγώ. Τα εχω χρονομετρήση πολλές φορές. Το θέμα είναι κάτι γρηγορότερο ?
NewProject Δημοσ. 5 Σεπτεμβρίου 2010 Δημοσ. 5 Σεπτεμβρίου 2010 (Βάζω λίστα με 130.000 items περίπου και αργεί) περιεργο θα'ταν το αντιθετο
taazz Δημοσ. 5 Σεπτεμβρίου 2010 Δημοσ. 5 Σεπτεμβρίου 2010 Υπάρχει γρηγορότερος τρόπος ? (Βάζω λίστα με 130.000 items περίπου και αργεί) Τα items από που έρχονται πως φορτώνονται στην μνήμη? Έχεις προσπαθήσει αντί να χρησιμοποιήσεις ένα string για να τα μαζέψεις να χρησιμοποιήσεις ένα TstringStream ώστε να αποφύγεις το βήμα αποθήκευσης στην μνήμη? Eχω την εντύπωση ότι το πιο χρονοβόρο είναι το concat εάν μπορέσεις να το απφύγεις με κάποιο τρόπο και τα φορτώσεις κατευθείαν στον listbox θα έχει την μεγαλήτερη δυνατή ταχύτητα. φυσικά χωρίς να γνωρίζω κάτι παραπάνω για την αρχική μορφή των items και γενικότερα την όλη διαδικασία δεν μπορώ να βοηθησω περισότερο αλλά για ρίξε μια ματιά στo virtual listbox. Σε αυτή την μορφή το Listbox δεν καταχωρεί τα δεδομένα εσωτερικά στην μνήμη του του λες μόνο πόσα δεδομένα έχεις και πρέπει να γράψεις των κώδικα για την εμφάνιση μια γραμμής στην οθόνη οταν σου ζητήται. Ένα παράδειγμα μπορείς να βρεις στο http://delphicikk.atw.hu/listaz.php?id=2471&oldal=52. Εάν χρειάζεσαι περισότερη βοήθεια θα μπορούσα να σου φτιαξω ένα demo απλά βαριέμαι να φτιάχνω την λίστα με 130.000 items οπότε το testing πέφτει σε εσένα.
Directx Δημοσ. 5 Σεπτεμβρίου 2010 Δημοσ. 5 Σεπτεμβρίου 2010 Η λύση στο πρόβλημα σου όπως ελέχθη δίδεται άνετα με την ενεργοποίηση του Virtual mode για το TListBox σου. Τούτο προϋποθέτει τρία πράγματα, αφενός θα πρέπει να ορίσεις από τον Object Inspector το Style του component σε lbVirtual και αφετέρου θα πρέπει να παράσχεις δυο event handlers, το OnData, προαιρετικά το OnDataFind και οπωσδήποτε τον αριθμό των προς προβολή στοιχείων στο TListBox.Count property. Η όλη φιλοσοφία του TListBox (και όχι μόνο..) Virtual mode είναι η καταχώρηση – φόρτωμα των περιεχομένων του control αντί στο ίδιο, σε ένα προσωπικό, δικό μας δηλαδή, Array list επιστρέφοντας στο TListBox μόνο το περιεχόμενο που μας ζητά κάθε φορά μέσο του OnData και OnDataFind. Ο αριθμός των στοιχείων του Array πρέπει (υποχρεωτικά) να δηλωθεί στο TListBox μέσο του .Count property ώστε το component να γνωρίζει τον αριθμό των προς προβολή διαθέσιμων στοιχείων (αν αμελήσεις τον ορισμό του TListBox.Count όντας σε lbVirtual style το TListBox θα μένει πάντα κενό!). Καθώς δεν ασχολούμαι με Delphi αλλά C++ Builder, και δεδομένου ότι ο δεύτερος βασίζεται στην Delphi VCL (ουσιαστικά πρόκειται για την εκδοχή της Delphi σε C++) ακολουθεί ένα υπόδειγμα χρήσης των OnData & OnDataFind. Προτού συνεχίσω, υποθέτω ότι τα προς παρουσίαση στο TListBox δεδομένα έχουν αποθηκευτεί σε ένα STL vector container (vector<UnicodeString> vectItem) και ότι έχουν ήδη εισαχθεί 130.000 UnicodeString/Items στο vector αυτό με κάποιον κώδικα, πχ: > // Fill vectItem with 130.000 UnicodeStrings.. Cursor = crHourGlass; vectItem.clear(); for(int nCount = 0; nCount < 130000; nCount++) vectItem.push_back(nCount + 1); /* * While ListBox style = lbVirtual, enumerate ListBox1 with the * number of available items (SOS). */ ListBox1->Count = vectItem.size(); Cursor = crDefault; Το OnData event έχει μορφή: ListBox1Data(TWinControl *Control, int Index, UnicodeString &Data) Όπου Control είναι το TListBox από το οποίο καλείται (μπορείς να το λάβεις με cast του TWinControl* σε TListBox*). Index η θέση του Item που σου ζητά να επιστρέψεις από το προσωπικό σου Array το TListBox. Και Data το περιεχόμενο της θέσης του Array σου. Σε C++ Builder, αυτό το event μπορεί να γραφθεί έτσι: > Data = vectItem.at(Index); Το OnDataFind event έχει μορφή: Int ListBox1DataFind(TWinControl *Control, UnicodeString FindString) Το Control όπως και προηγουμένως δηλώνει το TListBox από το οποίο καλείται. Το FindString είναι το UnicodeString που αναζητεί ο χρήστης. Εσύ πρέπει να επιστρέψεις την θέση του FindString από το προσωπικό σου Array ή αν το UnicodeString δεν υπάρχει, μηδέν (0). Σε C++ Builder, αυτό το event μπορεί να γραφθεί έτσι: > vector<UnicodeString>::iterator iterStr = find(vectItem.begin(), vectItem.end(), FindString); return iterStr != vectItem.end() ? iterStr - vectItem.begin() : 0; * Προς χάριν απλότητας το find διαχωρίζει μεταξύ μικρών & κεφαλαίων. Καλή συνέχεια!
smilefreeware Δημοσ. 5 Σεπτεμβρίου 2010 Μέλος Δημοσ. 5 Σεπτεμβρίου 2010 ....... Κανονικά αυτό το S:=S+... θα έπρεπε να είναι αργό. Είναι όμως τάχιστο. Ισως δεν ήμουν σαφής αλλά ο χρόνος ο πολύς είναι στη μεταφορά του string μέσα στο listbox. Για να καταλάβετε 1 με 2 δέκατα του δευτερολέπτου θέλει να δημιουργηθεί το string και 2+ sec να μπει στο listbox. Σε Ε840 cpu.(στα 3, διπύρηνο) με 130.000 items των 10-30 χαρακτήρων. Εάν χρειάζεσαι περισότερη βοήθεια θα μπορούσα να σου φτιαξω ένα demo απλά βαριέμαι να φτιάχνω την λίστα με 130.000 items οπότε το testing πέφτει σε εσένα. Με randome φτιάχνεις γρήγορα παράδειγμα. ...αλλά για ρίξε μια ματιά στo virtual listbox...... Αυτό ήταν τελικά η λύση. Ο χρόνος έγινε μηδέν επειδή δεν μεταφέρει τίποτα. Thanks taazz. ---------- Προσθήκη στις 10:44 ---------- Προηγούμενο μήνυμα στις 10:34 ---------- @Directx Thanks, τα lbVirtual , TListBox.Count , ListBox1Data έδωσαν οριστική λύση. Το ListBox1DataFind αν κατάλαβα καλά τι κάνει δεν με ενδιαφέρει γιατί γιατί κάνω μόνος μου παιχνίδι με τα strings. Πχ. για find χρησιμοποιώ μια ρουτίνα που, αφού μετατρέψει τα Ελληνικά σε γράμματα χωρίς τόνους , διαλυτικά κλπ και σε κεφαλαία, μετά ψάχνω. Οπότε αποφεύγω πολλά προβλήματα. Μη σας φαίνεται περίεργο, για 130.000 items το ψάξιμο είναι πολύ γρήγορο , σχεδόν ακαριαίο. (Δεν κρατάω 2 πίνακες, ένα κανονικό και ένα με μετατροπή. Τη στιγμή του ψαξίματος κάνω τις μετατροπές)
Directx Δημοσ. 5 Σεπτεμβρίου 2010 Δημοσ. 5 Σεπτεμβρίου 2010 [/color] Το ListBox1DataFind αν κατάλαβα καλά τι κάνει δεν με ενδιαφέρει γιατί γιατί κάνω μόνος μου παιχνίδι με τα strings.[..] Επιτρέπει στον χρήστη να εντοπίσει άμεσα ένα Item πληκτρολογώντας σταδιακά την ονομασία του στο focused TListBox, παλαιότερα δεν το προσέφερα ούτε εγώ αλλά μετά, καθώς θεωρώ ότι βελτιώνει την ευχρηστία του Interface το παρέχω πάντα.
smilefreeware Δημοσ. 5 Σεπτεμβρίου 2010 Μέλος Δημοσ. 5 Σεπτεμβρίου 2010 @Directx λάθος κατάλαβα για το ListBox1DataFind. Αυτό που γράφεις είναι χρήσιμο, θα το κοιτάξω. (παιχνίδια του μυαλού) Από παλιά είχα δει αυτό το lbVirtual , αλλά στο μυαλό μου είχε περάσει η έννοια του visual δηλ κάτι με φωτογραφίες ή κάτι τέτοιο και το θεωρούσα ακόμη πιο αργό. Οπότε το απ΄έφευγα. Είχα πάθει κάτι σαν εξετάσεις που δίνεις μάθημα και κάνεις λάθος πρόσθεση πχ 5+6=13 , η πλάκα είναι ότι και δεύτερη και τρίτη φορά που κάνεις πρόσθεση πάλι 13 λες.
smilefreeware Δημοσ. 6 Σεπτεμβρίου 2010 Μέλος Δημοσ. 6 Σεπτεμβρίου 2010 Τελικά ασχολήθηκα με το ListBox1DataFind και μου έκανε το εξής. Οταν πάταγα πλήκτρο αναβόσβηνε το item αρκετή ώρα και μετά σταμάταγε στο σωστό σημείο. Οταν το focus το έβαζα αλλού , δούλευε ωραία αλλά ήμουν σε άλλο Control, οπότε πρόβλημα. Τελικά το έφτιαξα με OnKeyPress και δουλεύει άψογα. Εκανα test και είναι πολύ γρήγορο για 130.000 Items. Βάζω και τη ρουτίνα που μεταττρέπει γρήγορα σε γράμματα χωρίς τόνους , διαλυτικά κλπ και σε κεφαλαία. CONST PFLATCHAR:ARRAY[0..255] OF CHAR = (#0,#1,#2,#3,#4,#5,#6,#7,#8,#9,#10,#11,#12,#13,#14,#15,#16,#17,#18,#19,#20,#21,#22,#23,#24,#25, #26,#27,#28,#29,#30,#31,#32,#33,#34,#35,#36,#37,#38,#39,#40,#41,#42,#43,#44,#45,#46,#47,#48, #49,#50,#51,#52,#53,#54,#55,#56,#57,#58,#59,#60,#61,#62,#63,#64,#65,#66,#67,#68,#69,#70,#71, #72,#73,#74,#75,#76,#77,#78,#79,#80,#81,#82,#83,#84,#85,#86,#87,#88,#89,#90,#91,#92,#93,#94, #95,#96,#65,#66,#67,#68,#69,#70,#71,#72,#73,#74,#75,#76,#77,#78,#79,#80,#81,#82,#83,#84,#85, #86,#87,#88,#89,#90,#123,#124,#125,#126,#127,#128,#129,#130,#131,#132,#133,#134,#135,#136,#137, #138,#139,#140,#141,#142,#143,#144,#145,#146,#147,#148,#149,#150,#151,#152,#153,#154,#155,#156, #157,#158,#159,#160,#161,#193,#163,#164,#165,#166,#167,#168,#169,#170,#171,#172,#173,#174,#175, #176,#177,#178,#179,#180,#181,#182,#183,#197,#199,#201,#187,#207,#189,#213,#217,#192,#193,#194, #195,#196,#197,#198,#199,#200,#201,#202,#203,#204,#205,#206,#207,#208,#209,#210,#211,#212,#213, #214,#215,#216,#217,#201,#213,#193,#197,#199,#201,#224,#193,#194,#195,#196,#197,#198,#199,#200, #201,#202,#203,#204,#205,#206,#207,#208,#209,#211,#211,#212,#213,#214,#215,#216,#217,#201,#213, #207,#213,#217,#255); VAR LB_FIND : STRING; LB_TIME : INTEGER; LB : TListBox; LBA : TSTRINGLIST; //ΤΑ DATA ΓΙΑ ΤΟ ListBox ............... LB_TIME:=0; LB_FIND:=''; //-------------------------------------------------------------------- FUNCTION PTIMER:INTEGER; VAR TT:TTimeStamp; BEGIN TT:=DateTimeToTimeStamp(Time); RESULT:=TT.Time; END; //-------------------------------------------------------------------- FUNCTION PFLATSTR(S:STRING):STRING; //ΜΕΤΑΤΡΕΠΕΙ ΤΟ STRING ΣΕ ΚΕΦΑΛΑΙΑ ΚΑΙ ΧΩΡΙΣ ΤΟΝΟΥΣ-ΔΙΑΛΥΤΙΚΑ VAR N:INTEGER; BEGIN FOR N:=1 TO LENGTH(S) DO S[N]:=PFLATCHAR[ORD(S[N])]; RESULT:=S; END; //-------------------------------------------------------------------- procedure TForm1.LBKeyPress(Sender: TObject; var Key: Char); LABEL LAB; VAR S,Q:STRING; X,L,N:INTEGER; begin X:=PTIMER; S:=' '; S[1]:=Key; //ΤΟ 1300 ΕΙΝΑΙ 1300 msec Ο ΧΡΟΝΟΣ ΜΕΤΑΞΥ ΚΤΥΠΗΜΑΤΟΣ ΤΩΝ ΠΛΗΚΤΡΩΝ IF X-LB_TIME<1300 THEN LB_FIND:=LB_FIND+S ELSE LB_FIND:=S; LB_TIME:=X; X:=LB.ItemIndex; LB.Selected[X]:=FALSE; //Η ΘΕΣΗ ΣΤΟ ListBox S:=PFLATSTR(LB_FIND); L:=LENGTH(S); //ΨΑΞΙΜΟ ΑΠΟ ΤΗΝ ΕΠΟΜΕΝΗ ΘΕΣΗ ΚΑΙ ΠΡΟΣ ΤΑ ΚΑΤΩ FOR N:=X+1 TO LBA.Count-1 DO BEGIN Q:=COPY(LBA[N],1,L); IF S=PFLATSTR(Q) THEN BEGIN X:=N; GOTO LAB; END; END; //ΑΝ ΔΕΝ ΒΡΕΘΕΙ ΨΑΞΙΜΟ ΑΠΟ ΤΗΝ ΑΡΧΗ FOR N:=0 TO X-1 DO BEGIN Q:=COPY(LBA[N],1,L); IF S=PFLATSTR(Q) THEN BEGIN X:=N; GOTO LAB; END; END; // ΑΝ ΔΕΝ ΒΡΕΘΕΙ ΜΕΝΕΙ ΣΤΗΝ ΙΔΙΑ ΘΕΣΗ LAB: LB.ItemIndex:=X; LB.Selected[X]:=TRUE; end; //--------------------------------------------------------------------
Evgenios1 Δημοσ. 6 Σεπτεμβρίου 2010 Δημοσ. 6 Σεπτεμβρίου 2010 περιεργο θα'ταν το αντιθετο Δεν ειναι πολλα. 10-20 mb θα'ναι. Btw πως λεγετε αυτο το framework;
smilefreeware Δημοσ. 6 Σεπτεμβρίου 2010 Μέλος Δημοσ. 6 Σεπτεμβρίου 2010 Δεν ειναι πολλα. 10-20 mb θα'ναι. Btw πως λεγετε αυτο το framework; Επειδή θέματα ταχύτηττας τα ψάχνω πολύ, αυτό που παίζει κυρίαρχο ρόλο είναι η ποσότητα των items και όχι το μέγεθος. Στο να τα βάλεις στο listbox και στο ψάξιμο. Ειδικά στο ψάξιμο αφού ψάχνεις τα string από την αρχή με λίγους χαρακτήρες δεν σε ενδιαφέρει πόσο μήκος έχει το string που ψάχνεις αλλά το πόσα string ψάχνεις. Αν ενδιαφέρεστε για συγκεκριμμένα νούμερα : Το αργό αρχείο είναι 13.700.724 επειδή έχει 130.000 items Ολα τα υπόλοιπα που χρησιμοποιώ είναι μέχρι και 76.640.716 τα οποία είναι πολλές φορές πιο γρήγορα επειδή τα items φθάνουν μέχρι και 50.000
Evgenios1 Δημοσ. 6 Σεπτεμβρίου 2010 Δημοσ. 6 Σεπτεμβρίου 2010 Απο περιεργεια, δεν ειναι καπως αβολο να εχεις ενα listbox με 1k items; Απο θεμα UI. Να μου πεις η λυση του directx βολευει... αλλα και παλι, αν ο χρηστης scrolarei καταλαθος; Πχ αυτο που γινεται με την επιλογη γλωσσας που υπαρχει σε site & app, πατας g,r,e και εκει που πας να κλικαρεις, σου ξεφευγει και πατας κανα ιρακ . Και δευτερον, δεν ειδα πουθενα για το ποσο αργει, δευτερα; λεπτα;
smilefreeware Δημοσ. 6 Σεπτεμβρίου 2010 Μέλος Δημοσ. 6 Σεπτεμβρίου 2010 "Απο περιεργεια, δεν ειναι καπως αβολο να εχεις ενα listbox με 1k items;" Τι 1k , αφου σου γράφω ότι είναι MB. "Απο θεμα UI." Δεν γνωρίζω τι είναι το UI "αν ο χρηστης scrolarei καταλαθος; Πχ αυτο που γινεται με την επιλογη γλωσσας που υπαρχει σε site & app, πατας g,r,e και εκει που πας να κλικαρεις, σου ξεφευγει και πατας κανα ιρακ ." Δεν είναι για site, είναι ένα αυτόνομο πρόγραμμα exe σε delphi. "Και δευτερον, δεν ειδα πουθενα για το ποσο αργει, δευτερα; λεπτα;" Το έγραψα πριν ... Για να καταλάβετε 1 με 2 δέκατα του δευτερολέπτου θέλει να δημιουργηθεί το string και 2+ sec να μπει στο listbox. Σε Ε840 cpu.(στα 3, διπύρηνο) με 130.000 items των 10-30 χαρακτήρων.
Directx Δημοσ. 7 Σεπτεμβρίου 2010 Δημοσ. 7 Σεπτεμβρίου 2010 [..]Btw πως λεγετε αυτο το framework; Πρόκειται για την βιβλιοθήκη οπτικού – γρήγορου προγραμματισμού Visual Component Library (VCL) η οποία έκανε το ντεμπούτο της στην Borland Delphi (Pascal) και αργότερα στην C++ ως C++ Builder. Ο προγραμματισμού του VCL framework ομοιάζει με εκείνον του .NET framework σε μεγάλο βαθμό, πλην της managed φιλοσοφίας του τελευταίου (και κάποιον ακόμα μικρών διαφορών), καθώς αμφότερα μοιράζονται κοινό πατέρα (Anders Hejlsberg). @smilefreeware: Δεν γνωρίζω τι είναι το UI Πρόκειται για συντομογραφία - σύντμηση της έκφρασης User Interface.
Προτεινόμενες αναρτήσεις
Αρχειοθετημένο
Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.