retireSakiの日記

たぶん引退した?ソフトウエアエンジニアのブログ

GTKmm (3.0) と glade によるアプリ (7) - ツールバーの表示、非表示切り替えとaboutダイアログの表示

 今回は、前回の" GTKmm (3.0) と glade によるアプリ (6) - (Qtでも使える)アプリケーションの多重起動の防止 v2 "で作成したプログラムをベースに、ツールバーの表示と表示/非表示の切り替え、そして AboutDialog ("このアプリケーションについて" で表示される) の表示の2つを行います。

retiresaki.hatenablog.com


 最終的にこんな感じですね。

f:id:retireSaki:20181027092856j:plain

 今回設置したツールバーは、アプリケーションの終了ボタンだけ設置しました。

 ソースコードは最後に両方の機能を含めたものを公開してます。


ツールバーの表示と表示/非表示の切り替え

 この作業はメニューバーと同じです。


retiresaki.hatenablog.com

 少し面倒なのが、galde のツールバーの設置ですが、すぐになれると思います。
表示だけなら glade で設定すれば表示されます。

1) ツールバーボタンのクリックイベント処理

ツールバーの終了ボタンに関連したコード

// get toolbar widget
    refBuilder->get_widget("toolBar", m_toolbar);
    refBuilder->get_widget("toolbar_quit", m_toolbar_quit);
〜
    // toolbar signals
    m_toolbar_quit->signal_clicked().connect(
        sigc::mem_fun(*this, &MainWindow::on_btn1_clicked));
〜

 ツールバーボタンのクリックイベントは、普通のボタンのシグナル処理と同様に signal_clicked().connect() で行います。
今回は on_btn1_clicked() を呼び出しています。

2) ツールバーの表示/非表示の切り替え

 これはメニューバーの処理と全く同じで、今回は btn3 のクリックイベント処理で切り替えています。
以下のコードをみれば、すぐに理解と思います。

ツールバーの表示/非表示の切り替えに関連したコード

void MainWindow::on_btn3_clicked()
{
    if (m_toolbar->is_visible()){
        m_toolbar->hide();
        m_btn3->set_label("click to show toolbarr");
    }
    else{
        m_toolbar->show();
        m_btn3->set_label("click to hide toolbar");
    }
}
〜


■ aboutダイアログの表示

 今回は普通のアプリと同様にメニューの about から表示するようにします。

1) glade で新たに GTKAboutDialog を作成

f:id:retireSaki:20181027093449j:plain

 特にボタンなど付けず、標準のままcopytightなどのテキストやアイコン指定を行いました。

 尚、ソースコードは最後にまとまっています。

2) メニューのクリックイベントから AboutDialog を表示

 2.1) AboutDialog に対応したクラスを作成

 今回は、APP_AbouDialog.h を作成しました。
特に何かをすることないので、ヘッダーでクラス APP_AboutDialogを定義しただけです。

 2.2) メニュー menu_about のクリックイベント処理で APP_AboutDialog を呼び出す

● AboutDialogの表示に関連したコード

〜
    refBuilder->get_widget("menu_about", m_menuitem_about);
〜
    m_menuitem_about->signal_activate().connect(
        sigc::mem_fun(*this, &MainWindow::on_app_about));
〜
void MainWindow::on_app_about()
{
    APP_AboutDialog *about_dialog = nullptr;

    refBuilder->get_widget_derived("aboutDialog", about_dialog);
    about_dialog->set_transient_for(*this);
    about_dialog->show_all();
}〜

 メニューの about で on_app_about() を呼び出すところはいつもどおりです

起動時に読み込み済の Gtk::Builder から glade で定義した aboutDialog を get_widget_derived() で取得し。APP_AboutDialog クラスに割り当てます。
set_transient_for() で、AboutDialog の親 MainWindow の手前に表示させます。
show_all() で AboutDialog を表示させます。

 glade で設置した GTKAboutDialog でボタンなど追加しない限り、実際に表示されるダイアログ内のクリック処理などは GTKAboutDialog が勝手にやってくれるので、glade やプログラムはどのように表示するか設定するかだけです。


