<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Chapter 7. Container Widgets</title> <link rel="stylesheet" href="style.css" type="text/css"> <meta name="generator" content="DocBook XSL Stylesheets V1.73.2"> <link rel="start" href="index.html" title="Programming with gtkmm"> <link rel="up" href="index.html" title="Programming with gtkmm"> <link rel="prev" href="ch06s05.html" title="Tooltips"> <link rel="next" href="ch07s02.html" title="Multiple-item widgets"> </head> <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> <div class="navheader"> <table width="100%" summary="Navigation header"> <tr><th colspan="3" align="center">Chapter 7. Container Widgets</th></tr> <tr> <td width="20%" align="left"> <a accesskey="p" href="ch06s05.html"><img src="../icons/prev.png" alt="Prev"></a> </td> <th width="60%" align="center"> </th> <td width="20%" align="right"> <a accesskey="n" href="ch07s02.html"><img src="../icons/next.png" alt="Next"></a> </td> </tr> </table> <hr> </div> <div class="chapter" lang="en"> <div class="titlepage"><div><div><h2 class="title"> <a name="sec-ContainerWidgets"></a>Chapter 7. Container Widgets</h2></div></div></div> <div class="toc"> <p><b>Table of Contents</b></p> <ul> <li><span class="sect1"><a href="ch07.html#sec-SingleItemWidgets">Single-item Containers</a></span></li> <li><span class="sect1"><a href="ch07s02.html">Multiple-item widgets </a></span></li> </ul> </div> <p> All container widgets derive from <code class="classname">Gtk::Container</code>, not always directly. Some container widgets, such as <code class="classname">Gtk::Table</code> can hold many child widgets, so these typically have more complex interfaces. Others, such as <code class="classname">Gtk::Frame</code> contain only one child widget. </p> <div class="sect1" lang="en"> <div class="titlepage"><div><div><h2 class="title" style="clear: both"> <a name="sec-SingleItemWidgets"></a>Single-item Containers</h2></div></div></div> <p> The single-item container widgets derive from <code class="classname">Gtk::Bin</code>, which provides the <code class="function">add()</code> and <code class="function">remove()</code> methods for the child widget. Note that <code class="classname">Gtk::Button</code> and <code class="classname">Gtk::Window</code> are technically single-item containers, but we have discussed them already elsewhere. </p> <p> We also discuss the <code class="classname">Gtk::Paned</code> 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. </p> <div class="sect2" lang="en"> <div class="titlepage"><div><div><h3 class="title"> <a name="sec-Frame"></a>Frame</h3></div></div></div> <p> Frames can enclose one or a group of widgets within a box, optionally with a title. For instance, you might place a group of <code class="classname">RadioButton</code>s or <code class="classname">CheckButton</code>s in a <code class="classname">Frame</code>. </p> <p><a class="ulink" href="../../reference/html/classGtk_1_1Frame.html" target="_top">Reference</a></p> <div class="sect3" lang="en"> <div class="titlepage"><div><div><h4 class="title"> <a name="id2574083"></a>Example</h4></div></div></div> <div class="figure"> <a name="figure-frame"></a><p class="title"><b>Figure 7.1. Frame</b></p> <div class="figure-contents"><div class="screenshot"><div><img src="../figures/frame.png" alt="Frame"></div></div></div> </div> <br class="figure-break"><p><a class="ulink" href="../../../examples/book/frame" target="_top">Source Code</a></p> <p>File: <code class="filename">examplewindow.h</code> </p> <pre class="programlisting"> #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 </pre> <p>File: <code class="filename">main.cc</code> </p> <pre class="programlisting"> #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; } </pre> <p>File: <code class="filename">examplewindow.cc</code> </p> <pre class="programlisting"> #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() { } </pre> </div> </div> <div class="sect2" lang="en"> <div class="titlepage"><div><div><h3 class="title"> <a name="id2574205"></a>Paned</h3></div></div></div> <p> Panes divide a widget into two halves, separated by a moveable divider. There are two such widgets: <code class="classname">Gtk::HPaned</code> adds a horizontal divider, and <code class="classname">Gtk::VPaned</code> adds a vertical one. Other than the names and the orientations, there's no difference between the two. </p> <p> Unlike the other widgets in this chapter, pane widgets contain not one but two child widgets, one in each pane. Therefore, you should use <code class="function">add1()</code> and <code class="function">add2()</code> instead of the <code class="function">add()</code> method. </p> <p> You can adjust the position of the divider using the <code class="function">set_position()</code> method, and you will probably need to do so. </p> <p><a class="ulink" href="../../reference/html/classGtk_1_1Paned.html" target="_top">Reference</a></p> <div class="sect3" lang="en"> <div class="titlepage"><div><div><h4 class="title"> <a name="id2574263"></a>Example</h4></div></div></div> <div class="figure"> <a name="figure-paned"></a><p class="title"><b>Figure 7.2. Paned</b></p> <div class="figure-contents"><div class="screenshot"><div><img src="../figures/paned.png" alt="Paned"></div></div></div> </div> <br class="figure-break"><p><a class="ulink" href="../../../examples/book/paned" target="_top">Source Code</a></p> <p>File: <code class="filename">messagetext.h</code> </p> <pre class="programlisting"> #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 </pre> <p>File: <code class="filename">messageslist.h</code> </p> <pre class="programlisting"> #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 </pre> <p>File: <code class="filename">examplewindow.h</code> </p> <pre class="programlisting"> #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 </pre> <p>File: <code class="filename">messagetext.cc</code> </p> <pre class="programlisting"> #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: 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"); } </pre> <p>File: <code class="filename">main.cc</code> </p> <pre class="programlisting"> #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; } </pre> <p>File: <code class="filename">examplewindow.cc</code> </p> <pre class="programlisting"> #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() { } </pre> <p>File: <code class="filename">messageslist.cc</code> </p> <pre class="programlisting"> #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() { } </pre> </div> </div> <div class="sect2" lang="en"> <div class="titlepage"><div><div><h3 class="title"> <a name="sec-ScrolledWindows"></a>ScrolledWindow</h3></div></div></div> <p> <code class="classname">ScrolledWindow</code> widgets are used to create a scrollable area. You can insert any type of widget into a <code class="classname">ScrolledWindow</code> window, and it will be accessible regardless of its size by using the scrollbars. Note that <code class="classname">ScrolledWindow</code> is not a <code class="classname">Gtk::Window</code> despite the slightly misleading name. </p> <p> Scrolled windows have <span class="emphasis"><em>scrollbar policies</em></span> which determine whether the <code class="classname">Scrollbar</code>s will be displayed. The policies can be set with the <code class="function">set_policy()</code> method. The policy may be one of <code class="literal">Gtk::POLICY_AUTOMATIC</code> or <code class="literal">Gtk::POLICY_ALWAYS</code>. <code class="literal">Gtk::POLICY_AUTOMATIC</code> will cause the scrolled window to display the scrollbar only if the contained widget is larger than the visible area. <code class="literal">Gtk::POLICY_ALWAYS</code> will cause the scrollbar to be displayed always. </p> <p><a class="ulink" href="../../reference/html/classGtk_1_1ScrolledWindow.html" target="_top">Reference</a></p> <div class="sect3" lang="en"> <div class="titlepage"><div><div><h4 class="title"> <a name="id2574578"></a>Example</h4></div></div></div> <p> Here is a simple example that packs 100 toggle buttons into a ScrolledWindow. Try resizing the window to see the scrollbars react. </p> <div class="figure"> <a name="figure-scrolledwindow"></a><p class="title"><b>Figure 7.3. ScrolledWindow</b></p> <div class="figure-contents"><div class="screenshot"><div><img src="../figures/scrolledwindow.png" alt="ScrolledWindow"></div></div></div> </div> <br class="figure-break"><p><a class="ulink" href="../../../examples/book/scrolledwindow" target="_top">Source Code</a></p> <p>File: <code class="filename">examplewindow.h</code> </p> <pre class="programlisting"> #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 </pre> <p>File: <code class="filename">main.cc</code> </p> <pre class="programlisting"> #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; } </pre> <p>File: <code class="filename">examplewindow.cc</code> </p> <pre class="programlisting"> #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(); } </pre> </div> </div> <div class="sect2" lang="en"> <div class="titlepage"><div><div><h3 class="title"> <a name="sec-AspectFrames"></a>AspectFrame</h3></div></div></div> <p> The <code class="classname">AspectFrame</code> widget looks like a <code class="classname">Frame</code> widget, but it also enforces the <span class="emphasis"><em>aspect ratio</em></span> (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. </p> <p><a class="ulink" href="../../reference/html/classGtk_1_1AspectFrame.html" target="_top">Reference</a></p> <div class="sect3" lang="en"> <div class="titlepage"><div><div><h4 class="title"> <a name="id2574781"></a>Example</h4></div></div></div> <p> The following program uses a <code class="classname">Gtk::AspectFrame</code> to present a drawing area whose aspect ratio will always be 2:1, no matter how the user resizes the top-level window. </p> <div class="figure"> <a name="figure-aspectframe"></a><p class="title"><b>Figure 7.4. AspectFrame</b></p> <div class="figure-contents"><div class="screenshot"><div><img src="../figures/aspectframe.png" alt="AspectFrame"></div></div></div> </div> <br class="figure-break"><p><a class="ulink" href="../../../examples/book/aspectframe" target="_top">Source Code</a></p> <p>File: <code class="filename">examplewindow.h</code> </p> <pre class="programlisting"> #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 </pre> <p>File: <code class="filename">main.cc</code> </p> <pre class="programlisting"> #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; } </pre> <p>File: <code class="filename">examplewindow.cc</code> </p> <pre class="programlisting"> #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() { } </pre> </div> </div> <div class="sect2" lang="en"> <div class="titlepage"><div><div><h3 class="title"> <a name="sec-Alignment"></a>Alignment</h3></div></div></div> <p> The <code class="classname">Alignment</code> widget allows you to place a widget at a position and size relative to the size of the <code class="classname">Alignment</code> widget itself. For instance, it might be used to center a widget. </p> <p> You need to specify the <code class="classname">Alignment</code>'s characteristics to the constructor, or to the <code class="function">set()</code> method. In particular, you won't notice much effect unless you specify a number other than 1.0 for the <code class="literal">xscale</code> and <code class="literal">yscale</code> parameters, because 1.0 simply means that the child widget will expand to fill all available space. </p> <p><a class="ulink" href="../../reference/html/classGtk_1_1Alignment.html" target="_top">Reference</a></p> <div class="sect3" lang="en"> <div class="titlepage"><div><div><h4 class="title"> <a name="id2574986"></a>Example</h4></div></div></div> <p> This example right-aligns a button in a window by using an <code class="classname">Alignment</code> widget. </p> <div class="figure"> <a name="figure-alignment"></a><p class="title"><b>Figure 7.5. Alignment</b></p> <div class="figure-contents"><div class="screenshot"><div><img src="../figures/alignment.png" alt="Alignment"></div></div></div> </div> <br class="figure-break"><p><a class="ulink" href="../../../examples/book/alignment" target="_top">Source Code</a></p> <p>File: <code class="filename">examplewindow.h</code> </p> <pre class="programlisting"> #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 </pre> <p>File: <code class="filename">main.cc</code> </p> <pre class="programlisting"> #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; } </pre> <p>File: <code class="filename">examplewindow.cc</code> </p> <pre class="programlisting"> #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(); } </pre> <p> See the <a class="link" href="ch06s04.html" title="ProgressBar">ProgressBar</a> section for another example that uses an <code class="classname">Alignment</code>. </p> </div> </div> </div> </div> <div class="navfooter"> <hr> <table width="100%" summary="Navigation footer"> <tr> <td width="40%" align="left"> <a accesskey="p" href="ch06s05.html"><img src="../icons/prev.png" alt="Prev"></a> </td> <td width="20%" align="center"> </td> <td width="40%" align="right"> <a accesskey="n" href="ch07s02.html"><img src="../icons/next.png" alt="Next"></a> </td> </tr> <tr> <td width="40%" align="left" valign="top">Tooltips </td> <td width="20%" align="center"><a accesskey="h" href="index.html"><img src="../icons/home.png" alt="Home"></a></td> <td width="40%" align="right" valign="top"> Multiple-item widgets </td> </tr> </table> </div> </body> </html>