Ruby/Gtk2初嘗
環境配置
只需在命令列執行 gem install gtk2
並稍等片刻。
我使用的是windows,目前gtk2庫並不能很好相容64位ruby,體現在gem安裝出錯,linux的情況未知。
Hello, World!
讓我們從這句經典的問候開始吧。
require 'gtk2'
button = Gtk::Button.new("Hello World!")
button.signal_connect("clicked") {
puts "Hello World!"
}
window = Gtk::Window.new("Example")
window.signal_connect("delete_event") {
puts "delete event occurred"
#true
false
}
window.signal_connect("destroy") {
puts "destroy event occurred"
Gtk.main_quit
}
window.border_width = 50
window.add(button)
window.show_all
Gtk.main
這個HW似乎有點長,不過彈出的視窗仍然會讓人興奮不已。
解構
button = Gtk::Button.new("Hello World!")
button.signal_connect("clicked") {
puts "Hello World!"
}
首先,我們新建了一個名為button的按鈕,並把它的label屬性設為"Hello World!"。接著我們使用了signal_connect方法,將button的點選訊號與列印字串的程式碼連結了起來。
Gtk的運作基於訊號和回撥的,程式執行時,會啟動一個主迴圈(即 Gtk.main
),這個主迴圈在接到訊號之前,不會進行任何工作。而當接到一個訊號,Gtk即會回撥對應這個事件的函式。在這個例子中,當button被點選的訊號傳給主迴圈,主迴圈便會呼叫 puts "Hello World!"
,在命令列列印一行字。
window = Gtk::Window.new("Example")
window.signal_connect("delete_event") {
puts "delete event occurred"
#true
false
}
window.signal_connect("destroy") {
puts "destroy event occurred"
Gtk.main_quit
}
類似地,我們新建了一個title為"Example"的視窗,並新增了delete_event和destroy兩個事件。delete_event會在視窗的關閉鍵被點選時觸發,而這個事件會返回一個值,若為假則會呼叫destroy事件,這對實現“你確定要關掉它嗎?”很有用。而在destroy事件中,簡單明瞭地執行了退出Gtk主迴圈的命令。
window.border_width = 50
window.add(button)
視窗是承載按鈕等控制元件的容器,後者依賴前者以顯示。這段程式碼把button新增進了window。而border_width指的是視窗邊界距離內容物的寬度,設成50px讓這個視窗看起來有些臃腫,不過這麼做只是為了讓視窗的標題能正常顯示。
然後,執行 window.show_all
讓視窗和它包含的按鈕顯示,這和以下兩行是等價的。
button.show
window.show
最後,使用 Gtk.main
啟動Gtk主迴圈,開始等待事件訊號。
安裝Glade
從Glade官網下載安裝檔案,Gtk2的設計需要使用Glade 3.8。
設計器的使用
先來瀏覽一下左側的控制元件欄,嗯,沒有什麼新奇的。
那麼首先新建一個Window,採取預設名字也就是 window1
了。右邊可以修改各種屬性,暫時只把 Common - Border width
改為10。
Gtk控制元件的排布需要藉助容器,在容器欄可以看到 Horizontal Box
,Table
等等容器控制元件。嘗試一下將他們新增到 window1
,例如 Table
會把視窗按照行列分成數格,就像傳統的HTML設計方法,接著就可以把按鈕等控制元件放置到每個格子裡。
然而利用表格設計顯然太不方便,實際上我們還有更好的選擇。
把剛才的 table1
容器刪掉,然後在 window1
中新增一個 Fixed
容器。試試在容器中新增一個按鈕 button1
,可以發現這個按鈕會懸浮在你點選的位置。按住Shift鍵可以對按鈕的大小和位置進行調整。再新增一個文字框 label1
,這個簡單的GUI作為示例大致足夠了。
將設計檔案儲存為 test.glade
。它的內在大概是這個樣子:
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="2.24"/>
<!-- interface-naming-policy project-wide -->
<object class="GtkWindow" id="window1">
<property name="can_focus">False</property>
<property name="border_width">10</property>
<property name="window_position">center</property>
<child>
<object class="GtkFixed" id="fixed1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkButton" id="button1">
<property name="label" translatable="yes">button</property>
<property name="width_request">100</property>
<property name="height_request">80</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="x">27</property>
<property name="y">107</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label1">
<property name="width_request">159</property>
<property name="height_request">80</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">label</property>
</object>
</child>
</object>
</child>
</object>
</interface>
使用Gtk::Builder繪製GUI
在同目錄新建一個ruby原始檔,輸入以下程式碼:
require 'gtk2'
builder = Gtk::Builder.new
builder.add_from_file('test.glade')
builder['window1'].signal_connect('destroy') { Gtk.main_quit }
builder['window1'].show_all
builder['button1'].signal_connect('clicked') { builder['label1'].label = 'Hello' }
Gtk.main
Gtk是利用 Gtk::Builder
對glade檔案進行讀取的,我們會新建一個Builder物件來繪製GUI。利用Builder物件可以直接對控制元件進行屬性和方法的操作,這段程式碼還是很好理解的。
執行程式碼,點選一下按鈕,會發現文字框的文字變成了"Hello"。由於我們並未對視窗的大小進行設定,所以實際上視窗大小是依據控制元件的位置和 Border width
決定的。
更規範的方法?
在查詢資料的過程中,我發現人們一般不會直接用Builder物件操作控制元件,而是會將控制元件的訊號與函式連結起來。在glade設計器裡,對控制元件可以設定 Signals
屬性。嘗試對 button1
的 clicked
訊號進行設定,將其 Handler
設為 on_button1_clicked
。
儲存,然後執行以下ruby程式碼:
require 'gtk2'
class Builder < Gtk::Builder
def initialize(file)
super()
self.add_from_file(file)
self['window1'].signal_connect('destroy') { Gtk.main_quit }
self['window1'].show_all
self.connect_signals{ |handler| method(handler) }
end
def on_button1_clicked
self['label1'].label = 'Hello'
end
end
builder = Builder.new('test.glade')
Gtk.main
在這個例子中使用了更OO的方法,connect_signals
方法把控制元件的訊號和對應的函式都連結起來。比如剛才設定了 button1
的 Handler
,這裡就把 button1
的點選訊號和函式 on_button1_clicked
連結了起來。
雖然應該這才是規範的寫法,但是我對此不太理解。為每個訊號分配一個特定的函式,是不是降低了檢視和程式的分離度?直接使用控制元件 signal_connect
不是很好嗎?等待高人解答。
一個例項
附上我用gtk2做的一個IM實驗: https://github.com/CicholGricenchos/ruby-instant-messager
相關文章
- Ruby 札記 - 淺嘗 Ruby 特性
- Ruby初學
- 初嘗 DockerDocker
- 初嘗試swiftSwift
- webgl 效能優化初嘗Web優化
- [Vuex系列] - 初嘗Vuex第一個例子Vue
- Flutter 初嘗:從 Java 無縫過渡FlutterJava
- 前端的gitlab的ci初嘗試前端Gitlab
- 設計模式(一) 動態代理初嘗試設計模式
- Kotlin 初嘗之專案實踐總結Kotlin
- Flutter Web初嘗試以及一些問題解決FlutterWeb
- 初嘗微信小程式開發與實踐經驗分享微信小程式
- 第一次網站初嘗試爬的坑網站
- 產品初學的三步:瞭解、嘗試、想想
- [Ruby]format xml with RubyORMXML
- Unity 開源雙端框架 ET 中初嘗熱更新技術Unity框架
- 函數語言程式設計初嘗之指令碼解析豆瓣首頁函數程式設計指令碼
- Ruby 札記 - 淺談和配置 Ruby
- Ruby己死?NodeJS能否取代Ruby?NodeJS
- 解析Ruby
- Oomox:定製和建立你自己的 GTK2、GTK3 主題OomoxGTK2GTK3
- Ruby 3.0.0釋出:Ruby3將比Ruby2快3倍
- 嘗試
- rails on ruby,ruby on rails 之程式碼塊(二)AI
- Ruby Profiler詳解之ruby-prof(I)
- Ruby Struct EqualStruct
- Ruby loop 方法OOP
- JavaScript and Ruby in ABAPJavaScript
- Ruby Block 理解BloC
- Ruby語言
- Ruby Code & Style
- [ruby] rails renderAI
- Ruby變數變數
- 技術人初嘗帶隊作戰 — 指導一次騰訊 SNG MINI 專案
- 2016年總結:教師路的開啟,愛情味的初嘗 (上)
- 2016年總結:教師路的開啟,愛情味的初嘗 (下)
- JAVAFX嘗試Java
- 嘗試1