以上です。
1つ1つはとてもシンプルで簡単でしたね。


■今回作成したソースコードとダウンロード

● 今回作成した APP_AboutDialog.h

#ifndef ABOUTDIALOG_H
#define ABOUTDIALOG_H

#include <gtkmm.h>

class APP_AboutDialog : public Gtk::AboutDialog {
public:
    APP_AboutDialog(BaseObjectType* obj, Glib::RefPtr<Gtk::Builder> const& m_builder_)
        : Gtk::AboutDialog(obj)
        , m_builder{m_builder_}
    {
    }

    virtual ~APP_AboutDialog() = default;

protected:

private:
    Glib::RefPtr<Gtk::Builder> m_builder;

};

#endif

● 今回作成した MainWindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <gtkmm.h>
#include <glibmm.h>
#include <giomm.h>
#include <fstream>
#include <iostream>
#include <string>

#include <glib.h>

#include "APP_AboutDialog.h"


#define ORG_APPICON "test_about.svg"
#define CONF_FILE "application.conf"

class MainWindow : public Gtk::ApplicationWindow {
public:
    MainWindow(BaseObjectType* obj, Glib::RefPtr<Gtk::Builder> const& m_builder_)
        : Gtk::ApplicationWindow(obj)
        , m_builder{m_builder_}
    {
        setInit_display();
    }

    virtual ~MainWindow() = default;

protected:

    virtual void on_btn1_clicked();
    virtual void on_btn2_clicked();
    virtual void on_btn3_clicked();

    Gtk::MenuBar *m_menu = nullptr;
    Gtk::MenuItem *m_menuitem_quit = nullptr;
    Gtk::MenuItem *m_menuitem_about = nullptr;

    Gtk::Toolbar *m_toolbar = nullptr;
    Gtk::ToolButton *m_toolbar_quit = nullptr;

    Gtk::Button *m_btn1 = nullptr;
    Gtk::Button *m_btn2 = nullptr;
    Gtk::Button *m_btn3 = nullptr;

    Gtk::Paned  *m_paned1 = nullptr;
    Gtk::Paned  *m_paned2 = nullptr;

private:
    Glib::RefPtr<Gtk::Builder> m_builder;

    gchar *cstrInitPathFile;

    int nConf_MainWindow_posx;
    int nConf_MainWindow_posy;
    int nConf_MainWindow_width;
    int nConf_MainWindow_height;
    int nConf_Paned1_position;
    int nConf_Paned2_position;

    void set_AppIcon();
    gchar * create_InitPath();
    void load_InitDatas();
    void save_InitDatas();

    void setInit_display();
    void on_hide_window()
    {
        save_InitDatas();
    }

    void on_app_about();

};

#endif

● 今回作成した MainWindow.cc

#include "MainWindow.h"

using namespace std;

extern Glib::RefPtr<Gtk::Builder> refBuilder;

void MainWindow::setInit_display()
{
    cstrInitPathFile = create_InitPath();
    load_InitDatas();

    // get menu widget
    refBuilder->get_widget("menuBar", m_menu);
    refBuilder->get_widget("menu_quit", m_menuitem_quit);
    refBuilder->get_widget("menu_about", m_menuitem_about);

    // get toolbar widget
    refBuilder->get_widget("toolBar", m_toolbar);
    refBuilder->get_widget("toolbar_quit", m_toolbar_quit);

    // get widget
    refBuilder->get_widget("btn1", m_btn1);
    refBuilder->get_widget("btn2", m_btn2);
    refBuilder->get_widget("btn3", m_btn3);

    refBuilder->get_widget("paned1", m_paned1);
    refBuilder->get_widget("paned2", m_paned2);

    // connect signals

    // menu signals
    m_menuitem_quit->signal_activate().connect(
        sigc::mem_fun(*this, &MainWindow::on_btn1_clicked));
    m_menuitem_about->signal_activate().connect(
        sigc::mem_fun(*this, &MainWindow::on_app_about));

    // toolbar signals
    m_toolbar_quit->signal_clicked().connect(
        sigc::mem_fun(*this, &MainWindow::on_btn1_clicked));

    // button signals
    m_btn1->signal_clicked().connect(
        sigc::mem_fun(*this, &MainWindow::on_btn1_clicked));
    m_btn2->signal_clicked().connect(
        sigc::mem_fun(*this, &MainWindow::on_btn2_clicked));
    m_btn3->signal_clicked().connect(
        sigc::mem_fun(*this, &MainWindow::on_btn3_clicked));

    // hide signal
    this->signal_hide().connect(
        sigc::mem_fun(*this, &MainWindow::on_hide_window));

    // set window titles & sizes
    set_title("test menu");
    if (nConf_MainWindow_posx != -1*G_MAXINT && nConf_MainWindow_posy != -1*G_MAXINT)
        move(nConf_MainWindow_posx, nConf_MainWindow_posy);;
    set_default_size(nConf_MainWindow_width, nConf_MainWindow_height);
    //resize(nConf_MainWindow_width, nConf_MainWindow_height);

    // set paned position
    m_paned1->set_position(nConf_Paned1_position);
    m_paned2->set_position(nConf_Paned2_position);

    // set application icon
    set_AppIcon();

}

