Προς το περιεχόμενο

Listview στη C++


georginos1989

Προτεινόμενες αναρτήσεις

Πως μπορώ σε ενα listview στη c++ να ξέρω ποια γραμμή ειναι επιλεγμενη καθε φορα?

 

Δλδ οταν θα επιλεγω μια γραμμή να μπορώ να παιρνω το περιεχομενο αυτης της γραμμης

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

  • Απαντ. 62
  • Δημ.
  • Τελ. απάντηση
Πως μπορώ σε ενα listview στη c++ να ξέρω ποια γραμμή ειναι επιλεγμενη καθε φορα?

 

Δλδ οταν θα επιλεγω μια γραμμή να μπορώ να παιρνω το περιεχομενο αυτης της γραμμης

 

Θα ήθελες να μας πεις ποίο εργαλείο προγραμματισμού χρησιμοποιείς;

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Μπορείς να χρησιμοποιήσεις το OnSelectItem event το οποίο παρέχει εκτός του TObject *Sender, το επιλεγμένο Item σε μορφή TListItem* και το bool Selected το οποίο είναι true αν ο χρήστης επιλέγει ένα Item ή false αν ο χρήστης απο-επιλέγει το Item.

 

Για παράδειγμα, αν θες να παρουσιάσεις τον τίτλο του επιλεγμένου Item στην οθόνη (υποθέτω ότι έχεις ένα TListView ονόματι ListView1 και πως μέσο του Object Inspector->Events έχεις ορίσει το "OnSelectItem" Event):

 

>
void __fastcall TForm1::ListView1SelectItem(TObject *Sender, TListItem *Item, bool Selected)

{
if(Selected)
	ShowMessage(Item->Caption);
}

 

Υ.Γ.

Σε περίπτωση που το TListView καλείται να υποστηρίξει μαζική επιλογή (MultiSelect), ο κώδικας θα πρέπει να τροποποιηθεί, αλλά καθώς δεν θέλω να σε μπερδέψω δεν θα επεκταθώ περαιτέρω εκτός και αν ζητηθεί.

 

Καλή συνέχεια!

:-)

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Ναι αυτο που είπες καλό ειναι... Για αρχή δεν θέλω multiselect... Απλώς θέλω αυτό που επιλέγεις να αφαιρείται απο το listview... Θα το ψάξω πως γίνεται και κολήσω κάπου τα ξαναλέμε...

Ευχαριστώ για την βοήθεια

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Λοιπόν έκανα τον κώδικα που είπες οπως φαινεται παρακατω... Έχω βάλει κωδικα ώστε οταν επιλέγεις ενα item να αφαιρείται αλλά αν επιλέξω ενα μεσαίο item το αφαιρεί μια χαρά το εμφανίζει και σε μνμ αλλά μετά πάει και στο επομενο item και το αφαιρεί... Οταν ομως επιλέξω ενα τελευταίο item δεν επιλέγει και επομενο item.. Λογικο το βρίσκω γιατί δεν εχει αλλο πιο μετα... Τι πρεπει να αλλάξω για να μην το κανει αυτο?

 

void __fastcall TForm1::ListView1SelectItem(TObject *Sender,

TListItem *Item, bool Selected)

{

if(Selected)

{

ShowMessage(Item->Caption);

Edit2->Text=Item->Index;

ListView1->Items->Delete(Item->Index);

}

}

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Το πρόβλημα αυτό προέρχεται από την κλήση της ShowMessage και τον τρόπο που αντιδρά η VCL ύστερα όταν ανακτά το focus η φόρμα. Θα μπορούσες να το αντιμετωπίσεις αφαιρώντας την ShowMessage. Επίσης μπορείς να εξαλείψεις το ->Items->Delete με την ListView1->DeleteSelected().

 

Για παράδειγμα:

>
ListView1->DeleteSelected();

Αν θες υποχρεωτικά να καλείς την ShowMessage θα μπορούσες να χρησιμοποιήσεις το TListView OnClick event το οποίο κατά την επιστροφή από το ShowMessage δεν "ντουμπλάρει" το OnSelectItem event. Αλλά σε αυτή την περίπτωση θα πρέπει να γράψεις έξτρα κώδικα για την διαγραφή από το πληκτρολόγιο καθώς αυτό το event ενημερώνει μόνο για γεγονότα από το ποντίκι.

 

Ακολουθεί κώδικας για το OnClick event:

 

>
void __fastcall TForm1::ListView1Click(TObject *Sender)
{
TListItem *Item = ListView1->Selected;

if(Item != NULL)
{
	ShowMessage(Item->Caption);
	Edit1->Text=Item->Index;
	ListView1->Items->Delete(Item->Index);
}
}

Υ.Γ.

Προσωπικά πάντως θα απέφευγα την άμεση διαγραφή του Item κατά την επιλογή του από τον χρήστη, τοποθετώντας τον κώδικα σε ένα ανεξάρτητο event, για παράδειγμα σε ένα πλήκτρο "Διαγραφή". Η άμεση διαγραφή του επιλεγμένου Item έχει αρκετά χρηστικά μειονεκτήματα (δύσχρηστη).

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Για να καταλαβεις τι προγραμμα ειναι και γιατι θελω να διαγραφεται...

