[wxWidgets] wxGrid mit eigener Klasse verbinden


  • Mod

    Ich hab mich jetzt länger in wxGrid eingearbeitet,
    mit dem Ziel, irgendwann es zu ermöglichen, das ich
    Klassen, die ihre Daten per Setter und Getter preisgeben,
    einfach an das Grid binden zu können, wenn diese in
    einer anderen Klasse in einem Container liegen.

    Damit wollte ich vorallem mir die Arbeit ersparen, für
    jede Klasse ein eigenes Grid schreiben zu müssen, wie ich
    das noch unter MFC getan habe.

    Wie gesagt, ich habe häufiger Klassen, wo man die
    Daten über Setter und Getter manipulieren kann.
    Andere Klassen haben wiederum einen Container der
    diese Klasse enthält. Im Grid soll nun der
    Inhalt dieses Containers angezeigt werden, und
    dort auch gleichzeitig bearbeitbar sein.

    wxGrid besitzt übrigens nur einen Pointer auf einen
    wxGridTableBase, welcher die eigentlichen Daten liefert,
    daher findet sich in meinem Beispiel auch ein ganz normales
    wxGrid, man muss dieses nicht überschreiben, sondern lediglich
    eine Klasse von wxGridTableBase ableiten.

    Eine Beispielklasse:

    class Article
    {
    	std::string name;
    	std::string id;
    	int number;
    	bool instock;
    	float price;
    protected:
    public:
    	Article(std::string name, std::string id, int number);
    	virtual ~Article();
    	Article(const Article& copy);
    	Article& operator=(const Article& copy);
    	std::string Getname();
    	void Setname(std::string Name);
    	std::string Getid();
    	void Setid(std::string Id);
    	int Getnumber();
    	void Setnumber(int Number);
    	bool Getinstock();
    	void Setinstock(bool Instock);
    	float Getprice();
    	void Setprice(float Price);
    };
    

    Um nun einen Container (std::list<Article>) mit dem Grid zu verbinden,
    ist folgender Codeausschnitt nötig:

    // ein paar werte schon mal in die Liste einfügen...
    	artlist.push_back(Article("Metalplates","23",34));
    	artlist.push_back(Article("Nails","24",26));
    	artlist.push_back(Article("Screws","25",12025));
    
    	// DataTable erstellen
    	pdatatable = new datagrid::DataTable<Article,std::list<Article>::iterator>(artlist.begin(),artlist.end());
    	// Die entsprechenden Membervariablen mit den Spalten des Grids verbinden
    	pdatatable->addColumn("Name",new datagrid::TCI_string<Article>(&Article::Setname,&Article::Getname));
    	pdatatable->addColumn("id",new datagrid::TCI_string<Article>(&Article::Setid,&Article::Getid));
    	pdatatable->addColumn("Numbers",new datagrid::TCI_int<Article>(&Article::Setnumber,&Article::Getnumber));
    	pdatatable->addColumn("is in Stock",new datagrid::TCI_bool<Article>(&Article::Setinstock,&Article::Getinstock));
    	pdatatable->addColumn("Price",new datagrid::TCI_float<Article>(&Article::Setprice,&Article::Getprice,3,2));
    	// Den DataTable dem wxGrid mitteilen
    	grid->SetTable(pdatatable);
    	// Das Grid initialisieren
    	pdatatable->InitGrid();
    

    Schon zeigt das Grid den Inhalt der Liste an.
    Kurze Erklärung der einzelnen Klassen:
    DataTable<Type,It> : Die Klasse welche die Daten an das Grid liefert, und auch benachrichtigt wird, wenn Werte geändert wurden.
    Type ist die Datenklasse, It der Iterator auf den Container.
    TCI_int<Type>: Verbindet eine int-Variable mit einer Spalte im Grid, es müssen
    die entsprechenden Handler übergeben werden. TCI steht für TableColumnItem,
    welches auch die Basisklasse für alle TCI_* Klassen ist.
    TCI_float, TCI_string und TCI_bool verbinden den entsprechenden Datentyp mit einer Spalte im Grid.

    Das ganze zum Downloaden mit Beispiel gibts hier

    phlox


  • Mod

    Gibt ein Update.

    Kurz die Neuerungen:

    Klasse DataTable:
    Das interface ist jetzt:

    template<class It, class Type = typename std::iterator_traits<It>::value_type>class DataTable
    

    So kann man bei STL Containern sich den 2. Parameter sparen.
    Ebenfalls hat die Klasse nun 2 neue Methoden:
    Update(It beg, It end): Das Grid aktualisieren
    SetColumnName(int index,wxString name): ColumnHeader umbenennen
    Geändert hat sich auch InitGrid, hier wird nun das Grid übergeben:
    InitGrid(wxGrid*,bool owntable = true): wxGrid::SetTable wird nun durch die Methode
    aufgerufen, und owntable bestimmt dabei ob das Grid den Table mit löscht
    wenn es zerstört wird.

    ebenfalls haben sich die Getter Methoden geändert:
    von: type class::Getvarname() zu type class::Getvarname()const
    ()const macht für Getter einfach mehr Sinn in diesem Kontext.

    phlox


Anmelden zum Antworten