/*************************************************
    ini functions
*************************************************/

// set application icon
void MainWindow::set_AppIcon()
{
    std::string appname = Glib::get_application_name();

    if ( Glib::file_test( ORG_APPICON, Glib::FILE_TEST_EXISTS )) {
        this->set_icon_from_file( ORG_APPICON );
        return;
    }
    if ( Glib::file_test( appname+".png", Glib::FILE_TEST_EXISTS )) {
        this->set_icon_from_file( appname+".png" );
        return;
    }

    std::vector<std::string> list_dirs = Glib::get_system_data_dirs();
    for (string dir : list_dirs){

        for (int ni=0; ni < 2; ni++){
            string choice_file;
            if (ni==0)  // set original name
                choice_file = Glib::build_filename(	dir, "icons", ORG_APPICON);
            else        // set applcation name
                choice_file = Glib::build_filename(	dir, "icons", appname+".png" );
            if ( Glib::file_test( choice_file, Glib::FILE_TEST_EXISTS )) {
                this->set_icon_from_file( choice_file );
                break;
            }
        }

    }
}

// create ini-file pathfilename
gchar * MainWindow::create_InitPath()
{
    cstrInitPathFile = NULL;
    //g_autoptr(GError) error = NULL;
    GError *error = nullptr;

    // get application name
    const gchar *app_name;
    app_name = g_get_application_name();
    if (!app_name)
        app_name = g_get_prgname();

    // get config directory
    const gchar *user_config_dir = g_get_user_config_dir();
    gchar *pathfile = g_build_filename(user_config_dir, app_name, CONF_FILE, NULL);
    if (g_file_test(pathfile, G_FILE_TEST_EXISTS)) {
        return pathfile;
    }

    // check exists derectory
    if (!g_file_test(g_build_filename(user_config_dir, app_name, NULL), G_FILE_TEST_EXISTS)) {
        // create directory
        GFile *file = g_file_new_build_filename(user_config_dir, app_name,NULL);
        if (!g_file_make_directory(file, NULL, &error)){
            std::cout << "Error make application config directory :"
                      << error->message << std::endl;            
            g_clear_error(&error);
            return NULL;
        }
    }

    return pathfile;
}

