Table of Contents
Container widgets, like other widgets, derive from Gtk::Widget
.
Some container widgets, such as Gtk::Grid
can hold many
child widgets, so these typically have more complex interfaces. Others, such as
Gtk::Frame
contain only one child widget.
Most single-item container widgets have set_child()
and unset_child()
methods for the child widget.
Gtk::Button
and Gtk::Window
are
technically single-item containers, but we have discussed them already elsewhere.
We also discuss the Gtk::Paned
widget, which allows you
to divide a window into two separate "panes". This widget actually contains
two child widgets, but the number is fixed so it seems appropriate.
Frames can enclose one or a group of widgets within a box, optionally with a
title. For instance, you might place a group of
ToggleButton
s or CheckButton
s in a
Frame
.
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:
//Child widgets:
Gtk::Frame m_Frame;
};
#endif //GTKMM_EXAMPLEWINDOW_H
File: examplewindow.cc
(For use with gtkmm 4)
#include "examplewindow.h"
ExampleWindow::ExampleWindow()
{
/* Set some window properties */
set_title("Frame Example");
set_size_request(300, 300);
/* Sets the margin around the frame. */
m_Frame.set_margin(10);
set_child(m_Frame);
/* Set the frames label */
m_Frame.set_label("Gtk::Frame Widget");
/* Align the label at the right of the frame */
m_Frame.set_label_align(Gtk::Align::END);
}
ExampleWindow::~ExampleWindow()
{
}
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);
}
Panes divide a widget into two halves, separated by a moveable divider. The two halves (panes) can be oriented either horizontally (side by side) or vertically (one above the other).
Unlike the other widgets in this section, pane widgets contain not one but two
child widgets, one in each pane. Therefore, you should use
set_start_child()
and set_end_child()
instead of a set_child()
method.
You can adjust the position of the divider using the
set_position()
method, and you will probably need to do
so.
File: examplewindow.h
(For use with gtkmm 4)
#ifndef GTKMM_EXAMPLEWINDOW_H
#define GTKMM_EXAMPLEWINDOW_H
#include "messageslist.h"
#include "messagetext.h"
#include <gtkmm.h>
class ExampleWindow : public Gtk::Window
{
public:
ExampleWindow();
virtual ~ExampleWindow();
protected:
//Child widgets:
Gtk::Paned m_VPaned;
MessagesList m_MessagesList;
MessageText m_MessageText;
};
#endif //GTKMM_EXAMPLEWINDOW_H
File: messageslist.h
(For use with gtkmm 4)
#ifndef GTKMM_EXAMPLE_MESSAGESLIST_H
#define GTKMM_EXAMPLE_MESSAGESLIST_H
#include <gtkmm.h>
class MessagesList: public Gtk::ScrolledWindow
{
public:
MessagesList();
~MessagesList() override;
protected:
// Signal handlers:
void on_setup_message(const Glib::RefPtr<Gtk::ListItem>& list_item);
void on_bind_message(const Glib::RefPtr<Gtk::ListItem>& list_item);
Glib::RefPtr<Gtk::StringList> m_refStringList; // The List Model.
Gtk::ListView m_ListView; // The List View.
};
#endif //GTKMM_EXAMPLE_MESSAGESLIST_H
File: messagetext.h
(For use with gtkmm 4)
#ifndef GTKMM_EXAMPLE_MESSAGETEXT_H
#define GTKMM_EXAMPLE_MESSAGETEXT_H
#include <gtkmm.h>
class MessageText : public Gtk::ScrolledWindow
{
public:
MessageText();
virtual ~MessageText();
void insert_text();
protected:
Gtk::TextView m_TextView;
};
#endif //GTKMM_EXAMPLE_MESSAGETEXT_H
File: examplewindow.cc
(For use with gtkmm 4)
#include "examplewindow.h"
ExampleWindow::ExampleWindow()
: m_VPaned(Gtk::Orientation::VERTICAL)
{
set_title ("Paned Windows");
set_default_size(450, 400);
m_VPaned.set_margin(10);
/* Add a vpaned widget to our toplevel window */
set_child(m_VPaned);
/* Now add the contents of the two halves of the window */
m_VPaned.set_start_child(m_MessagesList);
m_VPaned.set_end_child(m_MessageText);
}
ExampleWindow::~ExampleWindow()
{
}
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: messageslist.cc
(For use with gtkmm 4)
#include "messageslist.h"
MessagesList::MessagesList()
{
/* Create a new scrolled window, with scrollbars only if needed */
set_policy(Gtk::PolicyType::AUTOMATIC, Gtk::PolicyType::AUTOMATIC);
set_child(m_ListView);
/* create list store */
m_refStringList = Gtk::StringList::create({});
auto selection_model = Gtk::SingleSelection::create(m_refStringList);
m_ListView.set_model(selection_model);
/* Add some messages to the window */
for (int i = 1; i <= 10; ++i)
m_refStringList->append(Glib::ustring::format("message #", i));
// Create a ListItemFactory to use for populating list items.
auto factory = Gtk::SignalListItemFactory::create();
factory->signal_setup().connect(sigc::mem_fun(*this, &MessagesList::on_setup_message));
factory->signal_bind().connect(sigc::mem_fun(*this, &MessagesList::on_bind_message));
m_ListView.set_factory(factory);
}
MessagesList::~MessagesList()
{
}
void MessagesList::on_setup_message(const Glib::RefPtr<Gtk::ListItem>& list_item)
{
auto label = Gtk::make_managed<Gtk::Label>();
label->set_halign(Gtk::Align::START);
list_item->set_child(*label);
}
void MessagesList::on_bind_message(const Glib::RefPtr<Gtk::ListItem>& list_item)
{
auto pos = list_item->get_position();
if (pos == GTK_INVALID_LIST_POSITION)
return;
auto label = dynamic_cast<Gtk::Label*>(list_item->get_child());
if (!label)
return;
label->set_text(m_refStringList->get_string(pos));
}
File: messagetext.cc
(For use with gtkmm 4)
#include "messagetext.h"
MessageText::MessageText()
{
set_policy(Gtk::PolicyType::AUTOMATIC, Gtk::PolicyType::AUTOMATIC);
set_child(m_TextView);
insert_text();
}
MessageText::~MessageText()
{
}
void MessageText::insert_text()
{
auto refTextBuffer = m_TextView.get_buffer();
auto iter = refTextBuffer->get_iter_at_offset(0);
refTextBuffer->insert(iter,
"From: pathfinder@nasa.gov\n"
"To: mom@nasa.gov\n"
"Subject: Made it!\n"
"\n"
"We just got in this morning. The weather has been\n"
"great - clear but cold, and there are lots of fun sights.\n"
"Sojourner says hi. See you soon.\n"
" -Path\n");
}
ScrolledWindow
widgets create a scrollable
area. You can insert any type of widget into a
ScrolledWindow
, and it will be accessible
regardless of its size by using the scrollbars. Note that
ScrolledWindow
is not a
Gtk::Window
despite the slightly misleading name.
Scrolled windows have scrollbar policies which determine
whether the Scrollbar
s will be displayed. The policies
can be set with the set_policy()
method. The policy may be
for instance Gtk::PolicyType::AUTOMATIC
or
Gtk::PolicyType::ALWAYS
.
Gtk::PolicyType::AUTOMATIC
will cause the scrolled window
to display the scrollbar only if the contained widget is larger than the
visible area. Gtk::PolicyType::ALWAYS
will cause the
scrollbar to be displayed always.
Here is a simple example that packs 100 toggle buttons into a ScrolledWindow. Try resizing the window to see the scrollbars react.
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();
~ExampleWindow() override;
protected:
//Signal handlers:
void on_button_close();
//Child widgets:
Gtk::Box m_VBox;
Gtk::ScrolledWindow m_ScrolledWindow;
Gtk::Grid m_Grid;
Gtk::Button m_ButtonClose;
};
#endif //GTKMM_EXAMPLEWINDOW_H
File: examplewindow.cc
(For use with gtkmm 4)
#include "examplewindow.h"
#include <iostream>
ExampleWindow::ExampleWindow()
: m_VBox(Gtk::Orientation::VERTICAL, 10),
m_ButtonClose("_Close", true)
{
set_title("Gtk::ScrolledWindow example");
set_size_request(300, 300);
set_child(m_VBox);
m_VBox.set_margin(10);
/* The policy is one of Gtk::PolicyType::AUTOMATIC, or Gtk::PolicyType::ALWAYS.
* Gtk::PolicyType::AUTOMATIC will automatically decide whether you need
* scrollbars, whereas Gtk::PolicyType::ALWAYS will always leave the scrollbars
* there. The first one is the horizontal scrollbar, the second, the vertical. */
m_ScrolledWindow.set_policy(Gtk::PolicyType::AUTOMATIC, Gtk::PolicyType::ALWAYS);
m_ScrolledWindow.set_expand();
m_VBox.append(m_ScrolledWindow);
/* set the spacing to 10 on x and 10 on y */
m_Grid.set_row_spacing(10);
m_Grid.set_column_spacing(10);
/* pack the grid into the scrolled window */
m_ScrolledWindow.set_child(m_Grid);
/* this simply creates a grid of toggle buttons
* to demonstrate the scrolled window. */
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
auto s = Glib::ustring::compose("button (%1,%2)", i, j);
auto pButton = Gtk::make_managed<Gtk::ToggleButton>(s);
m_Grid.attach(*pButton, i, j);
}
}
/* Add a "close" button to the bottom of the dialog */
m_VBox.append(m_ButtonClose);
m_ButtonClose.set_halign(Gtk::Align::END);
m_ButtonClose.signal_clicked().connect(
sigc::mem_fun(*this, &ExampleWindow::on_button_close));
/* Hitting the "Enter" key will cause this button to activate. */
m_ButtonClose.grab_focus();
}
ExampleWindow::~ExampleWindow()
{
}
void ExampleWindow::on_button_close()
{
set_visible(false);
}
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);
}
The AspectFrame
widget looks like a
Frame
widget, but it also enforces the aspect
ratio (the ratio of the width to the height) of the child
widget, adding extra space if necessary. For instance, this would allow you to
display a photograph without allowing the user to distort it horizontally or
vertically while resizing.
The following program uses a Gtk::AspectFrame
to present a
drawing area whose aspect ratio will always be 2:1, no matter how the user
resizes the top-level 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();
virtual ~ExampleWindow();
protected:
//Child widgets:
Gtk::AspectFrame m_AspectFrame;
Gtk::Frame m_Frame;
Gtk::DrawingArea m_DrawingArea;
};
#endif //GTKMM_EXAMPLEWINDOW_H
File: examplewindow.cc
(For use with gtkmm 4)
#include "examplewindow.h"
ExampleWindow::ExampleWindow()
: m_AspectFrame(
Gtk::Align::CENTER, /* center x */
Gtk::Align::CENTER, /* center y */
2.0, /* xsize/ysize = 2 */
false /* ignore child's aspect */),
m_Frame("2x1" /* label */)
{
set_title("Aspect Frame");
// Set a child widget to the aspect frame */
// Ask for a 200x200 window, but the AspectFrame will give us a 200x100
// window since we are forcing a 2x1 aspect ratio */
m_DrawingArea.set_content_width(200);
m_DrawingArea.set_content_height(200);
m_Frame.set_child(m_DrawingArea);
m_AspectFrame.set_child(m_Frame);
m_AspectFrame.set_margin(10);
// Add the aspect frame to our toplevel window:
set_child(m_AspectFrame);
}
ExampleWindow::~ExampleWindow()
{
}
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);
}
There are other single-item containers. See the reference documentation for a complete list. Here are links to some example programs that show containers, which are not mentioned elsewhere in this tutorial.