#ifndef GTKMM_EXAMPLE_HELLOWORLD_H
#define GTKMM_EXAMPLE_HELLOWORLD_H
#include <gtkmm/box.h>
#include <gtkmm/button.h>
#include <gtkmm/window.h>
class HelloWorld : public Gtk::Window
public:
HelloWorld();
~HelloWorld() override;
protected:
// Signal handlers:
// Our new improved on_button_clicked().
void on_button_clicked(const Glib::ustring& data);
// Child widgets:
Gtk::Box m_box1;
Gtk::Button m_button1, m_button2;
#endif // GTKMM_EXAMPLE_HELLOWORLD_H
File: main.cc (For use with gtkmm 4)
#include "helloworld.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<HelloWorld>(argc, argv);
File: helloworld.cc (For use with gtkmm 4)
#include "helloworld.h"
#include <iostream>
HelloWorld::HelloWorld()
: m_button1("Button 1"),
m_button2("Button 2")
// This just sets the title of our new window.
set_title("Hello Buttons!");
// Sets the margin around the box.
m_box1.set_margin(10);
// put the box into the main window.
set_child(m_box1);
// Now when the button is clicked, we call the on_button_clicked() function
// with a pointer to "button 1" as its argument.
m_button1.signal_clicked().connect(sigc::bind(
sigc::mem_fun(*this, &HelloWorld::on_button_clicked), "button 1"));
// We use Gtk::Box::append() to pack this button into the box,
// which has been packed into the window.
// A widget's default behaviour is not to expand if extra space is available.
// A container widget by default expands if any of the contained widgets
// wants to expand.
m_box1.append(m_button1);
m_button1.set_expand();
// call the same signal handler with a different argument,
// passing a pointer to "button 2" instead.
m_button2.signal_clicked().connect(sigc::bind(
sigc::mem_fun(*this, &HelloWorld::on_button_clicked), "button 2"));
m_box1.append(m_button2);
m_button2.set_expand();
// Gtk::Widget::show() is seldom needed. All widgets are visible by default.
HelloWorld::~HelloWorld()
// Our new improved signal handler. The data passed to this method is
// printed to stdout.
void HelloWorld::on_button_clicked(const Glib::ustring& data)
std::cout << "Hello World - " << data << " was pressed" << std::endl;
生成并运行这个程序后,请尝试调整窗口的大小查看其行为。此外在阅读盒子(Boxes)小节时请尝试使用set_expand()、set_hexpand()、set_vexpand()、set_halign()和set_valign()方法。
如上例所示,这些都是不可见容器我们可以将容器装入其中。将部件装填到水平盒中的时候部件从左到右水平插入。将部件装填到垂直盒中的时候部件从上到下垂直插入。你可以在盒中或盒侧组合使用盒以达到你所需的效果。
9.2.3.1. 添加部件
9.2.3.2. Gtk::Application和命令行选项
9.2.3.3. 示例
9.2.3.1.1. 子部件装填选项
9.2.3.1.2. 容器装填选项
append()方法将部件放置于这些容器中。它们将从顶部开始。按Box的垂直方向向下移动,或者按Box的水平方向从左向右移动。如果你不愿意按此顺序添加子部件,请使用insert_child_after()或insert_child_at_start()方法。我们将在示例中使用append()。
有几个选项可以控制部件的打包方式,但是初次使用可能会难以理清效果。你可以在子部件上使用set_expand()、set_hexpand()、set_vexpand()、set_halign()、set_valign()方法修改装填策略。如果你感到困难,可以试试gladeGUI设计器,看看能不能对你有所帮助。你甚至可以使用Gtk::BuilderAPI在运行时加载GUI。
如图所示,有五种不同的基本样式。
Figure 9-6 组装盒1
每一行包含一个有多个按钮的水平Box。行中的每一个按钮都使用相同参数的set_hexpand()、set_halign()、set_margin_start()和set_margin_end()方法装入Box。
这是Box部件的构造函数,以及设置每个容器的打包选项的方法:
Gtk::Box(Gtk::Orientation orientation = Gtk::Orientation::HORIZONTAL, int spacing = 0);
void set_orientation(Gtk::Orientation orientation);
void set_spacing(int spacing);
void set_homogeneous(bool homogeneous = true);
将true传递给set_homogeneous()方法将导致容器部件所包含的所有部件都有一样的大小。spacing是每个部件之间要保留的最小像素数。
间距(创建盒的时候设置)与边距(为每个子部件分别设置)的区别是:在对象之间添加间距,在部件的一侧或多侧添加边距。下图能使你更清楚的理解这一点。所显示的边距是该行中每个按钮的左右边距。
Figure 9-7 组装盒2
下面的示例程序需要一个命令行选项。源代码展示了两种Gtk::Application处理命令行选项的方式。
在main()中处理选项并且通过设置argc = 1将他们从Gtk::Application中隐藏,然后调用Gtk::Application::run()。
将所有的命令行选项传递给Gtk::Application::run()并为Gtk::Application::create()方法设置标志Gio::Application::Flags::HANDLES_COMMAND_LINE。
你必须在调用signal_command_line().connect()时设置可选参数after = false,因为此时必须在默认的信号处理程序之前调用你的信号处理程序。你还必须调用Gio::Application::activate()处理程序,除非你希望你的应用程序不显示主窗口直接退出(Gio::Application是Gtk::Application的基类)。
这是上述截图所运行示例的源代码。在运行此示例时请提供1到3之间的数字作为命令行选项以查看正在使用不同装填选项的行为。
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(int which);
virtual ~ExampleWindow();
protected:
//Signal handlers:
void on_button_quit_clicked();
//Child widgets:
Gtk::Button m_button;
Gtk::Box m_box1;
Gtk::Box m_boxQuit;
Gtk::Button m_buttonQuit;
Gtk::Label m_Label1, m_Label2;
Gtk::Separator m_separator1, m_separator2;
#endif //GTKMM_EXAMPLEWINDOW_H
File: packbox.h (For use with gtkmm 4)
#ifndef GTKMM_EXAMPLE_PACKBOX_H
#define GTKMM_EXAMPLE_PACKBOX_H
#include <gtkmm.h>
class PackBox : public Gtk::Box
public:
PackBox(bool homogeneous = false, int spacing = 0, bool expand = false,
Gtk::Align align = Gtk::Align::FILL, int margin = 0);
protected:
Gtk::Button m_buttons[4];
#endif //GTKMM_EXAMPLE_PACKBOX_H
File: main.cc (For use with gtkmm 4)
#include "examplewindow.h"
#include <gtkmm/application.h>
#include <iostream>
#include <cstdlib>
#define GTK_APPLICATION_RECEIVES_COMMAND_LINE_ARGUMENTS 0
#if GTK_APPLICATION_RECEIVES_COMMAND_LINE_ARGUMENTS
namespace
int on_command_line(const Glib::RefPtr<Gio::ApplicationCommandLine>& command_line,
Glib::RefPtr<Gtk::Application>& app)
int argc = 0;
char** argv = command_line->get_arguments(argc);
for (int i = 0; i < argc; ++i)
std::cout << "argv[" << i << "] = " << argv[i] << std::endl;
app->activate(); // Without activate() the window won't be shown.
return EXIT_SUCCESS;
} // anonymous namespace
#endif
int main(int argc, char *argv[])
if (argc != 2)
std::cerr << "Usage: example <num>, where <num> is 1, 2, or 3." << std::endl;
return EXIT_FAILURE;
int argc1 = argc;
#if GTK_APPLICATION_RECEIVES_COMMAND_LINE_ARGUMENTS
// The Gio::Application::Flags::HANDLES_COMMAND_LINE flag and the
// on_command_line() signal handler are not necessary. This program is simpler
// without them, and with argc = 1 in the call to Gtk::Application::make_window_and_run().
// They are included to show a program with Gio::Application::Flags::HANDLES_COMMAND_LINE.
// Gio::Application::Flags::NON_UNIQUE makes it possible to run several instances of
// this application simultaneously.
auto app = Gtk::Application::create(
"org.gtkmm.example", Gio::Application::Flags::HANDLES_COMMAND_LINE | Gio::Application::Flags::NON_UNIQUE);
// Note after = false.
// Only one signal handler is invoked. This signal handler must run before
// the default signal handler, or else it won't run at all.
app->signal_command_line().connect(sigc::bind(sigc::ptr_fun(&on_command_line), app), false);
#else
// Gio::Application::Flags::NON_UNIQUE makes it possible to run several instances of
// this application simultaneously.
argc1 = 1; // Don't give the command line arguments to Gtk::Application.
auto app = Gtk::Application::create("org.gtkmm.example", Gio::Application::Flags::NON_UNIQUE);
#endif
// Shows the window and returns when it is closed.
return app->make_window_and_run<ExampleWindow>(argc1, argv, std::atoi(argv[1]));
File: examplewindow.cc (For use with gtkmm 4)
#include <iostream>
#include "examplewindow.h"
#include "packbox.h"
ExampleWindow::ExampleWindow(int which)
: m_box1(Gtk::Orientation::VERTICAL),
m_buttonQuit("Quit")
set_title("Gtk::Box example");
m_separator1.set_margin_top(5);
m_separator1.set_margin_bottom(5);
m_separator2.set_margin_top(5);
m_separator2.set_margin_bottom(5);
switch(which)
case 1:
m_Label1.set_text("Gtk::Box(Gtk::Orientation::HORIZONTAL, 0); set_homogeneous(false);");
// Align the label to the left side.
m_Label1.set_halign(Gtk::Align::START);
m_Label1.set_valign(Gtk::Align::START);
// Pack the label into the vertical box (vbox box1). Remember that
// widgets added to a vbox will be packed one on top of the other in
// order.
m_box1.append(m_Label1);
// Create a PackBox - homogeneous = false, spacing = 0,
// expand = false, Gtk::Align::FILL, margin = 0
// These are the default values.
auto pPackBox = Gtk::make_managed<PackBox>();
m_box1.append(*pPackBox);
// Create a PackBox - homogeneous = false, spacing = 0,
// expand = true, Gtk::Align::CENTER, margin = 0
pPackBox = Gtk::make_managed<PackBox>(false, 0, true, Gtk::Align::CENTER);
m_box1.append(*pPackBox);
// Create a PackBox - homogeneous = false, spacing = 0,
// expand = true, Gtk::Align::FILL, margin = 0
pPackBox = Gtk::make_managed<PackBox>(false, 0, true);
m_box1.append(*pPackBox);
// pack the separator into the vbox. Remember each of these
// widgets are being packed into a vbox, so they'll be stacked
// vertically.
m_box1.append(m_separator1);
// create another new label, and show it.
m_Label2.set_text("Gtk::Box(Gtk::Orientation::HORIZONTAL, 0); set_homogeneous(true);");
m_Label2.set_halign(Gtk::Align::START);
m_Label2.set_valign(Gtk::Align::START);
m_box1.append(m_Label2);
// Args are: homogeneous, spacing, expand, align, margin
pPackBox = Gtk::make_managed<PackBox>(true, 0, true, Gtk::Align::CENTER);
m_box1.append(*pPackBox);
// Args are: homogeneous, spacing, expand, align, margin
pPackBox = Gtk::make_managed<PackBox>(true, 0, true);
m_box1.append(*pPackBox);
m_box1.append(m_separator2);
break;
case 2:
m_Label1.set_text("Gtk::Box(Gtk::Orientation::HORIZONTAL, 10); set_homogeneous(false);");
m_Label1.set_halign(Gtk::Align::START);
m_Label1.set_valign(Gtk::Align::START);
m_box1.append(m_Label1);
auto pPackBox = Gtk::make_managed<PackBox>(false, 10, true, Gtk::Align::CENTER);
m_box1.append(*pPackBox);
pPackBox = Gtk::make_managed<PackBox>(false, 10, true);
m_box1.append(*pPackBox);
m_box1.append(m_separator1);
m_Label2.set_text("Gtk::Box(Gtk::Orientation::HORIZONTAL, 0); set_homogeneous(false);");
m_Label2.set_halign(Gtk::Align::START);
m_Label2.set_valign(Gtk::Align::START);
m_box1.append(m_Label2);
pPackBox = Gtk::make_managed<PackBox>(false, 0, false, Gtk::Align::FILL, 10);
m_box1.append(*pPackBox);
pPackBox = Gtk::make_managed<PackBox>(false, 0, true, Gtk::Align::FILL, 10);
m_box1.append(*pPackBox);
m_box1.append(m_separator2);
break;
case 3:
// This demonstrates the ability to use Gtk::Align::END to
// right justify widgets. First, we create a new box as before.
auto pPackBox = Gtk::make_managed<PackBox>();
// create the label that will be put at the end.
m_Label1.set_text("end");
// pack it using Gtk::Align::END, so it is put on the right side
// of the PackBox.
m_Label1.set_halign(Gtk::Align::END);
m_Label1.set_hexpand(true);
pPackBox->append(m_Label1);
m_box1.append(*pPackBox);
// This explicitly sets the separator to 700 pixels wide by 5 pixels
// high. This is so the hbox we created will also be 700 pixels wide,
// and the "end" label will be separated from the other labels in the
// hbox. Otherwise, all the widgets in the hbox would be packed as
// close together as possible.
m_separator1.set_size_request(700, 5);
// pack the separator into the vbox.
m_box1.append(m_separator1);
break;
default:
std::cerr << "Unexpected command-line option." << std::endl;
break;
// Connect the signal to hide the window:
m_buttonQuit.signal_clicked().connect( sigc::mem_fun(*this,
&ExampleWindow::on_button_quit_clicked) );
// pack the button into the quitbox.
m_boxQuit.append(m_buttonQuit);
m_buttonQuit.set_hexpand(true);
m_buttonQuit.set_halign(Gtk::Align::CENTER);
m_box1.append(m_boxQuit);
// pack the vbox (box1) which now contains all our widgets, into the
// main window.
set_child(m_box1);
ExampleWindow::~ExampleWindow()
void ExampleWindow::on_button_quit_clicked()
hide();
File: packbox.cc
(For use with gtkmm 4)
#include "packbox.h"
#include <map>
namespace
const std::map<Gtk::Align, Glib::ustring> align_string = {
{Gtk::Align::FILL, "Gtk::Align::FILL"},
{Gtk::Align::START, "Gtk::Align::START"},
{Gtk::Align::END, "Gtk::Align::END"},
{Gtk::Align::CENTER, "Gtk::Align::CENTER"},
{Gtk::Align::BASELINE, "Gtk::Align::BASELINE"},
PackBox::PackBox(bool homogeneous, int spacing, bool expand, Gtk::Align align, int margin)
: Gtk::Box(Gtk::Orientation::HORIZONTAL, spacing)
set_homogeneous(homogeneous);
m_buttons[0].set_label("box.append(button);");
m_buttons[1].set_label("expand=" + Glib::ustring(expand ? "true" : "false"));
m_buttons[2].set_label(align_string.at(align));
m_buttons[3].set_label("margin=" + Glib::ustring::format(margin));
for (auto& button : m_buttons)
append(button);
button.set_hexpand(expand);
button.set_halign(align);
button.set_margin_start(margin);
button.set_margin_end(margin);
Grid在行与列中动态的摆放他的子部件。不需要在其构造函数当中指定维数。
使用attach()方法可以跨越多行/列插入子部件,也可以使用attach_next_to()将子部件插入已经存在于网格中的部件的旁边。可以通过调用set_row_homogeneous()和set_column_homogeneous()令网格中所有子部件具有一致的高度或宽度。
你可以设置子部件的margin和expand属性用以控制调整网格大小时它们之间的间距。
9.2.4.1. 示例
本示例创建一个窗口其中具有一个包含三个按钮的网格。前两个按钮位于最上行并从左向右排列。第三个按钮位于第一个按钮的下方,位于最下行并横跨两列。
Figure 9-8 网格(Grid)
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();
virtual ~ExampleWindow();
private:
// Signal handlers:
void on_button_quit();
void on_button_numbered(const Glib::ustring& data);
// Child widgets:
Gtk::Grid m_grid;
Gtk::Button m_button_1, m_button_2, m_button_quit;
#endif /* GTKMM_EXAMPLEWINDOW_H */
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);
File: examplewindow.cc (For use with gtkmm 4)
#include <iostream>
#include "examplewindow.h"
ExampleWindow::ExampleWindow()
: m_button_1("button 1"),
m_button_2("button 2"),
m_button_quit("Quit")
set_title("Gtk::Grid");
m_grid.set_margin(12);
set_child(m_grid);
m_grid.attach(m_button_1, 0, 0);
m_grid.attach(m_button_2, 1, 0);
m_grid.attach_next_to(m_button_quit, m_button_1, Gtk::PositionType::BOTTOM, 2, 1);
m_button_1.signal_clicked().connect(
sigc::bind( sigc::mem_fun(*this, &ExampleWindow::on_button_numbered), "button 1") );
m_button_2.signal_clicked().connect(
sigc::bind( sigc::mem_fun(*this, &ExampleWindow::on_button_numbered), "button 2") );
m_button_quit.signal_clicked().connect(sigc::mem_fun(*this,
&ExampleWindow::on_button_quit) );
ExampleWindow::~ExampleWindow()
void ExampleWindow::on_button_quit()
hide();
ExampleWindow::on_button_numbered(const Glib::ustring& data)
std::cout << data << " was pressed" << std::endl;
Notebook有一组堆叠好的pages,每个页面(page)包含一个部件。带标签的tabs允许用户选择页面。Notebook一次只显示一页,这样可以将好几组部件放于很小的空间当中。例如他们经常在首选项对话框中使用。
使用append_page()、prepend_page()和insert_page()方法可以添加带标签的页面到Notebook中,你需要为这些方法提供子部件和标签名。
如果你想知道当前可见的页面是那一个,可以使用get_current_page()方法。该方法返回一个页码,你可以将页码传递给get_nth_page()获取指向该页当前子部件的指针。
要以编程方式改变所选的页面,请使用set_current_page()方法。
9.2.5.1. 示例
Figure 9-9 笔记本(Notebook)
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();
virtual ~ExampleWindow();
protected:
//Signal handlers:
void on_button_quit();
void on_notebook_switch_page(Gtk::Widget* page, guint page_num);
//Child widgets:
Gtk::Box m_VBox;
Gtk::Notebook m_Notebook;
Gtk::Label m_Label1, m_Label2;
Gtk::Box m_ButtonBox;
Gtk::Button m_Button_Quit;
#endif //GTKMM_EXAMPLEWINDOW_H
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);
File: examplewindow.cc (For use with gtkmm 4)
#include <iostream>
#include "examplewindow.h"
ExampleWindow::ExampleWindow()
: m_VBox(Gtk::Orientation::VERTICAL),
m_Label1("Contents of tab 1"),
m_Label2("Contents of tab 2"),
m_Button_Quit("Quit")
set_title("Gtk::Notebook example");
set_default_size(400, 200);
m_VBox.set_margin(10);
set_child(m_VBox);
//Add the Notebook, with the button underneath:
m_Notebook.set_margin(10);
m_Notebook.set_expand();
m_VBox.append(m_Notebook);
m_VBox.append(m_ButtonBox);
m_ButtonBox.append(m_Button_Quit);
m_Button_Quit.set_hexpand(true);
m_Button_Quit.set_halign(Gtk::Align::CENTER);
m_Button_Quit.signal_clicked().connect(sigc::mem_fun(*this,
&ExampleWindow::on_button_quit) );
//Add the Notebook pages:
m_Notebook.append_page(m_Label1, "First");
m_Notebook.append_page(m_Label2, "Second");
m_Notebook.signal_switch_page().connect(sigc::mem_fun(*this,
&ExampleWindow::on_notebook_switch_page) );
ExampleWindow::~ExampleWindow()
void ExampleWindow::on_button_quit()
hide();
void ExampleWindow::on_notebook_switch_page(Gtk::Widget* /* page */, guint page_num)
std::cout << "Switched to tab with index " << page_num << std::endl;
//You can also use m_Notebook.get_current_page() to get this index.
Assistant将一个复杂的操作切分为数个步骤。每个步骤都是一个页面,包含一个标题、一个子部件和一个可操作区域。助手的操作区域有一个导航按钮,这些按钮会根据页面的类型自动更新(使用set_page_type()设置页面类型)。
使用append_page()、prepend_page和insert_page()方法可以向Assistant添加页面,你需要每个页面提供子部件。
要确定当前可见的页面,请使用get_current_page()方法,然后将返回值传递给get_nth_page(),其会返回一个指向实际部件的指针。要想用编程的方式改变当前页,请使用set_current_page()方法。
要为页面设置标题,请使用set_page_title()方法。
要将部件添加到操作区域,请使用add_action_widget()方法。他们将与默认按钮一并被装填。使用remove_action_widget()方法可以删除部件。
9.2.6.1. 示例
Figure 9-10 助手(Assistant)
File: examplewindow.h (For use with gtkmm 4)
#ifndef GTKMM_EXAMPLEWINDOW_H
#define GTKMM_EXAMPLEWINDOW_H
#include "exampleassistant.h"
#include <gtkmm.h>
class ExampleWindow : public Gtk::Window
public:
ExampleWindow();
virtual ~ExampleWindow();
private:
// Signal handlers:
void on_button_clicked();
void on_assistant_apply();
// Child widgets:
Gtk::Grid m_grid;
Gtk::Button m_button;
Gtk::Label m_label1, m_label2;
Gtk::CheckButton m_check;
Gtk::Entry m_entry;
ExampleAssistant m_assistant;
#endif /* GTKMM_EXAMPLEWINDOW_H */
File: exampleassistant.h (For use with gtkmm 4)
#ifndef GTKMM_EXAMPLEASSISTANT_H
#define GTKMM_EXAMPLEASSISTANT_H
#include <gtkmm.h>
class ExampleAssistant : public Gtk::Assistant
public:
ExampleAssistant();
virtual ~ExampleAssistant();
void get_result(bool& check_state, Glib::ustring& entry_text);
private:
// Signal handlers:
void on_assistant_apply();
void on_assistant_cancel();
void on_assistant_close();
void on_assistant_prepare(Gtk::Widget* widget);
void on_entry_changed();
// Member functions:
void print_status();
// Child widgets:
Gtk::Box m_box;
Gtk::Label m_label1, m_label2;
Gtk::CheckButton m_check;
Gtk::Entry m_entry;
#endif /* GTKMM_EXAMPLEASSISTANT_H */
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);
File: examplewindow.cc (For use with gtkmm 4)
#include "examplewindow.h"
#include "exampleassistant.h"
ExampleWindow::ExampleWindow()
: m_button("Show the assistant"),
m_label1("State of assistant checkbutton:", Gtk::Align::START, Gtk::Align::CENTER),
m_label2("Contents of assistant entry:", Gtk::Align::START, Gtk::Align::CENTER)
set_title("Gtk::Assistant example");
m_grid.set_row_homogeneous(true);
m_grid.set_column_spacing(5);
m_grid.set_margin(12);
m_grid.attach(m_button, 0, 0, 2, 1);
m_button.set_hexpand(true);
m_button.set_valign(Gtk::Align::CENTER);
m_grid.attach(m_label1, 0, 1, 1, 1);
m_grid.attach(m_label2, 0, 2, 1, 1);
m_grid.attach(m_check, 1, 1, 1, 1);
m_check.set_halign(Gtk::Align::START);
m_grid.attach(m_entry, 1, 2, 1, 1);
m_entry.set_hexpand(true);
set_child(m_grid);
m_button.signal_clicked().connect(sigc::mem_fun(*this,
&ExampleWindow::on_button_clicked));
m_assistant.signal_apply().connect(sigc::mem_fun(*this,
&ExampleWindow::on_assistant_apply));
m_check.set_sensitive(false);
m_entry.set_sensitive(false);
ExampleWindow::~ExampleWindow()
void ExampleWindow::on_assistant_apply()
bool check_state;
Glib::ustring entry_text;
m_assistant.get_result(check_state, entry_text);
m_check.set_active(check_state);
m_entry.set_text(entry_text);
void ExampleWindow::on_button_clicked()
m_assistant.show();
File: exampleassistant.cc (For use with gtkmm 4)
#include <iostream>
#include "exampleassistant.h"
ExampleAssistant::ExampleAssistant()
: m_box(Gtk::Orientation::HORIZONTAL, 12),
m_label1("Type text to allow the assistant to continue:"),
m_label2("Confirmation page"),
m_check("Optional extra information")
set_title("Gtk::Assistant example");
set_default_size(400, 200);
m_box.append(m_label1);
m_box.append(m_entry);
m_label1.set_wrap();
m_label1.set_valign(Gtk::Align::CENTER);
m_entry.set_valign(Gtk::Align::CENTER);
append_page(m_box);
append_page(m_check);
append_page(m_label2);
set_page_title(*get_nth_page(0), "Page 1");
set_page_title(*get_nth_page(1), "Page 2");
set_page_title(*get_nth_page(2), "Confirmation");
set_page_complete(m_check, true);
set_page_complete(m_label2, true);
set_page_type(m_box, Gtk::AssistantPage::Type::INTRO);
set_page_type(m_label2, Gtk::AssistantPage::Type::CONFIRM);
signal_apply().connect(sigc::mem_fun(*this,
&ExampleAssistant::on_assistant_apply));
signal_cancel().connect(sigc::mem_fun(*this,
&ExampleAssistant::on_assistant_cancel));
signal_close().connect(sigc::mem_fun(*this,
&ExampleAssistant::on_assistant_close));
signal_prepare().connect(sigc::mem_fun(*this,
&ExampleAssistant::on_assistant_prepare));
m_entry.signal_changed().connect(sigc::mem_fun(*this,
&ExampleAssistant::on_entry_changed));
ExampleAssistant::~ExampleAssistant()
void ExampleAssistant::get_result(bool& check_state, Glib::ustring& entry_text)
check_state = m_check.get_active();
entry_text = m_entry.get_text();
void ExampleAssistant::on_assistant_apply()
std::cout << "Apply was clicked";
print_status();
void ExampleAssistant::on_assistant_cancel()
std::cout << "Cancel was clicked";
print_status();
hide();
void ExampleAssistant::on_assistant_close()
std::cout << "Assistant was closed";
print_status();
hide();
void ExampleAssistant::on_assistant_prepare(Gtk::Widget* /* widget */)
set_title(Glib::ustring::compose("Gtk::Assistant example (Page %1 of %2)",
get_current_page() + 1, get_n_pages()));
void ExampleAssistant::on_entry_changed()
// The page is only complete if the entry contains text.
if(m_entry.get_text_length())
set_page_complete(m_box, true);
set_page_complete(m_box, false);
void ExampleAssistant::print_status()
std::cout << ", entry contents: \"" << m_entry.get_text()
<< "\", checkbutton status: " << m_check.get_active() << std::endl;