[gtkmm] Wie funktioniert der ListStore?
-
Hi Leute,
kann mir einer von euch mal erklären, wie man den ListStore verwendet? Ich hab mir das Beispiel in der Dokumentation durchgelesen, aber ich steig da irgendwie nicht so ganz durch. Hat da einer von euch vielleicht ein einfacheres Beispiel? Wäre sehr nett von euch. ^^ Danke schonmal...
MfG Apo
-
Na ja, die Listen- bzw. Baumwidgets sind in gtkmm der härteste Brocken. Sie sind sehr flexibel und mächtig (zudem toll, um Design Patterns im Einsatz zu sehen
), allerdings auch komplex und etwas unhandlich.
Ein viel einfacheres Beispiel als das des Tutorials kann ich dir auch nicht geben. Was genau verstehst du denn nicht?
-
Ich bekomm es nicht mal hin, dass das ListStore angezeigt wird. Hast kannst du mir da vielleicht eine ganz kurze Einweisung geben? Ich musst das vererben, soweit bin ich schon, aber ich raff das nicht so richtig, wie das dann machen soll. xD
Wäre nett...
MfG Apo
-
Okay, ich werde mal ein einfaches Beispiel zusammenbasteln und beschreiben. Dauert aber evtl. etwas.
-
Schau mal hier: http://www.c-plusplus.net/forum/viewtopic-var-p-is-1000591.html#1000591
Ist teilweise kommentiert, aber ansonsten einfach zu verstehen.Die inner Klasse "ModelColumns" repräsentiert die Spalten der Tabelle, jenachdem kann man dort dann mehrere Spalten einfügen.
Kannst ja mal mit dem Code was rumspielen
-
OMG..., danke! Das sieht schon wesentlich einfacherer aus. Damit werde ich bestimmt zurecht kommen. Danke.
MfG Apo
-
Gut, weniger Arbeit für mich
-
Habe dank dem kurzen Tut von KasF geschafft eine Liste zu erstellen. Nun würde ich es gern so machen, dass wenn ich auf ein Listenelement klicke, dass die Daten zu der jeweiligen Person, aus einem Array des Typs Person*, ausgelesen werden und in den jeweiligen Textfeldern ausgegeben werden . Mein bisheriger Quelltext sieht so aus:
telefonbuch.hpp
//--- Definitionen ---------------------------------------- #ifndef _TELEFONBUCH_HPP #define _TELEFONBUCH_HPP //--- Header-Dateien -------------------------------------- #include <gtkmm/alignment.h> #include <gtkmm/box.h> #include <gtkmm/button.h> #include <gtkmm/entry.h> #include <gtkmm/label.h> #include <gtkmm/liststore.h> #include <gtkmm/scrolledwindow.h> #include <gtkmm/treemodelcolumn.h> #include <gtkmm/treeview.h> #include <gtkmm/window.h> #include "ModelColumns.hpp" #include "person.hpp" //--- Klasse Telfonbuch ----------------------------------- class Telefonbuch : public Gtk::Window { public: // Konstruktor und Destruktor Telefonbuch(); virtual ~Telefonbuch(); // Spalten ModelColumns m_Columns; protected: // anzeigen der Personendaten nach der Auswahl virtual void on_person_select(); // beenden des Programms virtual void on_button_beenden(); // Widgets Gtk::ScrolledWindow m_ScrolledWindow; Gtk::Alignment m_Alignment; Gtk::HBox m_hboxNachname, m_hboxVorname, m_hboxStrasse, m_hboxHNr, m_hboxPLZ, m_hboxOrt, m_hboxTelefon, m_hboxHandy, m_hboxEMail, m_hboxButtons; Gtk::VBox m_vboxOuter, m_vboxPersDaten; Gtk::Label m_lblNachname, m_lblVorname, m_lblStrasse, m_lblHNr, m_lblPLZ, m_lblOrt, m_lblTelefon, m_lblHandy, m_lblEMail; Gtk::Entry m_txtNachname, m_txtVorname, m_txtStrasse, m_txtHNr, m_txtPLZ, m_txtOrt, m_txtTelefon, m_txtHandy, m_txtEMail; Gtk::Button m_btnNeu, m_btnSpeichern, m_btnBeenden; Gtk::TreeView m_tview; Glib::RefPtr<Gtk::ListStore> m_refTreeModel; Person* pPersonen[300]; unsigned int m_uiAnzPersonen; }; #endif // _TELFONBUCH_HPP
telefonbuch.cpp
//--- Header-Dateien -------------------------------------- #include <fstream> #include <string> #include "telefonbuch.hpp" //--- Konstruktor ----------------------------------------- Telefonbuch::Telefonbuch() : m_lblNachname("Nachname:"), m_lblVorname("Vorname:"), m_lblStrasse("Straße:"), m_lblHNr("Hausnummer:"), m_lblPLZ("PLZ:"), m_lblOrt("Ort:"), m_lblTelefon("Telefon:"), m_lblHandy("Handy:"), m_lblEMail("E-Mail:"), m_btnNeu("Neu"), m_btnSpeichern("Speichern"), m_btnBeenden("Beenden"), m_uiAnzPersonen(0) { // personen.dat zum Lesen öffnen std::ifstream fin("personen.dat"); // deklarieren der benötigten Variablen std::string strNName, strVName, strStrasse, strHNr, strPLZ, strOrt, strTelefon, strHandy, strEMail; // Erstdaten auslesen fin >> strNName >> strVName >> strStrasse >> strHNr >> strPLZ >> strOrt >> strTelefon >> strHandy >> strEMail; // neue Person erzeugen pPersonen[m_uiAnzPersonen++] = new Person(strNName, strVName, strStrasse, strHNr, strPLZ, strOrt, strTelefon, strHandy, strEMail); do { // weitere Daten auslesen fin >> strNName >> strVName >> strStrasse >> strHNr >> strPLZ >> strOrt >> strTelefon >> strHandy >> strEMail; // weitere Person erzeugen pPersonen[m_uiAnzPersonen++] = new Person(strNName, strVName, strStrasse, strHNr, strPLZ, strOrt, strTelefon, strHandy, strEMail); } while(fin.eof()); // Spalten definieren m_refTreeModel = Gtk::ListStore::create(m_Columns); m_tview.set_model(m_refTreeModel); // Spalten mit Zeilen füllen Gtk::TreeModel::Row row; for(unsigned int i = 0; i < m_uiAnzPersonen; i++) { row = *(m_refTreeModel->append()); row[m_Columns.m_ID] = i+1; row[m_Columns.m_Nachname] = pPersonen[i]->GetNName(); row[m_Columns.m_Vorname] = pPersonen[i]->GetVName(); } // Spalten dem Treeview hinzufügen m_tview.append_column("ID", m_Columns.m_ID); m_tview.append_column("Nachname", m_Columns.m_Nachname); m_tview.append_column("Vorname", m_Columns.m_Vorname); // Fenstertitel setzen set_title("Telefonbuch"); // Rahmenabstand festlegen set_border_width(10); // Abstände zwischen den äußeren Bogen m_vboxOuter.set_spacing(15); // Scrollbars nur anzeigen, wenn sie gebraucht werden m_ScrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); // Klick auf eine Person m_tview.signal_clicked().connect(sigc::mem_fun(*this, &Telefonbuch::on_person_select)); // Klick auf den Button "Beenden" m_btnBeenden.signal_clicked().connect(sigc::mem_fun(*this, &Telefonbuch::on_button_beenden)); // Größe der Boxen homogenisieren m_vboxOuter.set_homogeneous(); m_hboxNachname.set_homogeneous(); m_hboxVorname.set_homogeneous(); m_hboxStrasse.set_homogeneous(); m_hboxHNr.set_homogeneous(); m_hboxPLZ.set_homogeneous(); m_hboxOrt.set_homogeneous(); m_hboxTelefon.set_homogeneous(); m_hboxHandy.set_homogeneous(); m_hboxEMail.set_homogeneous(); m_hboxButtons.set_homogeneous(); m_vboxPersDaten.set_homogeneous(); // Labels ausrichten m_lblNachname.set_alignment(0.05, 0.5); m_lblVorname.set_alignment(0.05, 0.5); m_lblStrasse.set_alignment(0.05, 0.5); m_lblHNr.set_alignment(0.05, 0.5); m_lblPLZ.set_alignment(0.05, 0.5); m_lblOrt.set_alignment(0.05, 0.5); m_lblTelefon.set_alignment(0.05, 0.5); m_lblHandy.set_alignment(0.05, 0.5); m_lblEMail.set_alignment(0.05, 0.5); // Fenster zusammensetzen m_ScrolledWindow.add(m_tview); m_vboxOuter.pack_start(m_ScrolledWindow); m_vboxOuter.pack_start(m_vboxPersDaten); m_vboxPersDaten.pack_start(m_hboxNachname); m_vboxPersDaten.pack_start(m_hboxVorname); m_vboxPersDaten.pack_start(m_hboxStrasse); m_vboxPersDaten.pack_start(m_hboxHNr); m_vboxPersDaten.pack_start(m_hboxPLZ); m_vboxPersDaten.pack_start(m_hboxOrt); m_vboxPersDaten.pack_start(m_hboxTelefon); m_vboxPersDaten.pack_start(m_hboxHandy); m_vboxPersDaten.pack_start(m_hboxEMail); m_vboxPersDaten.pack_start(m_hboxButtons); m_vboxPersDaten.pack_start(m_btnBeenden); // Entries, Labels und Buttons hinzufügen m_hboxNachname.pack_start(m_lblNachname); m_hboxNachname.pack_start(m_txtNachname); m_hboxVorname.pack_start(m_lblVorname); m_hboxVorname.pack_start(m_txtVorname); m_hboxStrasse.pack_start(m_lblStrasse); m_hboxStrasse.pack_start(m_txtStrasse); m_hboxHNr.pack_start(m_lblHNr); m_hboxHNr.pack_start(m_txtHNr); m_hboxPLZ.pack_start(m_lblPLZ); m_hboxPLZ.pack_start(m_txtPLZ); m_hboxOrt.pack_start(m_lblOrt); m_hboxOrt.pack_start(m_txtOrt); m_hboxTelefon.pack_start(m_lblTelefon); m_hboxTelefon.pack_start(m_txtTelefon); m_hboxHandy.pack_start(m_lblHandy); m_hboxHandy.pack_start(m_txtHandy); m_hboxEMail.pack_start(m_lblEMail); m_hboxEMail.pack_start(m_txtEMail); m_hboxButtons.pack_start(m_btnNeu); m_hboxButtons.pack_start(m_btnSpeichern); // äußere Box hinzufügen add(m_vboxOuter); // alle Widgets anzeigen show_all_children(); } //--- Destruktor ------------------------------------------ Telefonbuch::~Telefonbuch() { } //--- anzeigen der Personendaten nach der Auswahl --------- void Telefonbuch::on_person_select() { // herausfinden, welcher Datensatz ausgewählt ist Glib::RefPtr<Gtk::TreeSelection> refTreeSelection = m_tview.get_selection(); Gtk::TreeModel::iterator iter = refTreeSelection->get_selected(); // testen, ob etwas ausgewählt wurde if(iter) { // ID des ausgewählen Items holen Gtk::TreeModel::Row row = *iter; unsigned int uiIndex = row[m_Columns.m_ID]; // Daten der ausgewählen Person ausgeben m_txtNachname.set_text(pPersonen[uiIndex]->GetNName()); // OB DAS SO GEHT, WEISS ICH AUCH NICHT!!! } } //--- beenden des Programms ------------------------------- void Telefonbuch::on_button_beenden() { hide(); }
ModelColumns.hpp
//--- Definitionen ---------------------------------------- #ifndef _MODELCOLUMNS_HPP #define _MODELCOLUMNS_HPP //--- Header-Dateien -------------------------------------- #include <gtkmm/treemodelcolumn.h> #include <gtkmm/treeview.h> //--- Klasse ModelColumns --------------------------------- class ModelColumns : public Gtk::TreeModel::ColumnRecord { public: // Konstruktor ModelColumns(); // Widgets Gtk::TreeModelColumn<unsigned int> m_ID; Gtk::TreeModelColumn<Glib::ustring> m_Nachname; Gtk::TreeModelColumn<Glib::ustring> m_Vorname; }; #endif // _MODELCOLUMNS_HPP
ModelColumns.cpp
//--- Header-Dateien -------------------------------------- #include "ModelColumns.hpp" //--- Konstruktor ----------------------------------------- ModelColumns::ModelColumns() { add(m_ID); add(m_Nachname), add(m_Vorname); }
Das TreeView hat ja kein Klick-Signal. Aber irgendwie, muss doch mein Programm reagieren können, wenn ich auf einen Listenelement klicke. Wäre euch noch mal sehr dankbar, wenn ihr mir nochmals helfen könnten.
MfG Apo
-
Das ganze sieht dann so aus:
m_tview.signal_row_activated().connect( sigc::mem_fun(*this, &Telefonbuch::on_person_select) ); //... void Telefonbuch::on_person_select(const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column ) { Gtk::TreeModel::iterator iter = m_refTreeModel->get_iter(path); if(iter) { Gtk::TreeModel::Row row = *iter; unsigned int uiIndex = row[m_Columns.m_ID]; string name = row[m_Columns.m_Nachname]; //... } }
Warst also schon nahe dran
Zudem solltest du vllt überlegen, ob ein std::vector<Person> nicht schöner wäre als ein Person* p[300] und deine Schleife zum Auslesen der Datei sieht auch nicht irgendwie richtig aus und Erstdaten brauchst du auch nicht gesondert auszulesen.
Machst besser so:while(fin >> strNName >> strVName >> strStrasse >> strHNr >> strPLZ >> strOrt >> strTelefon >> strHandy >> strEMail ) { pPersonen[m_uiAnzPersonen++] = new Person(strNName, strVName, strStrasse, strHNr, strPLZ, strOrt, strTelefon, strHandy, strEMail); } // oder while(!fin.eof() && !fin.fail()) { fin >> strNName >> strVName >> strStrasse >> strHNr >> strPLZ >> strOrt >> strTelefon >> strHandy >> strEMail if(!fin.fail()) // oder if(fin.fail()) break; pPersonen[m_uiAnzPersonen++] = new Person(strNName, strVName, strStrasse, strHNr, strPLZ, strOrt, strTelefon, strHandy, strEMail); } // oder mit std::vector<Person> persons(300); while(!fin.eof() && !fin.fail()) { fin >> strNName >> strVName >> strStrasse >> strHNr >> strPLZ >> strOrt >> strTelefon >> strHandy >> strEMail if(!fin.fail()) // oder if(fin.fail()) break; persons.push_back( Person(strNName, strVName, strStrasse, strHNr, strPLZ, strOrt, strTelefon, strHandy, strEMail) ); }
Mal das durchlesen und aufjedenfall den Link am Ende ( der momentan leider nicht funktioniert ) : http://c-plusplus.net/forum/viewtopic-var-p-is-1319931.html
-
lol..., war ja echt ganz nah dran. Habe das mit dem signal_row_activated() nirgendwo gefunden. Steht das irgendwo in der Dokumentation?
Habe auch gestern Abend schon darüber nachgedacht einen std::vector<> zu verwenden und werde das umstellen, wenn ich mit dem Programm zum Größtenteil fertig bin.
Und ich werde mir mal die Seite, die du noch angehängt hast, ansehen. Mal sehen, was da interessantes steht.
MfG Apo
-
Apocalypse schrieb:
Steht das irgendwo in der Dokumentation?
Bei sowas immer bei jeweiligen Widget unter signals... nachschauen.
http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1TreeView.htmlApocalypse schrieb:
Und ich werde mir mal die Seite, die du noch angehängt hast, ansehen. Mal sehen,
was da interessantes steht.Der Link in meinem Link (
)ist wesentlich interessanter, vllt hat ja GPC die PDF von dort, oder du wartest bis sie wieder funktioniert
-
PDF
???
-
Auf Hume's Seite kann man die FAQ auch als pdf runterladen
, aber die Seite ist ehe wieder online, also hat sichs erledigt.
-
Okay..., werde mal gucken, ob ich dort eine PDF-Datei finde oder so etwas.
Auf jedenfall funktioniert das nun und ich habe auch schon auf einen std::vector<> umgebastelt. Außerdem habe ich meine Dateiauslesung überarbeitet. Nun kann ich weiter arbeiten. ^^
Das mit dem Auslesen habe ich so gemacht, weil wir das so in der Schule gelernt habe, aber man lernt ja bekanntlich nie aus.
MfG Apo