// load ini-file
void MainWindow::load_InitDatas()
{
    // defalts
    nConf_MainWindow_posx=-1*G_MAXINT;
    nConf_MainWindow_posy=-1*G_MAXINT;
    nConf_MainWindow_width = 400;
    nConf_MainWindow_height = 300;
    nConf_Paned1_position = 150;
    nConf_Paned2_position = 50;

    if (cstrInitPathFile == NULL)
        return;

    // exists check key file
    if (!g_file_test(cstrInitPathFile, G_FILE_TEST_EXISTS))
        return;

    //g_autoptr(GError) error = NULL;
    GError *error = nullptr;
    g_autoptr(GKeyFile) key_file = g_key_file_new ();

    if (!g_key_file_load_from_file (key_file,
            cstrInitPathFile,
            G_KEY_FILE_KEEP_COMMENTS,
            &error)) {
        if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
            std::cout << "Error loading key file :"
                      << error->message << std::endl;            
        else
            std::cout << "Error loading key file :"
                      << error->code << std::endl;            
        g_clear_error(&error);
        g_key_file_free(key_file);
        return;
    }

    int nvalue;

    // main window
    error = NULL;
    nvalue = g_key_file_get_integer(key_file, "MAINWINDOW", "window_posx", &error);
    if (error == NULL)
        nConf_MainWindow_posx = nvalue;
    else
        g_clear_error(&error);

    error = NULL;
    nvalue = g_key_file_get_integer(key_file, "MAINWINDOW", "window_posy", &error);
    if (error == NULL)
        nConf_MainWindow_posy = nvalue;
    else
        g_clear_error(&error);

    error = NULL;
    nvalue = g_key_file_get_integer(key_file, "MAINWINDOW", "window_width", &error);
    if (error == NULL)
        nConf_MainWindow_width = nvalue;
    else
        g_clear_error(&error);

    error = NULL;
    nvalue = g_key_file_get_integer(key_file, "MAINWINDOW", "window_height", &error);
    if (error == NULL)
        nConf_MainWindow_height = nvalue;
    else
        g_clear_error(&error);

    // paned1
    error = NULL;
    nvalue = g_key_file_get_integer(key_file, "MAINWINDOW", "paned1_divider_position", &error);
    if (error == NULL)
        nConf_Paned1_position = nvalue;
    else
        g_clear_error(&error);

    // paned2
    error = NULL;
    nvalue = g_key_file_get_integer(key_file, "MAINWINDOW", "paned2_divider_position", &error);
    if (error == NULL)
        nConf_Paned2_position = nvalue;
    else
        g_clear_error(&error);

    g_key_file_free(key_file);
}

void MainWindow::save_InitDatas()
{
    if (cstrInitPathFile == NULL)
        return;

    // get application position & size
    Gdk::Rectangle rect;
    get_window()->get_frame_extents(rect);
    

    int int_val_mw_posx = rect.get_x();
    int int_val_mw_posy = rect.get_y();
    int int_val_mw_width = 0;
    int int_val_mw_height = 0;
    get_size(int_val_mw_width, int_val_mw_height);

    // get paneds position
    gint int_val_paned1 = m_paned1->get_position();
    gint int_val_paned2 = m_paned2->get_position();

    // set key values
    GError *error = nullptr;
    g_autoptr(GKeyFile) key_file = g_key_file_new ();

    g_key_file_set_integer(key_file, "MAINWINDOW", "window_posx", int_val_mw_posx);
    g_key_file_set_integer(key_file, "MAINWINDOW", "window_posy", int_val_mw_posy);

    g_key_file_set_integer(key_file, "MAINWINDOW", "window_width", int_val_mw_width);
    g_key_file_set_integer(key_file, "MAINWINDOW", "window_height", int_val_mw_height);

    g_key_file_set_integer(key_file, "MAINWINDOW", "paned1_divider_position", int_val_paned1);
    g_key_file_set_integer(key_file, "MAINWINDOW", "paned2_divider_position", int_val_paned2);

    // write key file
    if (!g_key_file_save_to_file(key_file, cstrInitPathFile, &error)){
        std::cout << "Error saving key file :"
                  << error->message << std::endl;            
        g_clear_error(&error);
        return;
    }

    g_key_file_free(key_file);
}

/*************************************************
    events
*************************************************/

// btn1(close) event
void MainWindow::on_btn1_clicked()
{
    // confirm close
    Gtk::MessageDialog dialog(*this, "close this window ?", false,
                           Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_OK_CANCEL);
    dialog.set_title( "close this window" );
    dialog.set_default_response(Gtk::RESPONSE_OK);
    if (dialog.run()==Gtk::RESPONSE_CANCEL)
        return;

    hide();
}

void MainWindow::on_btn2_clicked()
{
    if (m_menu->is_visible()){
        m_menu->hide();
        m_btn2->set_label("click to show menu-bar");
    }
    else{
        m_menu->show();
        m_btn2->set_label("click to hide menu-bar");
    }
}

