Table of Contents
All container widgets derive from Gtk::Container
, not
always directly. Some container widgets, such as
Gtk::Table
can hold many child widgets, so these
typically have more complex interfaces. Others, such as
Gtk::Frame
contain only one child widget.
The single-item container widgets derive from Gtk::Bin
,
which provides the add()
and remove()
methods for the child widget. Note that 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
RadioButton
s or CheckButton
s in a
Frame
.
File: examplewindow.h
#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: main.cc
#include <gtkmm/main.h> #include "examplewindow.h" int main(int argc, char *argv[]) { Gtk::Main kit(argc, argv); ExampleWindow window; //Shows the window and returns when it is closed. Gtk::Main::run(window); return 0; }
File: examplewindow.cc
#include "examplewindow.h" ExampleWindow::ExampleWindow() { /* Set some window properties */ set_title("Frame Example"); set_size_request(300, 300); /* Sets the border width of the window. */ set_border_width(10); add(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_RIGHT, Gtk::ALIGN_TOP); /* Set the style of the frame */ m_Frame.set_shadow_type(Gtk::SHADOW_ETCHED_OUT); show_all_children(); } ExampleWindow::~ExampleWindow() { }
Panes divide a widget into two halves, separated by a moveable divider. There
are two such widgets: Gtk::HPaned
adds a horizontal
divider, and Gtk::VPaned
adds a vertical one. Other
than the names and the orientations, there's no difference between the two.
Unlike the other widgets in this chapter, pane widgets contain not one but two
child widgets, one in each pane. Therefore, you should use
add1()
and add2()
instead of the
add()
method.
You can adjust the position of the divider using the
set_position()
method, and you will probably need to do
so.
File: messagetext.h
#ifndef GTKMM_EXAMPLE_MESSAGETEXT_H #define GTKMM_EXAMPLE_MESSAGETEXT_H #include <gtkmm.h> class MessageText : public Gtk::ScrolledWindow { public: MessageText(); virtual ~MessageText(); virtual void insert_text(); protected: Gtk::TextView m_TextView; }; #endif //GTKMM_EXAMPLE_MESSAGETEXT_H
File: messageslist.h
#ifndef GTKMM_EXAMPLE_MESSAGESLIST_H #define GTKMM_EXAMPLE_MESSAGESLIST_H #include <gtkmm.h> class MessagesList: public Gtk::ScrolledWindow { public: MessagesList(); virtual ~MessagesList(); class ModelColumns : public Gtk::TreeModel::ColumnRecord { public: ModelColumns() { add(m_col_text); } Gtk::TreeModelColumn<Glib::ustring> m_col_text; }; ModelColumns m_Columns; protected: Glib::RefPtr<Gtk::ListStore> m_refListStore; //The Tree Model. Gtk::TreeView m_TreeView; //The Tree View. }; #endif //GTKMM_EXAMPLE_MESSAGESLIST_H
File: examplewindow.h
#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::VPaned m_VPaned; MessagesList m_MessagesList; MessageText m_MessageText; }; #endif //GTKMM_EXAMPLEWINDOW_H
File: messagetext.cc
#include "messagetext.h" MessageText::MessageText() { set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); add(m_TextView); insert_text(); show_all_children(); } MessageText::~MessageText() { } void MessageText::insert_text() { Glib::RefPtr<Gtk::TextBuffer> refTextBuffer = m_TextView.get_buffer(); Gtk::TextBuffer::iterator iter = refTextBuffer->get_iter_at_offset(0); refTextBuffer->insert(iter, "From: [email protected]\n" "To: [email protected]\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"); }
File: main.cc
#include <gtkmm/main.h> #include "examplewindow.h" int main(int argc, char *argv[]) { Gtk::Main kit(argc, argv); ExampleWindow window; //Shows the window and returns when it is closed. Gtk::Main::run(window); return 0; }
File: examplewindow.cc
#include "examplewindow.h" ExampleWindow::ExampleWindow() { set_title ("Paned Windows"); set_border_width(10); set_default_size(450, 400); /* Add a vpaned widget to our toplevel window */ add(m_VPaned); /* Now add the contents of the two halves of the window */ m_VPaned.add1(m_MessagesList); m_VPaned.add2(m_MessageText); show_all_children(); } ExampleWindow::~ExampleWindow() { }
File: messageslist.cc
#include "messageslist.h" #include <sstream> MessagesList::MessagesList() { /* Create a new scrolled window, with scrollbars only if needed */ set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); add(m_TreeView); /* create list store */ m_refListStore = Gtk::ListStore::create(m_Columns); m_TreeView.set_model(m_refListStore); /* Add some messages to the window */ for(int i = 0; i < 10; ++i) { std::ostringstream text; text << "message #" << i; Gtk::TreeModel::Row row = *(m_refListStore->append()); row[m_Columns.m_col_text] = text.str(); } //Add the Model's column to the View's columns: m_TreeView.append_column("Messages", m_Columns.m_col_text); show_all_children(); } MessagesList::~MessagesList() { }
ScrolledWindow
widgets are used to create a scrollable
area. You can insert any type of widget into a
ScrolledWindow
window, 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
one of Gtk::POLICY_AUTOMATIC
or
Gtk::POLICY_ALWAYS
.
Gtk::POLICY_AUTOMATIC
will cause the scrolled window
to display the scrollbar only if the contained widget is larger than the
visible area. Gtk::POLICY_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
#ifndef GTKMM_EXAMPLEWINDOW_H #define GTKMM_EXAMPLEWINDOW_H #include <gtkmm.h> class ExampleWindow : public Gtk::Dialog { public: ExampleWindow(); virtual ~ExampleWindow(); protected: //Signal handlers: virtual void on_button_close(); //Child widgets: Gtk::ScrolledWindow m_ScrolledWindow; Gtk::Table m_Table; Gtk::Button m_Button_Close; }; #endif //GTKMM_EXAMPLEWINDOW_H
File: main.cc
#include <gtkmm/main.h> #include "examplewindow.h" int main(int argc, char *argv[]) { Gtk::Main kit(argc, argv); ExampleWindow window; //Shows the window and returns when it is closed. Gtk::Main::run(window); return 0; }
File: examplewindow.cc
#include "examplewindow.h" #include <stdio.h> //For sprintf() ExampleWindow::ExampleWindow() : m_Table(10, 10), m_Button_Close("Close") { set_title("Gtk::ScrolledWindow example"); set_border_width(0); set_size_request(300, 300); m_ScrolledWindow.set_border_width(10); /* the policy is one of Gtk::POLICY AUTOMATIC, or Gtk::POLICY_ALWAYS. * Gtk::POLICY_AUTOMATIC will automatically decide whether you need * scrollbars, whereas Gtk::POLICY_ALWAYS will always leave the scrollbars * there. The first one is the horizontal scrollbar, the second, * the vertical. */ m_ScrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS); get_vbox()->pack_start(m_ScrolledWindow); /* set the spacing to 10 on x and 10 on y */ m_Table.set_row_spacings(10); m_Table.set_col_spacings(10); /* pack the table into the scrolled window */ m_ScrolledWindow.add(m_Table); /* this simply creates a grid of toggle buttons on the table * to demonstrate the scrolled window. */ for(int i = 0; i < 10; i++) { for(int j = 0; j < 10; j++) { char buffer[32]; sprintf(buffer, "button (%d,%d)\n", i, j); Gtk::Button* pButton = Gtk::manage(new Gtk::ToggleButton(buffer)); m_Table.attach(*pButton, i, i + 1, j, j + 1); } } /* Add a "close" button to the bottom of the dialog */ m_Button_Close.signal_clicked().connect( sigc::mem_fun(*this, &ExampleWindow::on_button_close)); /* this makes it so the button is the default. */ m_Button_Close.set_flags(Gtk::CAN_DEFAULT); Gtk::Box* pBox = get_action_area(); if(pBox) pBox->pack_start(m_Button_Close); /* This grabs this button to be the default button. Simply hitting * the "Enter" key will cause this button to activate. */ m_Button_Close.grab_default(); show_all_children(); } ExampleWindow::~ExampleWindow() { } void ExampleWindow::on_button_close() { hide(); }
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
#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::DrawingArea m_DrawingArea; }; #endif //GTKMM_EXAMPLEWINDOW_H
File: main.cc
#include <gtkmm/main.h> #include "examplewindow.h" int main(int argc, char *argv[]) { Gtk::Main kit(argc, argv); ExampleWindow window; //Shows the window and returns when it is closed. Gtk::Main::run(window); return 0; }
File: examplewindow.cc
#include "examplewindow.h" ExampleWindow::ExampleWindow() : m_AspectFrame("2x1", /* label */ Gtk::ALIGN_CENTER, /* center x */ Gtk::ALIGN_CENTER, /* center y */ 2.0, /* xsize/ysize = 2 */ false /* ignore child's aspect */) { set_title("Aspect Frame"); set_border_width(10); // Add 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_size_request(200, 200); m_AspectFrame.add(m_DrawingArea); // Add the aspect frame to our toplevel window: add(m_AspectFrame); show_all_children(); } ExampleWindow::~ExampleWindow() { }
The Alignment
widget allows you to place a widget at a
position and size relative to the size of the Alignment
widget itself. For instance, it might be used to center a widget.
You need to specify the Alignment
's characteristics to
the constructor, or to the set()
method. In particular, you
won't notice much effect unless you specify a number other than 1.0 for the
xscale
and yscale
parameters, because 1.0
simply means that the child widget will expand to fill all available space.
This example right-aligns a button in a window by using an
Alignment
widget.
File: examplewindow.h
#ifndef GTKMM_EXAMPLEWINDOW_H #define GTKMM_EXAMPLEWINDOW_H #include <gtkmm.h> class ExampleWindow : public Gtk::Window { public: ExampleWindow(); virtual ~ExampleWindow(); protected: //Signal handlers: virtual void on_button_clicked(); //Child widgets: Gtk::Alignment m_Alignment; Gtk::Button m_Button; }; #endif //GTKMM_EXAMPLEWINDOW_H
File: main.cc
#include <gtkmm/main.h> #include "examplewindow.h" int main(int argc, char *argv[]) { Gtk::Main kit(argc, argv); ExampleWindow window; //Shows the window and returns when it is closed. Gtk::Main::run(window); return 0; }
File: examplewindow.cc
#include "examplewindow.h" ExampleWindow::ExampleWindow() : m_Alignment(Gtk::ALIGN_RIGHT, Gtk::ALIGN_CENTER, 0.0, 0.0), m_Button("Close") { set_title("Gtk::Alignement"); set_border_width(10); set_default_size(200, 50); add(m_Alignment); m_Alignment.add(m_Button); m_Button.signal_clicked().connect( sigc::mem_fun(*this, &ExampleWindow::on_button_clicked) ); show_all_children(); } ExampleWindow::~ExampleWindow() { } void ExampleWindow::on_button_clicked() { hide(); }
See the ProgressBar section for another
example that uses an Alignment
.