Εισαι εσυ ο γιατρός και εχεις ενα προγραμμα στο οποιο οι ασθενεις εισαγουν καποιες μετρησεις και μετα το συστημα υπολογιζει τι εχει ο ασθενης και εμφανιζει μια ειδοποιηση(κοκκινη ,πρασινη κιτρινη)

 

Αυτό που θελω εγω ειναι οτι οταν ο γιατρος θα μπαινει στο συστημα να του εμφανιζει ενα listview με ολες τις σημερινες ειδοποιήσεις και σε ποιον ασθενη αντιστοιχουν..

Ετσι ο γιατρος θα μπορει να επιλεγει εναν ασθενη και να του ανοιγει μια φορμα με τα στοιχεια του και τις μετρησεις που εισηγαγε..

Γιαυτο θελω να διαγραφετε οταν τον επιλεξει

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Έτσι όπως μου το περιγράφεις θα μπορούσες να το κάνεις εκμεταλλευόμενος το DblClick event, δηλαδή να δίνεις την ευκαιρία στον χρήστη να κάνει double-click μια επιλογή, να εμφανίζεις την φόρμα με τα στοιχεία που θες και ύστερα στην επιστροφή να διαγραφείς το επιλεγμένο TListItem.

 

Φυσικά μπορείς να κάνεις το ίδιο και με το OnClick event -απλά εμένα μου αρέσει η χρήση του DblClick event.

 

Έτσι θα μπορούσες να τοποθετήσεις ένα κώδικα σαν αυτόν στο DblClick event του TListView σου:

 

>
void __fastcall TForm1::ListView1DblClick(TObject *Sender)
{
if(ListView1->Selected)
{
	std::auto_ptr<TForm2> frmPatient(new TForm2(this, ListView1->Selected));
	if(frmPatient->ShowModal() == mrOk)
		ListView1->DeleteSelected();
}
}

 

Υποθέτω ότι η δεύτερη φόρμα σου ονομάζεται TForm2 και ο constructor της δέχεται ως δεύτερη παράμετρο του ένα TListItem*. Μάλιστα δίνω ευκαιρία στον χρήστη να ακυρώσει την διαγραφή επιτρέποντας την αφαίρεση του TListItem μόνο αν το ShowModal της φόρμας επιστρέψει τιμή "mrOk". Φυσικά και αυτό μπορείς να το αφαιρέσεις οπότε με το κλείσιμο της φόρμας να εκτελείται άμεσα η διαγραφή.

 

Ακολουθεί ένα σύντομο video για να μην ταλαιπωρηθείς με κάτι που μπορεί να μην σε καλύπτει:

 

 

Υ.Γ.

Ο κώδικας γράφτηκε γρήγορα, είναι ενδεικτικός της φιλοσοφίας που ζητάς, φυσικά αν πρόκειται να χρησιμοποιηθεί σε τελικό λογισμικό χρειάζεται διάφορες προσθήκες & βελτιώσεις.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Υπάρχει τρόπος να μπορώ να βάζω χρώμα σε ξεχωριστά κελιά του listview?

Εψαξα στο ιντερνετ αλλά βρήκα ότι το κανουν με πολυ κωδικα... Υπάρχει άλλος τροπος?

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Από την έκδοση του C++ Builder 6 και μετά το TListView component προσφέρει το OnAdvancedCustomDrawSubItem event το οποίο επιτρέπει την άμεση επέμβαση στο rendering των SubItems κάθε TListView δίχως να μας υποχρεώνει να ξανά γράψουμε ολόκληρο τον κώδικα σχεδίασης των TListItem στο component.

 

Για παράδειγμα αν το TListView μας έχει 2 SubItems και θέλουμε να τα βάψουμε με κόκκινο (clRed) χρώμα το πρώτο και πράσινο (clGreen) χρώμα το δεύτερο, φτάνει να υποδείξουμε στο TListView->Canvas μας το χρώμα της βούρτσας (ListView1->Canvas->Brush->Color) που θα χρησιμοποιήσει πριν ξεκινήσει να σχεδιάζει (Stage == cdPrePaint) κάθε SubItem (ο αριθμός του προς σχεδίαση Item) στο component.

 

Όπως πάντα, υποθέτω ότι το TListView σου ονομάζεται ListView1.

 

>
void __fastcall TForm1::ListView1AdvancedCustomDrawSubItem(TCustomListView *Sender,
         TListItem *Item, int SubItem, TCustomDrawState State, TCustomDrawStage Stage,
         bool &DefaultDraw)
{
// Each SubItem/Column color array (init. once for program instance)..
static TColor SubItemColor[] = { clRed, clGreen };
// Before TListView Canvas get redrawn, override Brush to each SubItem color..
if(Stage == cdPrePaint)
	 ListView1->Canvas->Brush->Color = SubItemColor[subItem - 1];
// The rest is done automatically by VCL!
}

Ο κώδικας έχει δοκιμασθεί σε C++ Builder 2009 και Windows XP (SP3) και ελπίζω να λειτουργεί σωστά και σε νεότερες εκδόσεις του Λ.Σ.

 

Καλή συνέχεια!!

:)

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Ναι, αν για παράδειγμα επιθυμείς να βάψεις με κόκκινο χρώμα μόνο το SubItem1 και τα υπόλοιπα με άσπρο τότε:

 

>
if(Stage == cdPrePaint)
	ListView1->Canvas->Brush->Color = SubItem == 1 ? clRed: clWhite;

 

modec.png

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Αρχειοθετημένο

Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.


  • Δημιουργία νέου...