void MainWindow::on_btn3_clicked()
{
    if (m_toolbar->is_visible()){
        m_toolbar->hide();
        m_btn3->set_label("click to show toolbarr");
    }
    else{
        m_toolbar->show();
        m_btn3->set_label("click to hide toolbar");
    }
}

/*************************************************
    window or dialog
*************************************************/

void MainWindow::on_app_about()
{
    APP_AboutDialog *about_dialog = nullptr;

    refBuilder->get_widget_derived("aboutDialog", about_dialog);
    about_dialog->set_transient_for(*this);
    about_dialog->show_all();
}

● 今回作成した paned_test.glade

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
  <requires lib="gtk+" version="3.20"/>
  <object class="GtkAboutDialog" id="aboutDialog">
    <property name="name">aboutDialog</property>
    <property name="can_focus">False</property>
    <property name="window_position">center</property>
    <property name="destroy_with_parent">True</property>
    <property name="type_hint">dialog</property>
    <property name="skip_taskbar_hint">True</property>
    <property name="program_name">paned_test</property>
    <property name="version">0.0.0</property>
    <property name="copyright" translatable="yes">Copyright © 2018- retireSaki All rights reserved.</property>
    <property name="comments" translatable="yes">test program</property>
    <property name="website">https://retiresaki.hatenablog.com/</property>
    <property name="authors">retireSaki</property>
    <property name="documenters">retireSaki</property>
    <property name="logo">test_about.svg</property>
    <property name="license_type">gpl-3-0</property>
    <child>
      <placeholder/>
    </child>
    <child internal-child="vbox">
      <object class="GtkBox">
        <property name="can_focus">False</property>
        <property name="orientation">vertical</property>
        <property name="spacing">2</property>
        <child internal-child="action_area">
          <object class="GtkButtonBox">
            <property name="can_focus">False</property>
            <property name="layout_style">end</property>
            <child>
              <placeholder/>
            </child>
            <child>
              <placeholder/>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">False</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <placeholder/>
        </child>
      </object>
    </child>
  </object>
  <object class="GtkApplicationWindow" id="mainWindow">
    <property name="name">mainWindow</property>
    <property name="can_focus">False</property>
    <child>
      <placeholder/>
    </child>
    <child>
      <object class="GtkBox">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="orientation">vertical</property>
        <child>
          <object class="GtkMenuBar" id="menuBar">
            <property name="name">menuBar</property>
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <child>
              <object class="GtkMenuItem">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">ファイル(_F)</property>
                <property name="use_underline">True</property>
                <child type="submenu">
                  <object class="GtkMenu">
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <child>
                      <object class="GtkImageMenuItem">
                        <property name="label">gtk-new</property>
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="use_underline">True</property>
                        <property name="use_stock">True</property>
                      </object>
                    </child>
                    <child>
                      <object class="GtkImageMenuItem">
                        <property name="label">gtk-open</property>
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="use_underline">True</property>
                        <property name="use_stock">True</property>
                      </object>
                    </child>
                    <child>
                      <object class="GtkImageMenuItem">
                        <property name="label">gtk-save</property>
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="use_underline">True</property>
                        <property name="use_stock">True</property>
                      </object>
                    </child>
                    <child>
                      <object class="GtkImageMenuItem">
                        <property name="label">gtk-save-as</property>
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="use_underline">True</property>
                        <property name="use_stock">True</property>
                      </object>
                    </child>
                    <child>
                      <object class="GtkSeparatorMenuItem">
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                      </object>
                    </child>
                    <child>
                      <object class="GtkImageMenuItem" id="menu_quit">
                        <property name="label">gtk-quit</property>
                        <property name="name">menu_quit</property>
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="use_underline">True</property>
                        <property name="use_stock">True</property>
                      </object>
                    </child>
                  </object>
                </child>
              </object>
            </child>
            <child>
              <object class="GtkMenuItem">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">編集(_E)</property>
                <property name="use_underline">True</property>
                <child type="submenu">
                  <object class="GtkMenu">
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <child>
                      <object class="GtkImageMenuItem">
                        <property name="label">gtk-cut</property>
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="use_underline">True</property>
                        <property name="use_stock">True</property>
                      </object>
                    </child>
                    <child>
                      <object class="GtkImageMenuItem">
                        <property name="label">gtk-copy</property>
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="use_underline">True</property>
                        <property name="use_stock">True</property>
                      </object>
                    </child>
                    <child>
                      <object class="GtkImageMenuItem">
                        <property name="label">gtk-paste</property>
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="use_underline">True</property>
                        <property name="use_stock">True</property>
                      </object>
                    </child>
                    <child>
                      <object class="GtkImageMenuItem">
                        <property name="label">gtk-delete</property>
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="use_underline">True</property>
                        <property name="use_stock">True</property>
                      </object>
                    </child>
                  </object>
                </child>
              </object>
            </child>
            <child>
              <object class="GtkMenuItem">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">表示(_V)</property>
                <property name="use_underline">True</property>
              </object>
            </child>
            <child>
              <object class="GtkMenuItem">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">ヘルプ(_H)</property>
                <property name="use_underline">True</property>
                <child type="submenu">
                  <object class="GtkMenu">
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <child>
                      <object class="GtkImageMenuItem" id="menu_about">
                        <property name="label">gtk-about</property>
                        <property name="name">menu_about</property>
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="use_underline">True</property>
                        <property name="use_stock">True</property>
                      </object>
                    </child>
                  </object>
                </child>
              </object>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkToolbar" id="toolBar">
            <property name="name">toolBar</property>
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <child>
              <object class="GtkToolButton" id="toolbar_quit">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="tooltip_text" translatable="yes">Exit this application</property>
                <property name="label" translatable="yes">Exit</property>
                <property name="use_underline">True</property>
                <property name="stock_id">gtk-quit</property>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="homogeneous">True</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
        <child>
          <object class="GtkPaned" id="paned1">
            <property name="name">paned1</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <child>
              <object class="GtkPaned" id="paned2">
                <property name="name">paned2</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="orientation">vertical</property>
                <child>
                  <object class="GtkButton" id="btn1">
                    <property name="label" translatable="yes">quit</property>
                    <property name="name">btn1</property>
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="receives_default">True</property>
                  </object>
                  <packing>
                    <property name="resize">False</property>
                    <property name="shrink">True</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkButton" id="btn2">
                    <property name="label" translatable="yes">hide menubar</property>
                    <property name="name">btn2</property>
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="receives_default">True</property>
                  </object>
                  <packing>
                    <property name="resize">True</property>
                    <property name="shrink">True</property>
                  </packing>
                </child>
              </object>
              <packing>
                <property name="resize">True</property>
                <property name="shrink">True</property>
              </packing>
            </child>
            <child>
              <object class="GtkBox">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="orientation">vertical</property>
                <property name="homogeneous">True</property>
                <child>
                  <object class="GtkButton" id="btn3">
                    <property name="label" translatable="yes">hide toolbar</property>
                    <property name="name">btn3</property>
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="receives_default">True</property>
                  </object>
                  <packing>
                    <property name="expand">False</property>
                    <property name="fill">True</property>
                    <property name="position">0</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkButton" id="btn4">
                    <property name="label" translatable="yes">4</property>
                    <property name="name">btn4</property>
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="receives_default">True</property>
                  </object>
                  <packing>
                    <property name="expand">False</property>
                    <property name="fill">True</property>
                    <property name="position">1</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkButton" id="btn5">
                    <property name="label" translatable="yes">5</property>
                    <property name="name">btn5</property>
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="receives_default">True</property>
                  </object>
                  <packing>
                    <property name="expand">False</property>
                    <property name="fill">True</property>
                    <property name="position">2</property>
                  </packing>
                </child>
              </object>
              <packing>
                <property name="resize">True</property>
                <property name="shrink">True</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">True</property>
            <property name="fill">True</property>
            <property name="position">2</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>

ソースコードのダウンロード

www.mediafire.com

Gtk+3入門

Gtk+3入門

注目記事

「Amazon.co.jpアソシエイト」または「[乙の名称を挿入]は、Amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイトプログラムである、Amazonアソシエイト・プログラムの参加者です。