PythonGtk教程展示了如何使用Gtk模块在Python中创建GUI应用程序。本教程涵盖GTK4。
GTK
GTK是一个用于创建图形用户界面的多平台工具包。它是用C语言创建的。GTK经过全新设计,支持多种语言,包括Python、Ruby和Perl。
GTK库也称为GIMP工具包。最初,该库是在开发GIMP图像处理程序时创建的。从此,GTK成为Linux和BSDUnix下最流行的工具包之一。
#!/usr/bin/python
import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk
print(f'{Gtk.MAJOR_VERSION}.{Gtk.MINOR_VERSION}.{Gtk.MICRO_VERSION}')
我们通过语言内省访问GTK库。PyGObject是C库的语言接口。
import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk
我们导入Gtk模块。require_version方法确保命名空间加载给定版本。gi.repository是PyGObject的Python模块。PyGObject(PythonGObject自省)包含Python绑定和对GObject、GLib、GTK和其他库的支持。
$ ./version.py 4.6.5
PythonGtk简单例子
在第一个应用程序中,我们在屏幕上显示一个窗口。Gtk.Window是一个可以包含其他小部件的顶层窗口。换句话说,它是一个容器。Windows通常具有受窗口系统控制的装饰,并允许用户操作窗口。
#!/usr/bin/python
import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk
def on_activate(app):
win = Gtk.ApplicationWindow(application=app)
win.set_title('Simple')
win.present()
app = Gtk.Application(application_id='com.zetcode.Simple')
app.connect('activate', on_activate)
app.run(None)
该示例在屏幕上显示一个小窗口。
def on_activate(app):
win = Gtk.ApplicationWindow(application=app)
win.set_title('Simple')
win.present()
我们在on_activate函数中创建主应用程序窗口。我们使用set_title设置应用程序的标题,并使用present将其呈现给用户。
app = Gtk.Application(application_id='com.zetcode.Simple')
app.connect('activate', on_activate)
app.run(None)
我们创建一个新的Gtk.Application。要设置应用程序,我们连接到activate信号,该信号在应用程序激活时发出。run函数运行应用程序。
在下一个示例中,我们将以OOP风格重写示例。
#!/usr/bin/python
import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk
class AppWindow(Gtk.ApplicationWindow):
def __init__(self, app):
super(AppWindow, self).__init__(application=app)
self.init_ui()
def init_ui(self):
self.set_title('Simple')
self.set_default_size(350, 250)
def on_activate(app):
win = AppWindow(app)
win.present()
app = Gtk.Application(application_id='com.zetcode.Simple')
app.connect('activate', on_activate)
app.run(None)
我们创建一个继承自Gtk.ApplicationWindow的类。我们在init_ui库中构建UI。
self.set_default_size(350, 250)
使用set_default_size函数,我们设置应用程序窗口的默认大小。
PythonGtk.Image
Gtk.Image显示图像。如果文件加载不成功,图像将包含一个“损坏的图像”图标。
#!/usr/bin/python
import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk
class AppWindow(Gtk.ApplicationWindow):
def __init__(self, app):
super(AppWindow, self).__init__(application=app)
self.init_ui()
def init_ui(self):
self.set_title('Image')
image = Gtk.Image.new_from_file('sid.png')
self.set_child(image)
self.set_default_size(450, 350)
def on_activate(app):
win = AppWindow(app)
win.present()
app = Gtk.Application(application_id='com.zetcode.Image')
app.connect('activate', on_activate)
app.run(None)
该示例在窗口上显示PNG图像。
image = Gtk.Image.new_from_file('sid.png')
Gtk.Image是从文件创建的。
self.set_child(image)
我们将图像设置为应用程序窗口的主容器。
PythonGtk.Button
Gtk.Button用于触发按下按钮时调用的回调函数。
#!/usr/bin/python
import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk
class AppWindow(Gtk.ApplicationWindow):
def __init__(self, app):
super(AppWindow, self).__init__(application=app)
self.init_ui()
def init_ui(self):
self.set_title('Quit button')
box = Gtk.Box.new(Gtk.Orientation.VERTICAL, 0)
box.set_margin_start(5)
box.set_margin_top(5)
btn = Gtk.Button(label="Quit")
btn.connect('clicked', lambda _: self.close())
btn.set_halign(Gtk.Align.START)
box.append(btn)
self.set_default_size(350, 250)
self.set_child(box)
def on_activate(app):
win = AppWindow(app)
win.present()
app = Gtk.Application(application_id='com.zetcode.QuitButton')
app.connect('activate', on_activate)
app.run(None)
在示例中,我们有一个按钮。当我们按下按钮时,应用程序终止。
box = Gtk.Box.new(Gtk.Orientation.VERTICAL, 0) box.set_margin_start(5) box.set_margin_top(5)
我们创建一个垂直框。我们在框的左侧和顶部放置了一些边距。Gtk.Box是一个简单的布局小部件,可以将小部件排列成一行或一列。
btn = Gtk.Button(label="Quit")
创建了一个Gtk.Button。
btn.connect('clicked', lambda _: self.close())
当按钮被点击时,它发出一个clicked信号。使用connect方法,我们将信号绑定到self.close方法.
btn.set_halign(Gtk.Align.START) box.append(btn)
我们将按钮对齐到框的左侧并将其添加到垂直框。
self.set_default_size(350, 250) self.set_child(box)
最后,我们设置应用程序窗口的默认大小,并将垂直框添加到窗口容器中。
PythonGtk.CheckButton
Gtk.CheckButton一个有两种状态的小部件:打开和关闭。onstate通过复选标记可视化。
#!/usr/bin/python
import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk
class AppWindow(Gtk.ApplicationWindow):
def __init__(self, app):
super(AppWindow, self).__init__(application=app)
self.init_ui()
def init_ui(self):
self.set_title('Check button')
box = Gtk.Box.new(Gtk.Orientation.VERTICAL, 0)
box.set_margin_start(5)
box.set_margin_top(5)
cbtn = Gtk.CheckButton.new_with_label('Show title')
cbtn.set_active(True)
cbtn.connect('toggled', self.on_toggle)
box.append(cbtn)
self.set_child(box)
self.set_default_size(450, 350)
def on_toggle(self, wid):
if wid.get_active():
self.set_title('CheckButton')
else:
self.set_title('')
def on_activate(app):
win = AppWindow(app)
win.present()
app = Gtk.Application(application_id='com.zetcode.CheckButton')
app.connect('activate', on_activate)
app.run(None)
该示例根据Gtk.CheckButton的状态在窗口的标题栏中显示一个标题。
cbtn = Gtk.CheckButton.new_with_label('Show title')
cbtn.set_active(True)
Gtk.CheckButton已创建。由于默认情况下窗口的标题是可见的,我们使用set_active激活按钮。
cbtn.connect('toggled', self.on_toggle)
当我们选中或取消选中Gtk.CheckButton时,会发出toggled信号。我们将on_toggle处理程序插入信号。
def on_toggle(self, wid):
if wid.get_active():
self.set_title('CheckButton')
else:
self.set_title('')
我们使用get_active确定Gtk.CheckButton的状态并相应地设置标题。
按键事件
下一个示例对key-pressed事件作出反应。
#!/usr/bin/python
import gi
from gi.repository import Gtk
gi.require_version("Gtk", "4.0")
class AppWindow(Gtk.ApplicationWindow):
def __init__(self, app):
super(AppWindow, self).__init__(application=app)
self.init_ui()
def init_ui(self):
self.set_title('Key press')
keycont = Gtk.EventControllerKey()
keycont.connect('key-pressed', self.on_key_pressed)
self.add_controller(keycont)
self.set_default_size(350, 250)
# keyval, keycode, state, user_data
def on_key_pressed(self, keyval, keycode, *_):
if keycode == ord('q'):
self.close()
def on_activate(app):
win = AppWindow(app)
win.present()
app = Gtk.Application(application_id='com.zetcode.KeyPress')
app.connect('activate', on_activate)
app.run(None)
应用程序监听按键事件。如果用户输入q键,则应用程序终止。
keycont = Gtk.EventControllerKey()
keycont.connect('key-pressed', self.on_key_pressed)
self.add_controller(keycont)
我们创建并注册了Gtk.EventControllerKey。我们连接到key-pressed信号。
# keyval, keycode, state, user_data
def on_key_pressed(self, keyval, keycode, *_):
if keycode == ord('q'):
self.close()
我们检查键码。如果是q,我们关闭应用程序。
PythonGtk.Entry
Gtk.Entry小部件是一个单行文本输入小部件。默认情况下支持许多键绑定。如果输入的文本比小部件的分配长,小部件将滚动以便光标位置可见。
#!/usr/bin/python
import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk
class AppWindow(Gtk.ApplicationWindow):
def __init__(self, app):
super(AppWindow, self).__init__(application=app)
self.init_ui()
def init_ui(self):
self.set_title('Quit button')
vbox = Gtk.Box.new(Gtk.Orientation.VERTICAL, 8)
hbox = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 8)
vbox.set_margin_start(5)
vbox.set_margin_top(5)
self.entry = Gtk.Entry()
hbox.append(self.entry)
keycont = Gtk.EventControllerKey()
keycont.connect('key-released', self.on_key_released)
self.add_controller(keycont)
self.label = Gtk.Label.new('...')
hbox.append(self.label)
self.set_title('Entry')
self.set_default_size(450, 350)
vbox.append(hbox)
self.set_child(vbox)
def on_key_released(self, *_):
self.label.set_text(self.entry.get_text())
def on_activate(app):
win = AppWindow(app)
win.present()
app = Gtk.Application(application_id='com.zetcode.QuitButton')
app.connect('activate', on_activate)
app.run(None)
在示例中,我们有一个条目小部件和一个标签。输入到条目中的文本显示在标签中。
vbox = Gtk.Box.new(Gtk.Orientation.VERTICAL, 8) hbox = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 8)
布局是通过垂直和水平框的组合创建的。
self.entry = Gtk.Entry()
我们创建了Gtk.Entry小部件。
keycont = Gtk.EventControllerKey()
keycont.connect('key-released', self.on_key_released)
self.add_controller(keycont)
为了能够处理按键事件,我们创建了一个Gtk.EventControllerKey。我们对on_key_released事件作出反应。
def on_key_released(self, *_):
self.label.set_text(self.entry.get_text())
在on_key_released事件处理程序中,我们使用get_text从条目中获取文本,并使用set_text将其设置为标签。
PythonGtk.ComboBoxText
Gtk.ComboBoxText是Gtk.ComboBox的一个简单变体,它隐藏了简单的纯文本用例的模型视图复杂性。
#!/usr/bin/python
import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk
class AppWindow(Gtk.ApplicationWindow):
def __init__(self, app):
super(AppWindow, self).__init__(application=app)
self.init_ui()
def init_ui(self):
self.set_title('Quit button')
vbox = Gtk.Box.new(Gtk.Orientation.VERTICAL, 8)
hbox = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 8)
combo = Gtk.ComboBoxText()
vbox.set_margin_start(5)
vbox.set_margin_top(5)
hbox.append(combo)
combo.connect('changed', self.on_changed)
combo.append_text('Arch')
combo.append_text('Fedora')
combo.append_text('Redhat')
combo.append_text('Gentoo')
combo.append_text('Xubuntu')
self.label = Gtk.Label.new('')
hbox.append(self.label)
self.set_title('ComboBoxText')
self.set_default_size(450, 350)
vbox.append(hbox)
self.set_child(vbox)
def on_changed(self, wid):
self.label.set_label(wid.get_active_text())
def on_activate(app):
win = AppWindow(app)
win.present()
app = Gtk.Application(application_id='com.zetcode.ComboBoxText')
app.connect('activate', on_activate)
app.run(None)
在示例中,我们有一个Gtk.ComboBoxText和一个标签。从组合框中选择的项目显示在标签小部件中。
combo = Gtk.ComboBoxText()
Gtk.ComboBoxText已创建。
combo.connect('changed', self.on_changed)
当活动项目发生变化时,changed信号被发射。
combo.append_text('Arch')
combo.append_text('Fedora')
combo.append_text('Redhat')
combo.append_text('Gentoo')
combo.append_text('Xubuntu')
我们向组合框添加五个文本项。
def on_changed(self, wid):
self.label.set_label(wid.get_active_text())
在on_changed事件处理程序中,我们使用get_active_text获取活动文本,并使用set_label将其设置为标签。
绘图
绘图是在Gtk.DrawingArea小部件上完成的。
#!/usr/bin/python
import gi
gi.require_version('Gtk', '4.0')
import math
from gi.repository import Gtk
class AppWindow(Gtk.ApplicationWindow):
def __init__(self, app):
super(AppWindow, self).__init__(application=app)
self.init_ui()
def init_ui(self):
self.set_title('Drawing')
area = Gtk.DrawingArea.new()
area.set_draw_func(self.on_draw)
self.set_default_size(450, 300)
self.set_child(area)
def on_draw(self, da, ctx, w, h):
ctx.set_source_rgb(0.6, 0.6, 0.6)
ctx.rectangle(20, 20, 120, 80)
ctx.rectangle(180, 20, 80, 80)
ctx.fill()
ctx.arc(330, 60, 40, 0, 2*math.pi)
ctx.fill()
ctx.arc(90, 160, 40, math.pi/4, math.pi)
ctx.fill()
ctx.translate(220, 180)
ctx.scale(1, 0.7)
ctx.arc(0, 0, 50, 0, 2*math.pi)
ctx.fill()
def on_activate(app):
win = AppWindow(app)
win.present()
app = Gtk.Application(application_id='com.zetcode.Drawing')
app.connect('activate', on_activate)
app.run(None)
该示例绘制了一些基本形状。
area = Gtk.DrawingArea.new() area.set_draw_func(self.on_draw)
我们创建Gtk.DrawingArea并使用set_draw_func设置绘图功能。
def on_draw(self, da, ctx, w, h):
...
on_draw的第二个参数是绘图区域,第三个是绘图上下文。上下文是一个用于在所有可绘制对象上绘制的对象。最后两个参数是区域的宽度和高度。
ctx.set_source_rgb(0.6, 0.6, 0.6)
set_source_rgb方法为绘图上下文设置颜色。该方法的三个参数是颜色强度值。取值范围为0到1。
ctx.rectangle(20, 20, 120, 80) ctx.rectangle(180, 20, 80, 80) ctx.fill()
我们绘制两个矩形。fill方法以先前设置的颜色绘制矩形的内部。
ctx.arc(330, 60, 40, 0, 2*math.pi) ctx.fill()
使用arc方法,我们画了一个完整的圆。
ctx.translate(220, 180)
translate方法将用户空间原点移动deltax和deltay。
ctx.scale(1, 0.7) ctx.arc(0, 0, 50, 0, 2*math.pi) ctx.fill()
如果我们想画一个椭圆,我们先做一些缩放。这里scale方法缩小了y轴。
PythonGtk.Menu
在下一个示例中,我们将创建一个带有菜单栏的应用程序。
#!/usr/bin/python
import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk, Gio
class AppWindow(Gtk.ApplicationWindow):
def __init__(self, app):
super(AppWindow, self).__init__(application=app)
self.init_ui(app)
def init_ui(self, app):
self.set_title('Simple menu')
main = Gio.Menu.new()
fmi = Gio.MenuItem.new('File')
menu = Gio.Menu.new()
emi = Gio.MenuItem.new('Exit', 'app.quit')
menu.append_item(emi)
fmi.set_submenu(menu)
main.append_item(fmi)
app.set_menubar(main)
act_quit = Gio.SimpleAction.new('quit', None)
Gio.ActionMap.add_action(app, act_quit)
act_quit.connect('activate', self.on_close, app)
self.set_show_menubar(True)
self.set_default_size(350, 250)
def on_close(self, *_):
self.close()
def on_activate(app):
win = AppWindow(app)
win.present()
app = Gtk.Application(application_id='com.zetcode.SimpleMenu')
app.connect('activate', on_activate)
app.run(None)
菜单栏有一个菜单项,它终止了应用程序。
main = Gio.Menu.new()
fmi = Gio.MenuItem.new('File')
menu = Gio.Menu.new()
emi = Gio.MenuItem.new('Exit', 'app.quit')
menu.append_item(emi)
fmi.set_submenu(menu)
main.append_item(fmi)
我们设置菜单和菜单项。app.quit字符串是指在应用程序对象中注册的操作。
app.set_menubar(main)
我们使用set_menubar设置菜单栏。
act_quit = Gio.SimpleAction.new('quit', None)
Gio.ActionMap.add_action(app, act_quit)
act_quit.connect('activate', self.on_close, app)
创建了一个简单的动作;该操作调用on_close,它会终止应用程序。
self.set_show_menubar(True)
我们使用set_show_menubar显示菜单栏。
CSS主题
我们可以使用CSS为我们的应用设置主题。
window {
background-color: rgb(59, 56, 56);
}
button {
color: rgb(233, 32, 27);
}
在CSS中,我们为窗口设置自定义背景色,为按钮设置自定义前景色。
#!/usr/bin/python
import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk, Gio
class AppWindow(Gtk.ApplicationWindow):
def __init__(self, app):
super(AppWindow, self).__init__(application=app)
self.init_ui()
def init_ui(self):
self.set_title('CSS theme')
box = Gtk.Box.new(Gtk.Orientation.VERTICAL, 0)
btn = Gtk.Button(label="Quit")
btn.connect('clicked', lambda _: self.close())
btn.set_margin_start(5)
btn.set_margin_top(5)
btn.set_halign(Gtk.Align.START)
box.append(btn)
self.set_child(box)
self.set_default_size(350, 250)
def on_activate(app):
win = AppWindow(app)
display = Gtk.Widget.get_display(win)
provider = Gtk.CssProvider.new()
fname = Gio.file_new_for_path('theme.css')
provider.load_from_file(fname)
Gtk.StyleContext.add_provider_for_display(display, provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
win.present()
app = Gtk.Application(application_id='com.zetcode.CheckButton')
app.connect('activate', on_activate)
app.run(None)
主题是使用Gtk.CssProvider创建的。在此示例中,我们从文件加载CSS。
display = Gtk.Widget.get_display(win)
provider = Gtk.CssProvider.new()
fname = Gio.file_new_for_path('theme.css')
provider.load_from_file(fname)
Gtk.StyleContext.add_provider_for_display(display, provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
我们创建一个CSS提供程序,加载主题,并将提供程序应用于显示。
在本教程中,我们使用PythonGtk创建了基本的GUI应用程序。
列出所有Python教程。
