GTKmm (3.0) と glade によるアプリ (5) - アプリケーションのアイコンをセット
今回は、アプリケーションらしく下のアイコンをセットみます。
今回も前回の"GTKmm (3.0) と glade によるアプリ (4) - メニューバーの表示と表示切り替え"で作成したプログラムをベースにします。
左 : アイコン未設定
右 : アイコンを設定
アイコンをセットするには、glade で指定する方法とアプリ内で設定する方法があります。
■ glade で指定する方法
これは一番単純な方法です。
画像のように、メインウィンドウのアイコンファイルを指定するだけです。
設定した 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="GtkApplicationWindow" id="mainWindow"> <property name="name">mainWindow</property> <property name="can_focus">False</property> <property name="icon">linux.png</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"> <property name="label">gtk-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="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">2</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="GtkButton" id="btn3"> <property name="label" translatable="yes">3</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="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">1</property> </packing> </child> </object> </child> </object> </interface>
<property name="icon">linux.png</property>
の部分です。
これだけです。
■ アプリ内で設定する方法
やることは実行しているカレントディレクト内、もしくは一般的に保存されるアイコンディレクト内にアイコンファイルがあるかどうか調べて、アプリにアイコンをセットします。
linuxにおける一般的に保存されるアイコンディレクトは、$XDG_DATA_DIRS/icons や $HOME内のicons などを使うなど指します。ひsつ様に応じて
今回は、実行カレントディレクトリー, /usr/local/share/icons , /usr/share/icons から探してセットすることとしますので、実行カレントディレクトリー, $XDG_DATA_DIRS を使います。
また本来必要ないのですが、アイコンファイル名は、指定したオリジナルものと、アプリケーション名の2通りのケースを想定し、オリジナルのアイコンがない場合、アプリ名のアイコンを使うこととし、アイコンは PNG 形式とします。
では、ソースから
設定した 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); // get widget refBuilder->get_widget("btn1", m_btn1); refBuilder->get_widget("btn2", m_btn2); 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)); // 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)); 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(GError) error = NULL; 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"); } }
オリジナルアイコンファイル名は、mainWindow.h 内で
#define ORG_APPICON "linux.png"
と定義しています。
アイコンを探し、セットしている関数は
void MainWindow::set_AppIcon()
です。
最初に、実行カレントディレクトリー内からファイルを探し、存在しているときは
this->set_icon_from_file( const std::string & filename );
でメインウィンドウに見つけたファイルをセットします。
この関数は、指定したファイル名filenameからイメージをロードして生成されたpixbufで Gtk::Window::set_icon ( const Glib::RefPtr< Gdk::Pixbuf >& icon ) を呼び出すのと同様です。
ここで念の為 PNG 以外のイメージフォーマットに対応しているか確認してみます。
用意したファイルは、GIF, JPG, SVG を用意しました。
元画像となったPNGファイル
GIFなどの画像は、下のプログラム一式のZIPに同梱
結果、いずれも問題なく表示できました。
実行カレントディレクトリー内にアイコンがファイルが存在していない場合、
(1) $XDG_DATA_DIRS つまり Glib::get_system_data_dirs(); で取得したディレクトリーリスト取得
(2) Glib::build_filenam() でファイルパスを作成
(3) 存在チェックで存在していれば this->set_icon_from_file(); でアイコンをセット。
という手順でアイコンをセットします。
以上です。
このあたりは、Qt のほうが楽ですね。
サポートされるアイコンのイメージフォマットは、OSやLinuxディストリビューションのバージョンによっても違ってくるので、インストールされるであろうバージョンを想定したイメージフォマットを使うと良いでしょう。
最後に、全てのファイルを圧縮したファイル(zip)を載せます。
ソース一式
すべてのファイル(zip)をダウンロードするwww.mediafire.com
GTK+, Qt のちょっと読んでみたい、こんな入門書はいかがでしょうか?
Qtで簡単 GUIプログラミング―Qt入門書を読む前に読む「入門書」
- 作者: 曹よしひろ
- 出版社/メーカー: カットシステム
- 発売日: 2009/04
- メディア: 単行本
- クリック: 24回
- この商品を含むブログ (6件) を見る
GTK+とGladeで作るLinuxプログラミング超入門―かっこいいアプリを自分で作ろう! (CompuBooks)
- 作者: 鈴木哲哉
- 出版社/メーカー: すばる舎
- 発売日: 2000/06
- メディア: 単行本
- クリック: 25回
- この商品を含むブログ (1件) を見る
- 作者: たなかひろゆき
- 出版社/メーカー: ソフトバンククリエイティブ
- 発売日: 2002/02
- メディア: 単行本
- クリック: 12回
- この商品を含むブログ (1件) を見る