开放的编程资料库

当前位置:我爱分享网 > Python教程 > 正文

Python 使用 Gtk

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.repositoryPyGObject的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的状态并相应地设置标题。

图: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.ComboBoxTextGtk.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.ComboBoxText

绘图

绘图是在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提供程序,加载主题,并将提供程序应用于显示。

图:CSS主题

在本教程中,我们使用PythonGtk创建了基本的GUI应用程序。

列出所有Python教程。

未经允许不得转载:我爱分享网 » Python 使用 Gtk

感觉很棒!可以赞赏支持我哟~

赞(0) 打赏