This program contains an application menu, a menubar and a toolbar.
Classes are derived from Gtk::Application
and
Gtk::ApplicationWindow
.
File: exampleapplication.h
(For use with gtkmm 4)
#ifndef GTKMM_EXAMPLEAPPLICATION_H #define GTKMM_EXAMPLEAPPLICATION_H #include <gtkmm.h> class ExampleApplication : public Gtk::Application { protected: ExampleApplication(); public: static Glib::RefPtr<ExampleApplication> create(); protected: //Overrides of default signal handlers: void on_startup() override; void on_activate() override; private: void create_window(); void on_window_hide(Gtk::Window* window); void on_menu_file_new_generic(); void on_menu_file_quit(); void on_menu_help_about(); Glib::RefPtr<Gtk::Builder> m_refBuilder; }; #endif /* GTKMM_EXAMPLEAPPLICATION_H */
File: examplewindow.h
(For use with gtkmm 4)
#ifndef GTKMM_EXAMPLEWINDOW_H #define GTKMM_EXAMPLEWINDOW_H #include <gtkmm.h> class ExampleWindow : public Gtk::ApplicationWindow { public: ExampleWindow(); virtual ~ExampleWindow(); protected: //Signal handlers: void on_menu_others(); void on_menu_choices(const Glib::ustring& parameter); void on_menu_choices_other(int parameter); void on_menu_toggle(); //Child widgets: Gtk::Box m_Box; Glib::RefPtr<Gtk::Builder> m_refBuilder; //Two sets of choices: Glib::RefPtr<Gio::SimpleAction> m_refChoice; Glib::RefPtr<Gio::SimpleAction> m_refChoiceOther; Glib::RefPtr<Gio::SimpleAction> m_refToggle; }; #endif //GTKMM_EXAMPLEWINDOW_H
File: exampleapplication.cc
(For use with gtkmm 4)
#include "exampleapplication.h" #include "examplewindow.h" #include <iostream> ExampleApplication::ExampleApplication() : Gtk::Application("org.gtkmm.example.main_menu") { Glib::set_application_name("Main Menu Example"); } Glib::RefPtr<ExampleApplication> ExampleApplication::create() { return Glib::make_refptr_for_instance<ExampleApplication>(new ExampleApplication()); } void ExampleApplication::on_startup() { //Call the base class's implementation: Gtk::Application::on_startup(); //Create actions for menus and toolbars. //We can use add_action() because Gtk::Application derives from Gio::ActionMap. //File|New sub menu: add_action("newstandard", sigc::mem_fun(*this, &ExampleApplication::on_menu_file_new_generic)); add_action("newfoo", sigc::mem_fun(*this, &ExampleApplication::on_menu_file_new_generic)); add_action("newgoo", sigc::mem_fun(*this, &ExampleApplication::on_menu_file_new_generic)); //File menu: add_action("quit", sigc::mem_fun(*this, &ExampleApplication::on_menu_file_quit)); //Help menu: add_action("about", sigc::mem_fun(*this, &ExampleApplication::on_menu_help_about)); // Set accelerator keys: set_accel_for_action("app.newstandard", "<Primary>n"); set_accel_for_action("app.quit", "<Primary>q"); set_accel_for_action("win.copy", "<Primary>c"); set_accel_for_action("win.paste", "<Primary>v"); m_refBuilder = Gtk::Builder::create(); //Layout the actions in a menubar and a menu: Glib::ustring ui_info = "<interface>" " <!-- menubar -->" " <menu id='menu-example'>" " <submenu>" " <attribute name='label' translatable='yes'>_File</attribute>" " <section>" " <item>" " <attribute name='label' translatable='yes'>New _Standard</attribute>" " <attribute name='action'>app.newstandard</attribute>" " <attribute name='accel'><Primary>n</attribute>" " </item>" " <item>" " <attribute name='label' translatable='yes'>New _Foo</attribute>" " <attribute name='action'>app.newfoo</attribute>" " </item>" " <item>" " <attribute name='label' translatable='yes'>New _Goo</attribute>" " <attribute name='action'>app.newgoo</attribute>" " </item>" " </section>" " <section>" " <item>" " <attribute name='label' translatable='yes'>_Quit</attribute>" " <attribute name='action'>app.quit</attribute>" " <attribute name='accel'><Primary>q</attribute>" " </item>" " </section>" " </submenu>" " <submenu>" " <attribute name='label' translatable='yes'>_Edit</attribute>" " <section>" " <item>" " <attribute name='label' translatable='yes'>_Copy</attribute>" " <attribute name='action'>win.copy</attribute>" " <attribute name='accel'><Primary>c</attribute>" " </item>" " <item>" " <attribute name='label' translatable='yes'>_Paste</attribute>" " <attribute name='action'>win.paste</attribute>" " <attribute name='accel'><Primary>v</attribute>" " </item>" " <item>" " <attribute name='label' translatable='yes'>_Something</attribute>" " <attribute name='action'>win.something</attribute>" " </item>" " </section>" " </submenu>" " <submenu>" " <attribute name='label' translatable='yes'>_Choices</attribute>" " <section>" " <item>" " <attribute name='label' translatable='yes'>Choice _A</attribute>" " <attribute name='action'>win.choice</attribute>" " <attribute name='target'>a</attribute>" " </item>" " <item>" " <attribute name='label' translatable='yes'>Choice _B</attribute>" " <attribute name='action'>win.choice</attribute>" " <attribute name='target'>b</attribute>" " </item>" " </section>" " </submenu>" " <submenu>" " <attribute name='label' translatable='yes'>_Other Choices</attribute>" " <section>" " <item>" " <attribute name='label' translatable='yes'>Choice 1</attribute>" " <attribute name='action'>win.choiceother</attribute>" " <attribute name='target' type='i'>1</attribute>" " </item>" " <item>" " <attribute name='label' translatable='yes'>Choice 2</attribute>" " <attribute name='action'>win.choiceother</attribute>" " <attribute name='target' type='i'>2</attribute>" " </item>" " </section>" " <section>" " <item>" " <attribute name='label' translatable='yes'>Some Toggle</attribute>" " <attribute name='action'>win.sometoggle</attribute>" " </item>" " </section>" " </submenu>" " <submenu>" " <attribute name='label' translatable='yes'>_Help</attribute>" " <section>" " <item>" " <attribute name='label' translatable='yes'>_About Window</attribute>" " <attribute name='action'>win.about</attribute>" " </item>" " <item>" " <attribute name='label' translatable='yes'>_About App</attribute>" " <attribute name='action'>app.about</attribute>" " </item>" " </section>" " </submenu>" " </menu>" "</interface>"; try { m_refBuilder->add_from_string(ui_info); } catch (const Glib::Error& ex) { std::cerr << "Building menus failed: " << ex.what(); } //Get the menubar and the app menu, and add them to the application: auto gmenu = m_refBuilder->get_object<Gio::Menu>("menu-example"); if (!gmenu) { g_warning("GMenu not found"); } else { set_menubar(gmenu); } } void ExampleApplication::on_activate() { //std::cout << "debug1: " << G_STRFUNC << std::endl; // The application has been started, so let's show a window. // A real application might want to reuse this window in on_open(), // when asked to open a file, if no changes have been made yet. create_window(); } void ExampleApplication::create_window() { auto win = new ExampleWindow(); //Make sure that the application runs for as long this window is still open: add_window(*win); //Delete the window when it is hidden. //That's enough for this simple example. win->signal_hide().connect(sigc::bind( sigc::mem_fun(*this, &ExampleApplication::on_window_hide), win)); win->set_show_menubar(); win->set_visible(true); } void ExampleApplication::on_window_hide(Gtk::Window* window) { delete window; } void ExampleApplication::on_menu_file_new_generic() { std::cout << "A File|New menu item was selected." << std::endl; } void ExampleApplication::on_menu_file_quit() { std::cout << G_STRFUNC << std::endl; quit(); // Not really necessary, when Gtk::Widget::set_visible(false) is called. // Gio::Application::quit() will make Gio::Application::run() return, // but it's a crude way of ending the program. The window is not removed // from the application. Neither the window's nor the application's // destructors will be called, because there will be remaining reference // counts in both of them. If we want the destructors to be called, we // must remove the window from the application. One way of doing this // is to hide the window. std::vector<Gtk::Window*> windows = get_windows(); if (windows.size() > 0) windows[0]->set_visible(false); // In this simple case, we know there is only one window. } void ExampleApplication::on_menu_help_about() { std::cout << "Help|About App was selected." << std::endl; }
File: examplewindow.cc
(For use with gtkmm 4)
#include "examplewindow.h" #include <iostream> ExampleWindow::ExampleWindow() : Gtk::ApplicationWindow(), m_Box(Gtk::Orientation::VERTICAL) { set_title("Main menu example"); set_default_size(300, 100); // ExampleApplication displays the menubar. Other stuff, such as a toolbar, // is put into the box. set_child(m_Box); // Create actions for menus and toolbars. // We can use add_action() because Gtk::ApplicationWindow derives from Gio::ActionMap. // This Action Map uses a "win." prefix for the actions. // Therefore, for instance, "win.copy", is used in ExampleApplication::on_startup() // to layout the menu. //Edit menu: add_action("copy", sigc::mem_fun(*this, &ExampleWindow::on_menu_others)); add_action("paste", sigc::mem_fun(*this, &ExampleWindow::on_menu_others)); add_action("something", sigc::mem_fun(*this, &ExampleWindow::on_menu_others)); //Choices menus, to demonstrate Radio items, //using our convenience methods for string and int radio values: m_refChoice = add_action_radio_string("choice", sigc::mem_fun(*this, &ExampleWindow::on_menu_choices), "a"); m_refChoiceOther = add_action_radio_integer("choiceother", sigc::mem_fun(*this, &ExampleWindow::on_menu_choices_other), 1); m_refToggle = add_action_bool("sometoggle", sigc::mem_fun(*this, &ExampleWindow::on_menu_toggle), false); //Help menu: add_action("about", sigc::mem_fun(*this, &ExampleWindow::on_menu_others)); //Create the toolbar and add it to a container widget: m_refBuilder = Gtk::Builder::create(); Glib::ustring ui_info = "<!-- Generated with glade 3.18.3 and then changed manually -->" "<interface>" " <object class='GtkBox' id='toolbar'>" " <property name='can_focus'>False</property>" " <child>" " <object class='GtkButton' id='toolbutton_new'>" " <property name='can_focus'>False</property>" " <property name='tooltip_text' translatable='yes'>New Standard</property>" " <property name='action_name'>app.newstandard</property>" " <property name='icon_name'>document-new</property>" " <property name='hexpand'>False</property>" " <property name='vexpand'>False</property>" " </object>" " </child>" " <child>" " <object class='GtkButton' id='toolbutton_quit'>" " <property name='can_focus'>False</property>" " <property name='tooltip_text' translatable='yes'>Quit</property>" " <property name='action_name'>app.quit</property>" " <property name='icon_name'>application-exit</property>" " <property name='hexpand'>False</property>" " <property name='vexpand'>False</property>" " </object>" " </child>" " </object>" "</interface>"; try { m_refBuilder->add_from_string(ui_info); } catch (const Glib::Error& ex) { std::cerr << "Building toolbar failed: " << ex.what(); } auto toolbar = m_refBuilder->get_widget<Gtk::Box>("toolbar"); if (!toolbar) g_warning("toolbar not found"); else m_Box.append(*toolbar); } ExampleWindow::~ExampleWindow() { } void ExampleWindow::on_menu_others() { std::cout << "A menu item was selected." << std::endl; } void ExampleWindow::on_menu_choices(const Glib::ustring& parameter) { //The radio action's state does not change automatically: m_refChoice->change_state(parameter); Glib::ustring message; if (parameter == "a") message = "Choice a was selected."; else message = "Choice b was selected."; std::cout << message << std::endl; } void ExampleWindow::on_menu_choices_other(int parameter) { //The radio action's state does not change automatically: m_refChoiceOther->change_state(parameter); Glib::ustring message; if (parameter == 1) message = "Choice 1 was selected."; else message = "Choice 2 was selected."; std::cout << message << std::endl; } void ExampleWindow::on_menu_toggle() { bool active = false; m_refToggle->get_state(active); //The toggle action's state does not change automatically: active = !active; m_refToggle->change_state(active); Glib::ustring message; if (active) message = "Toggle is active."; else message = "Toggle is not active."; std::cout << message << std::endl; }
File: main.cc
(For use with gtkmm 4)
#include "exampleapplication.h" int main(int argc, char* argv[]) { auto application = ExampleApplication::create(); // Start the application, showing the initial window, // and opening extra windows for any files that it is asked to open, // for instance as a command-line parameter. // run() will return when the last window has been closed by the user. const int status = application->run(argc, argv); return status; }
This program contains a menubar and a toolbar.
A class is derived from Gtk::Window
.
File: examplewindow.h
(For use with gtkmm 4)
#ifndef GTKMM_EXAMPLEWINDOW_H #define GTKMM_EXAMPLEWINDOW_H #include <gtkmm.h> class ExampleWindow : public Gtk::Window { public: ExampleWindow(const Glib::RefPtr<Gtk::Application>& app); virtual ~ExampleWindow(); private: //Signal handlers: void on_action_file_new(); void on_action_file_quit(); void on_action_others(); void on_action_toggle(); //Child widgets: Gtk::Box m_Box; Glib::RefPtr<Gtk::Builder> m_refBuilder; Glib::RefPtr<Gio::SimpleActionGroup> m_refActionGroup; Glib::RefPtr<Gio::SimpleAction> m_refActionRain; }; #endif //GTKMM_EXAMPLEWINDOW_H
File: examplewindow.cc
(For use with gtkmm 4)
#include "examplewindow.h" #include <gtkmm.h> #include <iostream> ExampleWindow::ExampleWindow(const Glib::RefPtr<Gtk::Application>& app) : m_Box(Gtk::Orientation::VERTICAL) { set_title("main_menu example"); set_default_size(200, 200); set_child(m_Box); //We can put a MenuBar at the top of the box and other stuff below it. //Define the actions: m_refActionGroup = Gio::SimpleActionGroup::create(); m_refActionGroup->add_action("new", sigc::mem_fun(*this, &ExampleWindow::on_action_file_new) ); m_refActionGroup->add_action("open", sigc::mem_fun(*this, &ExampleWindow::on_action_others) ); m_refActionRain = m_refActionGroup->add_action_bool("rain", sigc::mem_fun(*this, &ExampleWindow::on_action_toggle), false); m_refActionGroup->add_action("quit", sigc::mem_fun(*this, &ExampleWindow::on_action_file_quit) ); m_refActionGroup->add_action("cut", sigc::mem_fun(*this, &ExampleWindow::on_action_others) ); m_refActionGroup->add_action("copy", sigc::mem_fun(*this, &ExampleWindow::on_action_others) ); m_refActionGroup->add_action("paste", sigc::mem_fun(*this, &ExampleWindow::on_action_others) ); insert_action_group("example", m_refActionGroup); //Define how the actions are presented in the menus and toolbars: m_refBuilder = Gtk::Builder::create(); //Layout the actions in a menubar and toolbar: const Glib::ustring ui_info = "<interface>" " <menu id='menubar'>" " <submenu>" " <attribute name='label' translatable='yes'>_File</attribute>" " <section>" " <item>" " <attribute name='label' translatable='yes'>_New</attribute>" " <attribute name='action'>example.new</attribute>" " </item>" " <item>" " <attribute name='label' translatable='yes'>_Open</attribute>" " <attribute name='action'>example.open</attribute>" " </item>" " </section>" " <section>" " <item>" " <attribute name='label' translatable='yes'>Rain</attribute>" " <attribute name='action'>example.rain</attribute>" " </item>" " </section>" " <section>" " <item>" " <attribute name='label' translatable='yes'>_Quit</attribute>" " <attribute name='action'>example.quit</attribute>" " </item>" " </section>" " </submenu>" " <submenu>" " <attribute name='label' translatable='yes'>_Edit</attribute>" " <item>" " <attribute name='label' translatable='yes'>_Cut</attribute>" " <attribute name='action'>example.cut</attribute>" " </item>" " <item>" " <attribute name='label' translatable='yes'>_Copy</attribute>" " <attribute name='action'>example.copy</attribute>" " </item>" " <item>" " <attribute name='label' translatable='yes'>_Paste</attribute>" " <attribute name='action'>example.paste</attribute>" " </item>" " </submenu>" " </menu>" "</interface>"; // Set accelerator keys: app->set_accel_for_action("example.new", "<Primary>n"); app->set_accel_for_action("example.open", "<Primary>o"); app->set_accel_for_action("example.quit", "<Primary>q"); app->set_accel_for_action("example.cut", "<Primary>x"); app->set_accel_for_action("example.copy", "<Primary>c"); app->set_accel_for_action("example.paste", "<Primary>v"); try { m_refBuilder->add_from_string(ui_info); m_refBuilder->add_from_resource("/toolbar/toolbar.glade"); } catch(const Glib::Error& ex) { std::cerr << "Building menus and toolbar failed: " << ex.what(); } //Get the menubar: auto gmenu = m_refBuilder->get_object<Gio::Menu>("menubar"); if (!gmenu) g_warning("GMenu not found"); else { auto pMenuBar = Gtk::make_managed<Gtk::PopoverMenuBar>(gmenu); //Add the PopoverMenuBar to the window: m_Box.append(*pMenuBar); } //Get the toolbar and add it to a container widget: auto toolbar = m_refBuilder->get_widget<Gtk::Box>("toolbar"); if (!toolbar) g_warning("toolbar not found"); else m_Box.append(*toolbar); } ExampleWindow::~ExampleWindow() { } void ExampleWindow::on_action_file_quit() { set_visible(false); //Closes the main window to stop the app->make_window_and_run(). } void ExampleWindow::on_action_file_new() { std::cout << "A File|New menu item was selected." << std::endl; } void ExampleWindow::on_action_others() { std::cout << "A menu item was selected." << std::endl; } void ExampleWindow::on_action_toggle() { std::cout << "The toggle menu item was selected." << std::endl; bool active = false; m_refActionRain->get_state(active); //The toggle action's state does not change automatically: active = !active; m_refActionRain->change_state(active); Glib::ustring message; if(active) message = "Toggle is active."; else message = "Toggle is not active"; std::cout << message << std::endl; }
File: main.cc
(For use with gtkmm 4)
#include <gtkmm.h> #include "examplewindow.h" int main(int argc, char* argv[]) { auto app = Gtk::Application::create("org.gtkmm.example"); //Shows the window and returns when it is closed. return app->make_window_and_run<ExampleWindow>(argc, argv, app); }
File: toolbar.gresource.xml
(For use with gtkmm 4)
<?xml version="1.0" encoding="UTF-8"?> <gresources> <gresource prefix="/toolbar"> <file preprocess="xml-stripblanks">toolbar.glade</file> <file>rain.png</file> </gresource> </gresources>
File: examplewindow.h
(For use with gtkmm 4)
#ifndef GTKMM_EXAMPLEWINDOW_H #define GTKMM_EXAMPLEWINDOW_H #include <gtkmm.h> #include <memory> class ExampleWindow : public Gtk::Window { public: ExampleWindow(const Glib::RefPtr<Gtk::Application>& app); virtual ~ExampleWindow(); protected: //Signal handlers: void on_label_pressed(int n_press, double x, double y); void on_menu_file_popup_generic(); //Child widgets: Gtk::Box m_Box; Gtk::Label m_Label; Gtk::PopoverMenu m_MenuPopup; Glib::RefPtr<Gtk::Builder> m_refBuilder; Glib::RefPtr<Gtk::GestureClick> m_refGesture; }; #endif //GTKMM_EXAMPLEWINDOW_H
File: examplewindow.cc
(For use with gtkmm 4)
#include "examplewindow.h" #include <iostream> ExampleWindow::ExampleWindow(const Glib::RefPtr<Gtk::Application>& app) : m_Box(Gtk::Orientation::VERTICAL), m_Label("Right-click to see the popup menu.") { set_title("popup example"); set_default_size(200, 200); set_child(m_Box); // Catch button_press events: m_Box.append(m_Label); m_Label.set_expand(); m_refGesture = Gtk::GestureClick::create(); m_refGesture->set_button(GDK_BUTTON_SECONDARY); m_refGesture->signal_pressed().connect( sigc::mem_fun(*this, &ExampleWindow::on_label_pressed)); m_Label.add_controller(m_refGesture); //Create actions: auto refActionGroup = Gio::SimpleActionGroup::create(); //File|New sub menu: //These menu actions would normally already exist for a main menu, because a //context menu should not normally contain menu items that are only available //via a context menu. refActionGroup->add_action("edit", sigc::mem_fun(*this, &ExampleWindow::on_menu_file_popup_generic)); refActionGroup->add_action("process", sigc::mem_fun(*this, &ExampleWindow::on_menu_file_popup_generic)); refActionGroup->add_action("remove", sigc::mem_fun(*this, &ExampleWindow::on_menu_file_popup_generic)); insert_action_group("examplepopup", refActionGroup); // Set accelerator keys: app->set_accel_for_action("examplepopup.edit", "<Primary>e"); app->set_accel_for_action("examplepopup.process", "<Primary>p"); app->set_accel_for_action("examplepopup.remove", "<Primary>r"); m_refBuilder = Gtk::Builder::create(); //Layout the actions in a menubar and toolbar: Glib::ustring ui_info = "<interface>" " <menu id='menu-examplepopup'>" " <section>" " <item>" " <attribute name='label' translatable='yes'>Edit</attribute>" " <attribute name='action'>examplepopup.edit</attribute>" " </item>" " <item>" " <attribute name='label' translatable='yes'>Process</attribute>" " <attribute name='action'>examplepopup.process</attribute>" " </item>" " <item>" " <attribute name='label' translatable='yes'>Remove</attribute>" " <attribute name='action'>examplepopup.remove</attribute>" " </item>" " </section>" " </menu>" "</interface>"; try { m_refBuilder->add_from_string(ui_info); } catch(const Glib::Error& ex) { std::cerr << "building menus failed: " << ex.what(); } //Get the menu: auto gmenu = m_refBuilder->get_object<Gio::Menu>("menu-examplepopup"); if(!gmenu) g_warning("GMenu not found"); m_MenuPopup.set_parent(m_Label); m_MenuPopup.set_menu_model(gmenu); m_MenuPopup.set_has_arrow(false); } ExampleWindow::~ExampleWindow() { m_MenuPopup.unparent(); } void ExampleWindow::on_menu_file_popup_generic() { std::cout << "A popup menu item was selected." << std::endl; } void ExampleWindow::on_label_pressed(int /* n_press */, double x, double y) { const Gdk::Rectangle rect(x, y, 1, 1); m_MenuPopup.set_pointing_to(rect); m_MenuPopup.popup(); }
File: main.cc
(For use with gtkmm 4)
#include "examplewindow.h" #include <gtkmm/application.h> int main(int argc, char *argv[]) { auto app = Gtk::Application::create("org.gtkmm.example"); //Shows the window and returns when it is closed. return app->make_window_and_run<ExampleWindow>(argc, argv, app); }