Autore: Fabio Di Matteo
Ultima revisione: 20/02/2018 - 12:05
E' possibile risparmiare tempo e tante righe di codice “disegnando” il treeview, il list store e l'intera grafica della nostra gui con l'editor di interfaccie Glade. Di seguito il codice commentato.
gui.ui
<?xml version="1.0" encoding="UTF-8"?> <!-- Generated with glade 3.20.2 --> <interface> <requires lib="gtk+" version="3.20"/> <object class="GtkListStore" id="myListstore"> <columns> <!-- column-name ID --> <column type="gint"/> <!-- column-name Nome --> <column type="gchararray"/> <!-- column-name Gradimento --> <column type="gint"/> </columns> <data> <row> <col id="0">1</col> <col id="1" translatable="yes">Fabio Di Matteo</col> <col id="2">50</col> </row> <row> <col id="0">2</col> <col id="1" translatable="yes">Tizio Rossi</col> <col id="2">10</col> </row> </data> </object> <object class="GtkWindow" id="window1"> <property name="width_request">406</property> <property name="visible">True</property> <property name="can_focus">False</property> <property name="has_resize_grip">True</property> <signal name="delete-event" handler="on_mainWindow_delete_event()" swapped="no"/> <child> <object class="GtkBox"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="orientation">vertical</property> <child> <object class="GtkEntry" id="entry"> <property name="visible">True</property> <property name="can_focus">True</property> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> <object class="GtkScrolledWindow"> <property name="width_request">500</property> <property name="height_request">415</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="shadow_type">in</property> <child> <object class="GtkTreeView" id="myTreeView"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="model">myListstore</property> <property name="reorderable">True</property> <property name="search_column">1</property> <property name="activate_on_single_click">True</property> <child internal-child="selection"> <object class="GtkTreeSelection" id="myTreeSel"/> </child> <child> <object class="GtkTreeViewColumn" id="colID"> <property name="title" translatable="yes">ID</property> <child> <object class="GtkCellRendererSpin"/> <attributes> <attribute name="text">0</attribute> </attributes> </child> </object> </child> <child> <object class="GtkTreeViewColumn" id="colNome"> <property name="title" translatable="yes">Nome</property> <child> <object class="GtkCellRendererText"/> <attributes> <attribute name="text">1</attribute> </attributes> </child> </object> </child> <child> <object class="GtkTreeViewColumn" id="colGradimento"> <property name="title" translatable="yes">Gradimento</property> <child> <object class="GtkCellRendererProgress"/> <attributes> <attribute name="value">2</attribute> </attributes> </child> </object> </child> </object> </child> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> <property name="position">1</property> </packing> </child> <child> <placeholder/> </child> <child> <placeholder/> </child> </object> </child> <child type="titlebar"> <object class="GtkHeaderBar"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="title">GtkTreeview e Glade</property> <property name="subtitle">Come usare il treeview con glade</property> <property name="show_close_button">True</property> <child> <object class="GtkBox"> <property name="visible">True</property> <property name="can_focus">False</property> <child> <object class="GtkButton" id="btAdd"> <property name="label">gtk-add</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> <property name="use_stock">True</property> <property name="always_show_image">True</property> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> <object class="GtkButton" id="btDel"> <property name="label">gtk-delete</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> <property name="use_stock">True</property> <property name="always_show_image">True</property> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> <property name="position">1</property> </packing> </child> <child> <object class="GtkButton" id="btSave"> <property name="label">gtk-save</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> <property name="use_stock">True</property> <property name="always_show_image">True</property> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> <property name="position">2</property> </packing> </child> <child> <object class="GtkButton" id="btClear"> <property name="label">gtk-clear</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> <property name="use_stock">True</property> <property name="always_show_image">True</property> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> <property name="position">3</property> </packing> </child> </object> </child> </object> </child> </object> </interface>
main.cpp
#include <gtkmm.h> #include "mainwindow.hpp" int main(int argc, char *argv[]) { auto app = Gtk::Application::create(argc, argv, "org.gtkmm.example"); mainWindow mainw; return app->run(*mainw.window1); }
mainwindow.hpp
#ifndef MAINWINDOW_HPP #define MAINWINDOW_HPP #include <gtkmm.h> class mainWindow { public: Glib::RefPtr<Gtk::Builder> builder; Gtk::Window *window1; Gtk::TreeView *treeView; Glib::RefPtr<Gtk::ListStore> listStore; Gtk::Entry *entry; Gtk::Button *add, *del, *save, *clear; mainWindow(); protected: void on_add_clicked(); void on_delete_clicked(); void on_save_clicked(); void on_selection_changed(); void on_clear_clicked(); private: /* add your private declarations */ }; #endif /* MAINWINDOW_HPP */
mainwindow.cpp
#include "mainwindow.hpp" #include <iostream> mainWindow::mainWindow() { auto builder = Gtk::Builder::create(); try { builder->add_from_resource("/app/res/gui.ui"); } catch(const Glib::FileError& ex) { std::cerr << "FileError: " << ex.what() << std::endl; } catch(const Glib::MarkupError& ex) { std::cerr << "MarkupError: " << ex.what() << std::endl; } catch(const Gtk::BuilderError& ex) { std::cerr << "BuilderError: " << ex.what() << std::endl; } builder->get_widget("window1", window1); builder->get_widget("myTreeView",treeView); listStore = Glib::RefPtr<Gtk::ListStore>::cast_dynamic(builder->get_object("myListstore")); builder->get_widget("entry",entry); builder->get_widget("btAdd",add); builder->get_widget("btDel",del); builder->get_widget("btSave",save); builder->get_widget("btClear",clear); //Connetto i bottoni alle callbacks add->signal_clicked().connect(sigc::mem_fun(*this, &mainWindow::on_add_clicked) ); del->signal_clicked().connect(sigc::mem_fun(*this, &mainWindow::on_delete_clicked) ); save->signal_clicked().connect(sigc::mem_fun(*this, &mainWindow::on_save_clicked) ); clear->signal_clicked().connect(sigc::mem_fun(*this, &mainWindow::on_clear_clicked) ); //Connetto le callbacks per il Treeview (cambio di selezione riga) Glib::RefPtr<Gtk::TreeSelection> refTreeSelection = treeView->get_selection(); refTreeSelection->signal_changed().connect( sigc::mem_fun(*this,&mainWindow::on_selection_changed) ); } //Aggiunge una riga al liststore void mainWindow::on_add_clicked() { static double gradimento=0; static int i ; i++; gradimento=gradimento+0.8; //La nostra classe personalizzata per specificare il modello di colonne: class ModelColumns : public Gtk::TreeModel::ColumnRecord { public: ModelColumns() { add(id); add(nome); add(gradimento); } Gtk::TreeModelColumn<unsigned int> id; Gtk::TreeModelColumn<Glib::ustring> nome; Gtk::TreeModelColumn<unsigned int> gradimento; }; ModelColumns m_Columns; //Aggiungo le righe al liststore Gtk::TreeModel::Row row = *(listStore->append()); row[m_Columns.id] = i; row[m_Columns.nome] = entry->get_text(); row[m_Columns.gradimento] = gradimento; } void mainWindow::on_delete_clicked() { Glib::RefPtr<Gtk::TreeSelection> refTreeSelection = treeView->get_selection(); Gtk::TreeModel::iterator iter = refTreeSelection->get_selected(); if(iter) //se qualcosa è selezionato { listStore->Gtk::ListStore::erase(iter); } } void mainWindow::on_save_clicked() { std::string nome; nome=entry->get_text(); //Ricavo il valore di una riga selezionata Glib::RefPtr<Gtk::TreeSelection> refTreeSelection = treeView->get_selection(); Gtk::TreeModel::iterator iter = refTreeSelection->get_selected(); if(iter) { //Prelevo il valore di una cella al click e lo salvo Gtk::TreeModel::Row row = *iter; row.set_value (1, nome ); } } void mainWindow::on_selection_changed() { std::string nome; //Ricavo il valore di una riga selezionata Glib::RefPtr<Gtk::TreeSelection> refTreeSelection = treeView->get_selection(); Gtk::TreeModel::iterator iter = refTreeSelection->get_selected(); if(iter) { //Prelevo il valore di una cella al click e lo scrivo sulla entry Gtk::TreeModel::Row row = *iter; row.get_value (1, nome ); entry->set_text(nome); } } void mainWindow::on_clear_clicked() { listStore->clear(); }