在前面的文章中,介绍完了常用的一些小部件。本篇将为大家介绍Gtk.Builder的使用。
Gtk.Builder
Gtk.Builder是一个辅助对象,通过读取用户定义好的UI文件(通常是使用glade生成)来获取部件,并将用户的UI展示出来。
Methods
方法修饰词 | 方法名及参数 |
---|---|
static | new () |
static | new_from_file (filename) |
static | new_from_resource (resource_path) |
static | new_from_string (string, length) |
add_callback_symbol (callback_name, callback_symbol) | |
add_from_file (filename) | |
add_from_resource (resource_path) | |
add_from_string (buffer, length=-1) | |
add_objects_from_file (filename, object_ids) | |
add_objects_from_resource (resource_path, object_ids) | |
add_objects_from_string (buffer, object_ids) | |
connect_signals (self, obj_or_map) | |
connect_signals_full (func, *user_data) | |
expose_object (name, object) | |
extend_with_template (widget, template_type, buffer, length) | |
get_application () | |
get_object (name) | |
get_objects () | |
get_translation_domain () | |
get_type_from_name (type_name) | |
set_application (application) | |
set_translation_domain (domain) | |
value_from_string (pspec, string) | |
value_from_string_type (type, string) |
Virtual Methods
do_get_type_from_name (type_name) |
Properties
Name | Type | Flags | Short Description |
---|---|---|---|
translation-domain | str | r/w | The translation domain used by gettext |
Signals
Name | Short Description |
---|
例子
一.Signal
UI文件 example.glade
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- interface-requires gtk+ 3.0 -->
<object class="GtkWindow" id="window1">
<property name="title">Signal Button</property>
<property name="can_focus">False</property>
<signal name="delete-event" handler="onDeleteWindow" swapped="no"/>
<child>
<object class="GtkButton" id="button1">
<property name="label" translatable="yes">button</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<signal name="pressed" handler="onButtonPressed" swapped="no"/>
</object>
</child>
</object>
</interface>
代码:
#!/usr/bin/env python3
# Created by xiaosanyu at 16/6/16
# section 126
TITLE = "Signal"
DESCRIPTION = """ connect the button's signal """
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
import os
class Handler:
@staticmethod
def onDeleteWindow(*args):
Gtk.main_quit(*args)
@staticmethod
def onButtonPressed(button):
print("Hello World!")
def main():
builder = Gtk.Builder()
builder.add_from_file(os.path.join(os.path.dirname(__file__), "../Data/example.glade"))
builder.connect_signals(Handler())
window = builder.get_object("window1")
window.show_all()
Gtk.main()
if __name__ == "__main__":
main()
二
UI文件 1.glade
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- interface-requires gtk+ 3.0 -->
<object class="GtkButton" id="label1">
<signal name="clicked" handler="ok_button_clicked"/>
<property name="label">I am a Label for a Button</property>
</object>
<object class="GtkButton" id="button1">
<accessibility>
<action action_name="click" translatable="yes">Click the button.</action>
<relation target="label1" type="labelled-by"/>
</accessibility>
<child internal-child="accessible">
<object class="AtkObject" id="a11y-button1">
<property name="accessible-name">Clickable Button</property>
</object>
</child>
</object>
</interface>
代码:
#!/usr/bin/env python3
# Created by xiaosanyu at 16/7/8
# section 122
TITLE = "Builder1"
DESCRIPTION = """ """
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
import os
class MyWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="UI DEMO")
box = Gtk.VBox(spacing=6)
builder = Gtk.Builder()
builder.add_from_file(os.path.join(os.path.dirname(__file__), "1.glade"))
builder.connect_signals(self)
widget = builder.get_object("label1")
box.add(widget)
widget = builder.get_object("button1")
box.add(widget)
self.add(box)
@staticmethod
def ok_button_clicked(button):
print("Hello World!")
def main():
win = MyWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
if __name__ == '__main__':
main()
三.顶层窗口为Dialog
UI文件 2.glade
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- interface-requires gtk+ 3.0 -->
<object class="GtkDialog" id="dialog1">
<signal name="delete-event" handler="onDeleteWindow" swapped="no"/>
<child internal-child="vbox">
<object class="GtkBox" id="vbox1">
<property name="border-width">10</property>
<child internal-child="action_area">
<object class="GtkButtonBox" id="hbuttonbox1">
<property name="border-width">20</property>
<child>
<object class="GtkButton" id="ok_button">
<property name="label">gtk-ok</property>
<property name="use-stock">TRUE</property>
<signal name="clicked" handler="ok_button_clicked"/>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</interface>
代码:
#!/usr/bin/env python3
# Created by xiaosanyu at 16/7/8
# section 123
TITLE = "Dialog"
DESCRIPTION = """ The toplevel window is a Dialog """
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
import os
class Handler:
@staticmethod
def onDeleteWindow(*args):
Gtk.main_quit(*args)
@staticmethod
def ok_button_clicked(button):
print("Hello World!")
def main():
builder = Gtk.Builder()
builder.add_from_file(os.path.join(os.path.dirname(__file__), "2.glade"))
builder.connect_signals(Handler())
widget = builder.get_object("dialog1")
widget.show_all()
Gtk.main()
if __name__ == '__main__':
main()
四.快捷键accelerator
按“q”键激活按钮
UI文件 3.glade
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- interface-requires gtk+ 3.0 -->
<object class="GtkWindow" id="window1">
<property name="can_focus">False</property>
<signal name="delete-event" handler="onDeleteWindow" swapped="no"/>
<child>
<object class="GtkVBox" id="box1">
<child>
<object class="GtkButton" id="button1">
<signal name="clicked" handler="ok_button_clicked"/>
<property name="label">Button</property>
<accelerator key="q" signal="clicked"/>
</object>
</child>
<child>
<object class="GtkButton" id="button2">
<property name="label">Button2</property>
<style> <class name="my-special-button-class"/> <class name="dark-button"/> </style>
</object>
</child>
</object>
</child>
</object>
</interface>
代码
#!/usr/bin/env python3
# Created by xiaosanyu at 16/7/8
# section 124
TITLE = "Accelerator"
DESCRIPTION = """ press "q" will active the button """
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
import os
class Handler:
@staticmethod
def ok_button_clicked(button):
print("Hello World!")
@staticmethod
def onDeleteWindow(*args):
Gtk.main_quit(*args)
def main():
builder = Gtk.Builder()
builder.add_from_file(os.path.join(os.path.dirname(__file__), "3.glade"))
builder.connect_signals(Handler())
window = builder.get_object("window1")
window.show_all()
Gtk.main()
if __name__ == '__main__':
main()
五.Template
UI文件 4.glade
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="%s" parent="GtkBox">
<property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
<property name="spacing">4</property>
<child>
<object class="GtkButton" id="hello_button">
<property name="label">Hello World</property>
<signal name="clicked" handler="hello_button_clicked"/>
</object>
</child>
<child>
<object class="GtkButton" id="goodbye_button">
<property name="label">Goodbye World</property>
</object>
</child>
</template>
</interface>
代码:
#!/usr/bin/env python3
# Created by xiaosanyu at 16/7/8
# section 125
TITLE = "Template"
DESCRIPTION = """ Creates and initializes child widgets defined in templates. """
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gio, GObject, GLib
import os
class FooWidget(Gtk.Box):
def __init__(self):
data = Gio.resources_lookup_data("/templete/4.glade", 0)
data = data.get_data().decode() % (__name__.replace(".", "+") + '+FooWidget')
self.set_template(GLib.Bytes.new(data.encode()))
super().__init__()
# self.bind_template_callback_full("hello_button_clicked", self.hello_button_clicked)
self.bind_template_child_full("goodbye_button", False, 0)
self.bind_template_child_full("hello_button", False, 0)
self.init_template()
for child in self.get_children():
child.connect("clicked", self.button_clicked, child.get_label())
self.set_has_window(False)
# Bug: Only click once
@staticmethod
def hello_button_clicked():
print("hello_button_clicked")
@staticmethod
def button_clicked(widget, name):
print(name + " clicked")
class MyWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="UI DEMO")
widget = FooWidget()
# can't get child widget
button1 = widget.get_template_child(Gtk.Button, "goodbye_button")
print(button1)
self.add(widget)
def main():
win = MyWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
if __name__ == '__main__':
base_path = os.path.abspath(os.path.dirname(__file__))
resource_path = os.path.join(base_path, '../Data/demo.gresource')
resource = Gio.Resource.load(resource_path)
Gio.resources_register(resource)
main()
六.
UI文件 builder.glade
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
<interface domain="gtk20">
<object class="GtkListStore" id="liststore1">
<columns>
<column type="gchararray"/>
<column type="gchararray"/>
<column type="gint"/>
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0" translatable="yes">John</col>
<col id="1" translatable="yes">Doe</col>
<col id="2">25</col>
<col id="3" translatable="yes">This is the John Doe row</col>
</row>
<row>
<col id="0" translatable="yes">Mary</col>
<col id="1" translatable="yes">Unknown</col>
<col id="2">50</col>
<col id="3" translatable="yes">This is the Mary Unknown row</col>
</row>
</data>
</object>
<object class="GtkUIManager" id="uimanager">
<child>
<object class="GtkActionGroup" id="DefaultActions">
<child>
<object class="GtkAction" id="Copy">
<property name="name">Copy</property>
<property name="tooltip" translatable="yes">Copy selected object into the clipboard</property>
<property name="stock_id">gtk-copy</property>
</object>
</child>
<child>
<object class="GtkAction" id="Cut">
<property name="name">Cut</property>
<property name="tooltip" translatable="yes">Cut selected object into the clipboard</property>
<property name="stock_id">gtk-cut</property>
</object>
</child>
<child>
<object class="GtkAction" id="EditMenu">
<property name="name">EditMenu</property>
<property name="label" translatable="yes">_Edit</property>
</object>
</child>
<child>
<object class="GtkAction" id="FileMenu">
<property name="name">FileMenu</property>
<property name="label" translatable="yes">_File</property>
</object>
</child>
<child>
<object class="GtkAction" id="New">
<property name="name">New</property>
<property name="tooltip" translatable="yes">Create a new file</property>
<property name="stock_id">gtk-new</property>
</object>
</child>
<child>
<object class="GtkAction" id="Open">
<property name="name">Open</property>
<property name="tooltip" translatable="yes">Open a file</property>
<property name="stock_id">gtk-open</property>
</object>
</child>
<child>
<object class="GtkAction" id="Paste">
<property name="name">Paste</property>
<property name="tooltip" translatable="yes">Paste object from the Clipboard</property>
<property name="stock_id">gtk-paste</property>
</object>
</child>
<child>
<object class="GtkAction" id="Quit">
<property name="name">Quit</property>
<property name="tooltip" translatable="yes">Quit the program</property>
<property name="stock_id">gtk-quit</property>
<signal handler="quit_activate" name="activate"/>
</object>
</child>
<child>
<object class="GtkAction" id="Save">
<property name="name">Save</property>
<property name="is_important">True</property>
<property name="tooltip" translatable="yes">Save a file</property>
<property name="stock_id">gtk-save</property>
</object>
</child>
<child>
<object class="GtkAction" id="SaveAs">
<property name="name">SaveAs</property>
<property name="tooltip" translatable="yes">Save with a different name</property>
<property name="stock_id">gtk-save-as</property>
</object>
</child>
<child>
<object class="GtkAction" id="HelpMenu">
<property name="name">HelpMenu</property>
<property name="label" translatable="yes">_Help</property>
</object>
</child>
<child>
<object class="GtkAction" id="About">
<property name="name">About</property>
<property name="stock_id">gtk-about</property>
<signal handler="about_activate" name="activate"/>
</object>
<accelerator key="F1"/>
</child>
</object>
</child>
<ui>
<menubar name="menubar1">
<menu action="FileMenu" name="FileMenu">
<menuitem action="New" name="New"/>
<menuitem action="Open" name="Open"/>
<menuitem action="Save" name="Save"/>
<menuitem action="SaveAs" name="SaveAs"/>
<separator/>
<menuitem action="Quit" name="Quit"/>
</menu>
<menu action="EditMenu">
<menuitem action="Copy" name="Copy"/>
<menuitem action="Cut" name="Cut"/>
<menuitem action="Paste" name="Paste"/>
</menu>
<menu action="HelpMenu" name="HelpMenu">
<menuitem action="About" name="About"/>
</menu>
</menubar>
<toolbar name="toolbar1">
<toolitem action="New" name="New"/>
<toolitem action="Open" name="Open"/>
<toolitem action="Save" name="Save"/>
<separator/>
<toolitem action="Copy" name="Copy"/>
<toolitem action="Cut" name="Cut"/>
<toolitem action="Paste" name="Paste"/>
</toolbar>
</ui>
</object>
<object class="GtkAboutDialog" id="aboutdialog1">
<property name="program-name" translatable="yes">GtkBuilder demo</property>
<accessibility>
<relation target="window1" type="subwindow-of"/>
</accessibility>
</object>
<object class="GtkWindow" id="window1">
<property name="default_height">250</property>
<property name="default_width">440</property>
<property name="title">GtkBuilder demo</property>
<child>
<object class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<child>
<object constructor="uimanager" class="GtkMenuBar" id="menubar1">
<property name="visible">True</property>
<child internal-child="accessible">
<object class="AtkObject" id="a11y-menubar">
<property name="AtkObject::accessible-name">The menubar</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
</packing>
</child>
<child>
<object constructor="uimanager" class="GtkToolbar" id="toolbar1">
<property name="visible">True</property>
<child internal-child="accessible">
<object class="AtkObject" id="a11y-toolbar">
<property name="AtkObject::accessible-name">The toolbar</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow1">
<property name="hscrollbar_policy">automatic</property>
<property name="shadow_type">in</property>
<property name="visible">True</property>
<property name="vscrollbar_policy">automatic</property>
<child>
<object class="GtkTreeView" id="treeview1">
<property name="visible">True</property>
<property name="model">liststore1</property>
<property name="tooltip-column">3</property>
<child internal-child="accessible">
<object class="AtkObject" id="a11y-treeview">
<property name="AtkObject::accessible-name">Name list</property>
<property name="AtkObject::accessible-description">
A list of person with name, surname and age columns
</property>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="column1">
<property name="title">Name</property>
<child>
<object class="GtkCellRendererText" id="renderer1"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="column2">
<property name="title">Surname</property>
<child>
<object class="GtkCellRendererText" id="renderer2"/>
<attributes>
<attribute name="text">1</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="column3">
<property name="title">Age</property>
<child>
<object class="GtkCellRendererText" id="renderer3"/>
<attributes>
<attribute name="text">2</attribute>
</attributes>
</child>
</object>
</child>
</object>
</child>
<accessibility>
<action action_name="move-cursor" description="Move the cursor to select another person."/>
</accessibility>
</object>
<packing>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkStatusbar" id="statusbar1">
<property name="visible">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">3</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
代码:
#!/usr/bin/env python3
# section 127
# -*- Mode: Python; py-indent-offset: 4 -*-
# vim: tabstop=4 shiftwidth=4 expandtab
#
# Copyright (C) 2010 Red Hat, Inc., John (J5) Palmieri <johnp@redhat.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
# USA
TITLE = "Builder"
DESCRIPTION = """ Demonstrates an interface loaded from a XML description. """
import os
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GdkPixbuf
class BuilderApp:
def __init__(self):
self.builder = Gtk.Builder()
filename = os.path.join(os.path.dirname(__file__), '../Data', 'builder.glade')
self.builder.add_from_file(filename)
self.builder.connect_signals(self)
self.window = self.builder.get_object('window1')
self.window.connect('destroy', lambda x: Gtk.main_quit())
self.window.show_all()
def about_activate(self, action):
about_dlg = self.builder.get_object('aboutdialog1')
# set logo
icon = GdkPixbuf.Pixbuf.new_from_file(os.path.join(os.path.dirname(__file__), "../Data/gtk-logo-rgb.gif"))
# transparent
icon = icon.add_alpha(True, 0xff, 0xff, 0xff)
about_dlg.set_logo(icon)
about_dlg.run()
about_dlg.destroy()
def quit_activate(self, action):
self.window.destroy()
Gtk.main_quit()
def main():
BuilderApp()
Gtk.main()
if __name__ == '__main__':
main()