いまどきのGTK+3 は、UI部分は Gladeを使ってXMLを書いて Gtk::Builderで読み込み、色指定などは CSSで指定するスタイルみたいです。そこで、以前書いた;
・Ruby/GTK2,GTK3 プログラミング Tips 1〜9
をそのスタイルに書き換えていこうと思います。
参考)
→・Getting started with GTK+ with the ruby-gnome2 Gtk3 module. - ruby-gnome2 - GitHub
→・(13) Dynamic User Interfaces Built With Glade - Ruby/GTK2 Tutorial
→・19. Glade and Gtk.Builder — Python GTK+ 3 Tutorial 3.4 documentation
→・Glade - A User Interface Designer
→・GTK+ 3 Reference Manual
→・GTK+ CSS - GTK+ 3 Reference Manual
本当はさらに Gtk::Application、Gtk::ApplicationWindow を使うのがいまどきのようです。
ただ、簡単なGUIプログラム(マルチウィンドウでない、Gtk.main でループする)なら、Gtk::Window を使った方が簡潔なようなので、そちらを使っていきます(単に分かってないだけ?)。
(→・Proper way of building Gtk3 applications in Python - Stack Overflow)
1.Glade
XMLファイルを作るのに、GTK+用の Glade というソフトを使います。(Xcodeの Interface Builderみたいなもの?)
Glade を使うことで GUI部品の配置、設定を GUI画面で出来るようになり、大幅に楽になります。これはオススメです!
1-1.Gladeのインストール
○macOS で Homebrew を使う場合
ターミナルで;
ターミナル(端末)で;
(Ubuntu の場合、16.04LTS だと 3.18.1 までしか入りません。)
○Windows の場合
→・GTK+ Download/ Windows - The GTK+ Project
これでできる?(未確認)
○macOS,Windows で、仮想環境(VirtualBox)に Linux を入れる場合
macOS や Windowsで上記の方法でうまくインストールできなかった場合は、VirtualBox上の Linuxに Glade をインストールする方が楽かもしれません。
VirtualBox 公式サイトからダウンロードし、仮想環境を作ったら、あとは上記の Ubuntu(17.04以降)などをインストールし、Glade をインストールします。
※ なお、Glade公式のページの
・Windows Binariesはバージョンが古いです
1-2.Gladeを起動
ターミナル(端末)で;
ウィジェット一覧がアイコンのみになっていて、分かりにくい時は
2.Window を作る
2-A.XMLファイルを作る(Gladeを使う)
2-A-1)Windowを作る
Gladeを起動し、左のウィジェット一覧から「 Window」を選び、真ん中のスペースにドラッグします。
2-A-2)Windowの設定する
右上のスペースにある、「GtkWindow」をクリックして選択します。
右下のスペースに「Window Properties」が表示され、タブ「General」、「Packing」、「Common」、「Signals」、「Accessibility(アイコンのみ)」が並びます。
ここでウィジェットの設定をします。
2-A-3)Window の ID を設定する
Window をプログラム側から呼び出す時の名称を入力します。
「General」の「ID」に名称を入力します。(Window のタイトル/ラベル名ではありません)
ここでは window_1 にしました。
2-A-4)ハンドラを設定する
Glade では signal_connect("destroy") { ハンドラ名 } のようなハンドラ名を設定できます。
「Signals」>「GtkWidget」>「destroy」をクリックして、
「Handler」欄の <Type here> のところをクリックするとハンドラ名が入力できるようになります。
何文字か入れてからdeleteしていくと、標準的なハンドラ名の候補が表示されますのでそこから選んでもいいですし、自分独自のハンドラ名をつけてもいいです。
ここでは、候補にあった on_windows_1_destroy にしました。
(注意;enterキーを押さないと確定されません!)
2-A-5)保存する
あとはデフォルトのまま変更せずに、保存します。
ここでは、glade_window_1.ui という名前にしました。
で保存されます。
できたファイル glade_window_1.ui は XMLファイルなので、エディタで開いたり、編集できます。
(license; public domain)
・glade_window_1.ui
2-B.Rubyプログラムを作る
Glade で作った XMLファイルを読み込むには Gtk::Builder を使います。
○Gtk::Builder.new
Builderを作ります
○Gtk::Builder#add_from_file(filename)
Glade で作ったXMLファイルを読み込みます
・filename;XMLファイル(Gtk::Builder UI Definitions)
○Gtk::Builder#get_object(name)
読み込んだXMLファイルから、ウィジェットを取得します
・name;オブジェクト
○Gtk::Builder#connect_signals {|handler_name| ...}
XMLファイルに登録した各ハンドラー名の処理を設定します
・handler_name;ハンドラー名
※実際は、登録した全ハンドラー名をそれぞれ同名のメソッドにすればいいので、以下のように書けば良いようです
Gtk::Builder#connect_signals {|name| method(name)}
ハンドラー名のついた各メソッドは、その動作を def メソッド名 ... end で定義します。
・glade_window_1.rb
ウィンドウができます。
3.Windowの設定を変える
3-A.XMLファイルを変える(Gladeを使う)
(右上のスペースで GtkWindow をクリックしてから)
○ウィンドウの表示位置を指定する
・glade_window_2.rb
もし、背景色が変わらなかったら、background-image: none; という行を追加します。
→・[gtk3] Color setting of the Gtk/Button does not affect ・ Issue #1084 ・ ruby-gnome2/ruby-gnome2
window と書くと Gtk::Window 全体の設定になります。
また、色の指定の仕方もいろいろあります。
→・GTK+ CSS - GTK+ 3 Reference Manual
さらに、CSSで ID指定やクラス指定もできます。
その場合は XMLファイルも書き換えます。
Glade を起動して、
・ID で指定する場合
「Common」>「Widget Attributes」>「ウィジェット名」
自分で決めた ID を記入します
(「General」の「ID」ではないことに注意!)
・クラスで指定する場合
「Common」>「Widget Attributes」>「Style Classes」
の<Type Here> をクリックして、自分で決めたクラス名を記入します
(enterキーを押さないと確定しません)
その後、CSSファイルを設定します。
・ID で指定する場合(window_widget とします)
#を付けて指定します
・スタイルクラスで指定する場合(window_style とします)
.を付けて指定します
・glade_window_3.rb
(スタイルクラスで指定)・glade_window_5.ui
・glade_window_5.rb
・Ruby/GTK2,GTK3 プログラミング Tips 1〜9
をそのスタイルに書き換えていこうと思います。
参考)
→・Getting started with GTK+ with the ruby-gnome2 Gtk3 module. - ruby-gnome2 - GitHub
→・(13) Dynamic User Interfaces Built With Glade - Ruby/GTK2 Tutorial
→・19. Glade and Gtk.Builder — Python GTK+ 3 Tutorial 3.4 documentation
→・Glade - A User Interface Designer
→・GTK+ 3 Reference Manual
→・GTK+ CSS - GTK+ 3 Reference Manual
本当はさらに Gtk::Application、Gtk::ApplicationWindow を使うのがいまどきのようです。
ただ、簡単なGUIプログラム(マルチウィンドウでない、Gtk.main でループする)なら、Gtk::Window を使った方が簡潔なようなので、そちらを使っていきます(単に分かってないだけ?)。
(→・Proper way of building Gtk3 applications in Python - Stack Overflow)
○動作確認環境
・gtk3 (3.1.8)
・glade (3.20.0)
・ruby (2.4.1)
・macOS Sierra (10.12.6)
・Ubuntu (17.04) / VirtualBox (5.1.26);gladeの動作確認のみ・glade (3.20.0)
・ruby (2.4.1)
・macOS Sierra (10.12.6)
1.Glade
XMLファイルを作るのに、GTK+用の Glade というソフトを使います。(Xcodeの Interface Builderみたいなもの?)
Glade を使うことで GUI部品の配置、設定を GUI画面で出来るようになり、大幅に楽になります。これはオススメです!
1-1.Gladeのインストール
○macOS で Homebrew を使う場合
ターミナルで;
$ brew install glade○Ubuntu(17.04)の場合
ターミナル(端末)で;
$ sudo apt install gladeで glade (3.20.0) がインストールされます。
(Ubuntu の場合、16.04LTS だと 3.18.1 までしか入りません。)
○Windows の場合
→・GTK+ Download/ Windows - The GTK+ Project
これでできる?(未確認)
○macOS,Windows で、仮想環境(VirtualBox)に Linux を入れる場合
macOS や Windowsで上記の方法でうまくインストールできなかった場合は、VirtualBox上の Linuxに Glade をインストールする方が楽かもしれません。
VirtualBox 公式サイトからダウンロードし、仮想環境を作ったら、あとは上記の Ubuntu(17.04以降)などをインストールし、Glade をインストールします。
※ なお、Glade公式のページの
・Windows Binariesはバージョンが古いです
1-2.Gladeを起動
ターミナル(端末)で;
$ gladeで起動します。
ウィジェット一覧がアイコンのみになっていて、分かりにくい時は
View>Palette Appearance>Text beside iconsでウィジェット名も表示できます。
2.Window を作る
2-A.XMLファイルを作る(Gladeを使う)
2-A-1)Windowを作る
Gladeを起動し、左のウィジェット一覧から「 Window」を選び、真ん中のスペースにドラッグします。
2-A-2)Windowの設定する
右上のスペースにある、「GtkWindow」をクリックして選択します。
右下のスペースに「Window Properties」が表示され、タブ「General」、「Packing」、「Common」、「Signals」、「Accessibility(アイコンのみ)」が並びます。
ここでウィジェットの設定をします。
2-A-3)Window の ID を設定する
Window をプログラム側から呼び出す時の名称を入力します。
「General」の「ID」に名称を入力します。(Window のタイトル/ラベル名ではありません)
ここでは window_1 にしました。
2-A-4)ハンドラを設定する
Glade では signal_connect("destroy") { ハンドラ名 } のようなハンドラ名を設定できます。
「Signals」>「GtkWidget」>「destroy」をクリックして、
「Handler」欄の <Type here> のところをクリックするとハンドラ名が入力できるようになります。
何文字か入れてからdeleteしていくと、標準的なハンドラ名の候補が表示されますのでそこから選んでもいいですし、自分独自のハンドラ名をつけてもいいです。
ここでは、候補にあった on_windows_1_destroy にしました。
(注意;enterキーを押さないと確定されません!)
2-A-5)保存する
あとはデフォルトのまま変更せずに、保存します。
ここでは、glade_window_1.ui という名前にしました。
File>Saveまたは
control + s(macOS 標準の command + s ではないのに注意してください!)
で保存されます。
できたファイル glade_window_1.ui は XMLファイルなので、エディタで開いたり、編集できます。
(license; public domain)
・glade_window_1.ui
<?xml version="1.0" encoding="UTF-8"?><!-- Generated with glade 3.20.0 --><interface><requires lib="gtk+" version="3.20"/><object class="GtkWindow" id="window_1"><property name="can_focus">False</property><signal name="destroy" handler="on_window_1_destroy" swapped="no"/><child><placeholder/></child></object></interface>
2-B.Rubyプログラムを作る
Glade で作った XMLファイルを読み込むには Gtk::Builder を使います。
○Gtk::Builder.new
Builderを作ります
○Gtk::Builder#add_from_file(filename)
Glade で作ったXMLファイルを読み込みます
・filename;XMLファイル(Gtk::Builder UI Definitions)
○Gtk::Builder#get_object(name)
読み込んだXMLファイルから、ウィジェットを取得します
・name;オブジェクト
○Gtk::Builder#connect_signals {|handler_name| ...}
XMLファイルに登録した各ハンドラー名の処理を設定します
・handler_name;ハンドラー名
※実際は、登録した全ハンドラー名をそれぞれ同名のメソッドにすればいいので、以下のように書けば良いようです
Gtk::Builder#connect_signals {|name| method(name)}
ハンドラー名のついた各メソッドは、その動作を def メソッド名 ... end で定義します。
・glade_window_1.rb
require 'gtk3'builder = Gtk::Builder.newbuilder.add_from_file("glade_window_1.ui")win = builder.get_object("window_1")def on_window_1_destroyGtk.main_quitendbuilder.connect_signals {|handler| method(handler)}win.show_allGtk.main
(解説)
(1)
(1)
win = builder.get_object("window_1")
で、glade_window_1.ui の
<object class="GtkWindow" id="window_1">
を取得します。つまり、
win = Gtk::Window.new
と同じことになります
(2)
(2)
def on_window_1_destroyGtk.main_quitend
で、glade_window_1.ui の
<signal name="destroy" handler="on_window_1_destroy" swapped="no"/>
の処理を定義します。つまり、
win.signal_connect("destroy") { Gtk.main_quit }
と同じことになります。
2-C.プログラムの実行
glade_window_1.ui と glade_window_1.rb を同じディレクトリに置いて、ターミナル(端末)で;
2-C.プログラムの実行
glade_window_1.ui と glade_window_1.rb を同じディレクトリに置いて、ターミナル(端末)で;
$ ruby glade_window_1.rb
ウィンドウができます。
3.Windowの設定を変える
3-A.XMLファイルを変える(Gladeを使う)
(右上のスペースで GtkWindow をクリックしてから)
○ウィンドウの表示位置を指定する
「General」>「Window Attributes」>「Position」
から選択します。「None」,「Center」,「Mouse」などから選びます。
(x, y では指定できない?)
○ウィンドウのタイトルを指定する
から選択します。「None」,「Center」,「Mouse」などから選びます。
(x, y では指定できない?)
○ウィンドウのタイトルを指定する
「General」>「Appearance」>「Title」
に入力します。
に入力します。
○ウィンドウのサイズを指定する
「General」>「Appearance」>「デフォルトの幅」「デフォルトの高さ」
に入力します。
「General」>「Appearance」>「デフォルトの幅」「デフォルトの高さ」
に入力します。
○サイズ変更の許可
「General」>「Window Flags」>「サイズ変更可」のチェックで
サイズ変更の可否を決めます。
・glade_window_2.ui
「General」>「Window Flags」>「サイズ変更可」のチェックで
サイズ変更の可否を決めます。
・glade_window_2.ui
<?xml version="1.0" encoding="UTF-8"?><!-- Generated with glade 3.20.0 --><interface><requires lib="gtk+" version="3.20"/><object class="GtkWindow" id="window_1"><property name="can_focus">False</property><property name="title" translatable="yes">sample window</property><property name="resizable">False</property><property name="window_position">center</property><property name="default_width">300</property><property name="default_height">200</property><signal name="destroy" handler="on_window_1_destroy" swapped="no"/><child><placeholder/></child></object></interface>
・glade_window_2.rb
require 'gtk3'builder = Gtk::Builder.newbuilder.add_from_file("glade_window_2.ui")win = builder.get_object("window_1")def on_window_1_destroyGtk.main_quitendbuilder.connect_signals {|handler| method(handler)}win.show_allGtk.main
3-B.Rubyプログラムを変える
CSS で設定します(Gtk::CssProvider)
○Gtk::CssProvider.new
CSSオブジェクトを作成します
○Gtk::CssProvider#load(data: string)
data: CSSの文字列 の形で読み込みます
・string;CSSの設定
○Gtk::CssProvider#.load_from_path(filename)
CSSファイルを読み込みます
・filename;CSSファイル
○Gtk::Window#style_context.add_provider(css_provider, Gtk::StyleProvider::PRIORITY_USER)
ウィンドウにCSSの設定を加えます
・css_provider;Gtk::CssProviderクラス
CSS で設定します(Gtk::CssProvider)
○Gtk::CssProvider.new
CSSオブジェクトを作成します
○Gtk::CssProvider#load(data: string)
data: CSSの文字列 の形で読み込みます
・string;CSSの設定
○Gtk::CssProvider#.load_from_path(filename)
CSSファイルを読み込みます
・filename;CSSファイル
○Gtk::Window#style_context.add_provider(css_provider, Gtk::StyleProvider::PRIORITY_USER)
ウィンドウにCSSの設定を加えます
・css_provider;Gtk::CssProviderクラス
○背景の色を設定する
window {background-color: cyan;}
もし、背景色が変わらなかったら、background-image: none; という行を追加します。
→・[gtk3] Color setting of the Gtk/Button does not affect ・ Issue #1084 ・ ruby-gnome2/ruby-gnome2
window と書くと Gtk::Window 全体の設定になります。
また、色の指定の仕方もいろいろあります。
→・GTK+ CSS - GTK+ 3 Reference Manual
さらに、CSSで ID指定やクラス指定もできます。
その場合は XMLファイルも書き換えます。
Glade を起動して、
・ID で指定する場合
「Common」>「Widget Attributes」>「ウィジェット名」
自分で決めた ID を記入します
(「General」の「ID」ではないことに注意!)
・クラスで指定する場合
「Common」>「Widget Attributes」>「Style Classes」
の<Type Here> をクリックして、自分で決めたクラス名を記入します
(enterキーを押さないと確定しません)
その後、CSSファイルを設定します。
・ID で指定する場合(window_widget とします)
#を付けて指定します
#window_widget {background-color: cyan;}
・スタイルクラスで指定する場合(window_style とします)
.を付けて指定します
.window_style {background-color: #00FFFF;}
・glade_window_3.ui
<?xml version="1.0" encoding="UTF-8"?><!-- Generated with glade 3.20.0 --><interface><requires lib="gtk+" version="3.20"/><object class="GtkWindow" id="window_1"><property name="can_focus">False</property><property name="title" translatable="yes">sample window</property><property name="window_position">center</property><property name="default_width">300</property><property name="default_height">200</property><signal name="destroy" handler="on_window_1_destroy" swapped="no"/><child><placeholder/></child></object></interface>
・glade_window_3.rb
require 'gtk3'builder = Gtk::Builder.newbuilder.add_from_file("glade_window_3.ui")win = builder.get_object("window_1")css_provider = Gtk::CssProvider.newcss_provider.load(data:"window {background-color: cyan;}")win.style_context.add_provider(css_provider, Gtk::StyleProvider::PRIORITY_USER)def on_window_1_destroyGtk.main_quitendbuilder.connect_signals {|handler| method(handler)}win.show_allGtk.main
<?xml version="1.0" encoding="UTF-8"?><!-- Generated with glade 3.20.0 --><interface><requires lib="gtk+" version="3.20"/><object class="GtkWindow" id="window_1"><property name="name">window_widget</property><property name="can_focus">False</property><property name="title" translatable="yes">sample window</property><property name="window_position">center</property><property name="default_width">300</property><property name="default_height">200</property><signal name="destroy" handler="on_window_1_destroy" swapped="no"/><child><placeholder/></child></object></interface>
・glade_window_4.css
#window_widget {background-color: cyan;}
・glade_window_4.rb
require 'gtk3'builder = Gtk::Builder.newbuilder.add_from_file("glade_window_4.ui")win = builder.get_object("window_1")css_provider = Gtk::CssProvider.newcss_provider.load_from_path("glade_window_4.css")win.style_context.add_provider(css_provider, Gtk::StyleProvider::PRIORITY_USER)def on_window_1_destroyGtk.main_quitendbuilder.connect_signals {|handler| method(handler)}win.show_allGtk.main
(スタイルクラスで指定)
<?xml version="1.0" encoding="UTF-8"?><!-- Generated with glade 3.20.0 --><interface><requires lib="gtk+" version="3.20"/><object class="GtkWindow" id="window_1"><property name="can_focus">False</property><property name="title" translatable="yes">sample window</property><property name="window_position">center</property><property name="default_width">300</property><property name="default_height">200</property><signal name="destroy" handler="on_window_1_destroy" swapped="no"/><child><placeholder/></child><style><class name="window_style"/></style></object></interface>
・glade_window_5.css
.window_style {background-color: #00FFFF;}
・glade_window_5.rb
require 'gtk3'builder = Gtk::Builder.newbuilder.add_from_file("glade_window_5.ui")win = builder.get_object("window_1")css_provider = Gtk::CssProvider.newcss_provider.load_from_path("glade_window_5.css")win.style_context.add_provider(css_provider, Gtk::StyleProvider::PRIORITY_USER)def on_window_1_destroyGtk.main_quitendbuilder.connect_signals {|handler| method(handler)}win.show_allGtk.main