glade 是在开发 GUI 应用程序一个简单的布局平台, 采用 xml 的格式
prequisites: pygtk , pygtk-glade
1. 启动 glade (选择 libglade 方式) , 先建立主要的窗体 named window1, 由于 gtk2.0+ 的布局基本元素为 hbox 与 vbox.
2. 建立一个 2 维的 vbox.
3. 建立一个 label 控件 (named label1) 与 button 控件(named button1), 把他们分别放进 vbox 中
4. 再把 label1 与 button1 的 label 属性分别填入, 简单的布局就完成如下:
5. 加入 button on-click 时的 signal: 点击 button1, 切换到 Signals 页面, 在 GtkButton 中的 signal 选择 clicked, 在 Handler 栏填入 on_button1_clicked
6. 加入 window1 的 destroy signal: 点击 window1, 切换到 Signals 页面, 在 GtkObject 中的 signal 选择 destory, 在 Handler 栏填入 on_window1_destroy
7. 定义 on_button1_clicked event 的 callback, 在 terminal 下印出 "Hello World!"
执行效果:
完整代码 helloworld.py
#!/usr/bin/env python import sys #import glib try: import pygtk pygtk.require("2.0") except: pass try: import pygtk import gtk.glade except: sys.exit(1) class HelloWorldGTK: """This is an Hello World GTK application""" def __init__(self): # Set the glade file self.gladefile = "helloworld.glade" self.wtree = gtk.glade.XML(self.gladefile) self.window = self.wtree.get_widget("window1") dic = {"on_button1_clicked" : self.button1_clicked, "on_window1_destroy" : gtk.main_quit } self.wtree.signal_autoconnect(dic) if (self.window): # self.window.connect("destroy", gtk.main_quit) self.window.show() def button1_clicked(self, widget): print "Hello World!" if __name__ == "__main__": hwg = HelloWorldGTK() gtk.main()
完整代码 helloworld.glade
<?xml version="1.0"?> <glade-interface> <!-- interface-requires gtk+ 2.16 --> <!-- interface-naming-policy project-wide --> <widget class="GtkWindow" id="window1"> <signal name="destroy" handler="on_window1_destroy"/> <signal name="destroy_event" handler="on_window1_destroy_event"/> <child> <widget class="GtkVBox" id="vbox1"> <property name="visible">True</property> <child> <widget class="GtkLabel" id="label1"> <property name="visible">True</property> <property name="label" translatable="yes">Please click on button!</property> </widget> <packing> <property name="position">0</property> </packing> </child> <child> <widget class="GtkButton" id="button1"> <property name="label" translatable="yes">Click me</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> <signal name="clicked" handler="on_button1_clicked"/> </widget> <packing> <property name="position">1</property> </packing> </child> </widget> </child> </widget> </glade-interface>
接着来看另外一个格式的 glade (GTK Builder), 引用 glade 的方式略有不同, 也配合一个简单的 UI 来解说.
先看看布局:
首先建立一个主窗口 window1, 添加一个三维的 vbox, 依次放入 menubar1, 二维的 hpaned, statusbar; 在 hpaned 中放入 vbuttonbox 及 textview, 在 vbuttonbox 中构建 6 个 button.
在 glade UI designer 中的视图:
再依次定义 button 的 handler 及 callbacks.
完整代码 robot.py
#!/usr/bin/env python # -*- coding: utf-8 -*- import pygtk import gtk class Robot: """This is an a simple robot application""" def __init__(self): builder = gtk.Builder() builder.add_from_file("robot.glade") dic = { "on_window1_destroy" : self.on_window1_destroy, "on_btnMouse_clicked" : self.on_btnMouse_clicked, "on_btnKeyboard_clicked" : self.on_btnKeyboard_clicked, "on_btnClick_clicked" : self.on_btnClick_clicked, "on_btnDelay_clicked" : self.on_btnDelay_clicked, "on_btnExecute_clicked" : self.on_btnExecute_clicked, "on_btnLocation_clicked" : self.on_btnLocation_clicked } builder.connect_signals(dic) self.window = builder.get_object("window1") self.text = builder.get_object("textview1") self.chars = "" self.window.show() def on_window1_destroy(self, widget): gtk.main_quit() def on_btnMouse_clicked(self, widget): #buffers = self.text.get_buffer() #start, end = buffers.get_bounds() self.chars = self.chars + "鼠标移动参数被设定/n" self.text.get_buffer().set_text(self.chars) def on_btnKeyboard_clicked(self, widget): self.chars = self.chars + "键盘按键参数被设定/n" self.text.get_buffer().set_text(self.chars) def on_btnClick_clicked(self, widget): self.chars = self.chars + "鼠标按键参数被设定/n" self.text.get_buffer().set_text(self.chars) def on_btnDelay_clicked(self, widget): self.chars = self.chars + "时间延迟参数被设定/n" self.text.get_buffer().set_text(self.chars) def on_btnExecute_clicked(self, widget): self.chars = self.chars + "脚本执行参数被设定/n" self.text.get_buffer().set_text(self.chars) def on_btnLocation_clicked(self, widget): self.chars = self.chars + "鼠标取位参数被设定/n" self.text.get_buffer().set_text(self.chars) if __name__ == "__main__": robot = Robot() gtk.main()
布局代码 robot.glade (可以比较一下与 libglade 生成的不同之处)
<?xml version="1.0"?> <interface> <requires lib="gtk+" version="2.16"/> <!-- interface-naming-policy project-wide --> <object class="GtkWindow" id="window1"> <property name="width_request">400</property> <signal name="destroy" handler="on_window1_destroy"/> <child> <object class="GtkVBox" id="vbox1"> <property name="visible">True</property> <child> <object class="GtkMenuBar" id="menubar1"> <property name="visible">True</property> <child> <object class="GtkMenuItem" id="menuitem1"> <property name="visible">True</property> <property name="label" translatable="yes">文件</property> <property name="use_underline">True</property> <child type="submenu"> <object class="GtkMenu" id="menu1"> <property name="visible">True</property> <child> <object class="GtkImageMenuItem" id="imagemenuitem1"> <property name="label">新文件</property> <property name="visible">True</property> <property name="image">image1</property> <property name="use_stock">False</property> </object> </child> <child> <object class="GtkImageMenuItem" id="imagemenuitem2"> <property name="label">开启</property> <property name="visible">True</property> <property name="image">image2</property> <property name="use_stock">False</property> </object> </child> <child> <object class="GtkImageMenuItem" id="imagemenuitem3"> <property name="label">存档</property> <property name="visible">True</property> <property name="image">image3</property> <property name="use_stock">False</property> </object> </child> <child> <object class="GtkImageMenuItem" id="imagemenuitem4"> <property name="label">存档于</property> <property name="visible">True</property> <property name="image">image4</property> <property name="use_stock">False</property> </object> </child> <child> <object class="GtkSeparatorMenuItem" id="separatormenuitem1"> <property name="visible">True</property> </object> </child> <child> <object class="GtkImageMenuItem" id="imagemenuitem5"> <property name="label">离开</property> <property name="visible">True</property> <property name="image">image5</property> <property name="use_stock">False</property> </object> </child> </object> </child> </object> </child> <child> <object class="GtkMenuItem" id="menuitem2"> <property name="visible">True</property> <property name="label" translatable="yes">运行</property> <property name="use_underline">True</property> <child type="submenu"> <object class="GtkMenu" id="menu2"> <property name="visible">True</property> <child> <object class="GtkImageMenuItem" id="imagemenuitem6"> <property name="label">运行</property> <property name="visible">True</property> <property name="image">image6</property> <property name="use_stock">False</property> </object> </child> </object>
执行结果:
如上按键的效果会依次呈现在右边的 TextView 中.