Usar widgets derivados
Puede usar Glade para distribuir sus propios widgets personalizados derivados de las clases de widgets de gtkmm. Esto mantiene su código organizado y encapsulado. Por supuesto, no verá la apariencia exacta ni las propiedades de su widget derivado en Glade, pero puede especificar su ubicación, widgets hijos y las propiedades de su clase base de gtkmm.
Use Gtk::Builder::get_widget_derived() like so:
DerivedDialog* pDialog = nullptr; builder->get_widget_derived("DialogBasic", pDialog);
Su clase derivada debe tener un constructor que tome un puntero al tipo C subyacente, y a la instancia Gtk::Builder. Todas las clases relevantes de gtkmm crean alias de sus tipos C subyacentes como BaseObjectType (Gtk::Dialog define un alias de BaseObjectType como GtkDialog, por ejemplo).
You must call the base class's constructor in the initialization list, providing the C pointer. For instance,
DerivedDialog::DerivedDialog(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& builder) : Gtk::Dialog(cobject) { }
You could then encapsulate the manipulation of the child widgets in the constructor of the derived class, maybe using get_widget() or get_widget_derived() again. For instance,
DerivedDialog::DerivedDialog(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& builder) : Gtk::Dialog(cobject), m_builder(builder), m_pButton(nullptr) { //Get the Glade-instantiated Button, and connect a signal handler: m_builder->get_widget("quit_button", m_pButton); if(m_pButton) { m_pButton->signal_clicked().connect( sigc::mem_fun(*this, &DerivedDialog::on_button_quit) ); } }
Starting with gtkmm 3.19.7, it's possible to pass additional arguments from get_widget_derived() to the constructor of the derived widget. For instance, this call to get_widget_derived()
DerivedDialog* pDialog = nullptr; builder->get_widget_derived("DialogBasic", pDialog, true);
DerivedDialog::DerivedDialog(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& builder, bool warning) : Gtk::Dialog(cobject), m_builder(builder), m_pButton(nullptr) { // .... }
- 26.3.1. Ejemplo
26.3.1. Ejemplo
Este ejemplo mustra cómo cargar un archivo Glade en tiempo de ejecución y acceder a los widgets mediante una clase derivada.
File: deriveddialog.h (For use with gtkmm 3, not gtkmm 2)
#ifndef GTKMM_EXAMPLE_DERIVED_DIALOG_H #define GTKMM_EXAMPLE_DERIVED_DIALOG_H #include <gtkmm.h> class DerivedDialog : public Gtk::Dialog { public: DerivedDialog(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& refGlade); DerivedDialog(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& refGlade, bool is_glad); virtual ~DerivedDialog(); protected: //Signal handlers: void on_button_quit(); Glib::RefPtr<Gtk::Builder> m_refGlade; Gtk::Button* m_pButton; }; #endif //GTKMM_EXAMPLE_DERIVED_WINDOW_H
File: main.cc (For use with gtkmm 3, not gtkmm 2)
#include "deriveddialog.h" #include <iostream> #include <cstring> int main (int argc, char **argv) { bool show_icon = false; bool is_glad = true; int argc1 = argc; if (argc > 1) { if (std::strcmp(argv[1], "--glad") == 0) { show_icon = true; is_glad = true; argc1 = 1; // Don't give the command line arguments to Gtk::Application. } else if (std::strcmp(argv[1], "--sad") == 0) { show_icon = true; is_glad = false; argc1 = 1; // Don't give the command line arguments to Gtk::Application. } } auto app = Gtk::Application::create(argc1, argv, "org.gtkmm.example"); //Load the Glade file and instantiate its widgets: auto refBuilder = Gtk::Builder::create(); try { refBuilder->add_from_file("derived.glade"); } catch(const Glib::FileError& ex) { std::cerr << "FileError: " << ex.what() << std::endl; return 1; } catch(const Glib::MarkupError& ex) { std::cerr << "MarkupError: " << ex.what() << std::endl; return 1; } catch(const Gtk::BuilderError& ex) { std::cerr << "BuilderError: " << ex.what() << std::endl; return 1; } //Get the GtkBuilder-instantiated dialog: DerivedDialog* pDialog = nullptr; if (show_icon) // This call to get_widget_derived() requires gtkmm 3.19.7 or higher. refBuilder->get_widget_derived("DialogDerived", pDialog, is_glad); else refBuilder->get_widget_derived("DialogDerived", pDialog); if(pDialog) { //Start: app->run(*pDialog); } delete pDialog; return 0; }
File: deriveddialog.cc (For use with gtkmm 3, not gtkmm 2)
#include "deriveddialog.h" DerivedDialog::DerivedDialog(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& refGlade) : Gtk::Dialog(cobject), m_refGlade(refGlade), m_pButton(nullptr) { //Get the Glade-instantiated Button, and connect a signal handler: m_refGlade->get_widget("quit_button", m_pButton); if(m_pButton) { m_pButton->signal_clicked().connect( sigc::mem_fun(*this, &DerivedDialog::on_button_quit) ); } } // The first two parameters are mandatory in a constructor that will be called // from Gtk::Builder::get_widget_derived(). // Additional parameters, if any, correspond to additional arguments in the call // to Gtk::Builder::get_widget_derived(). DerivedDialog::DerivedDialog(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& refGlade, bool is_glad) : DerivedDialog(cobject, refGlade) // Delegate to the other constructor { // Show an icon. auto pImage = Gtk::manage(new Gtk::Image()); pImage->set_from_icon_name(is_glad ? "face-smile" : "face-sad", Gtk::ICON_SIZE_DIALOG); pImage->show_all(); get_content_area()->pack_start(*pImage); } DerivedDialog::~DerivedDialog() { } void DerivedDialog::on_button_quit() { hide(); //hide() will cause Gtk::Application::run() to end. }