456|6

6174

帖子

4

TA的资源

版主

【 STM32MP135F-DK测评】+(6)为制作图形界面通读python-gtk-3手册 之二 [复制链接]

本帖最后由 damiaa 于 2025-3-5 22:11 编辑
     【 STM32MP135F-DK测评】+(6)为制作图形界面通读python-gtk-3手册 之二
 
 
继续上面读第6章 Layout容器 关于布局
 
6. 布局容器

虽然许多 GUI 工具包要求您使用绝对定位将小部件精确地放置在窗口中,但 GTK+ 使用不同的方法。您可以按行、列和/或表格排列窗口小部件,而不是指定窗口中每个小部件的位置和大小。窗口的大小可以根据窗口包含的小部件的大小自动确定。而 Widget 的大小又取决于它们包含的文本量、您指定的最小和最大大小,和/或您如何请求在 Widget 集之间共享可用空间。您可以通过为每个小组件指定填充距离和居中值来完善布局。然后,当用户作窗口时,GTK+ 会使用所有这些信息来合理而平滑地调整所有内容的大小和位置。

GTK+ 使用容器分层排列小部件。它们对最终用户不可见,并入到窗口中,o
 
6.1. 盒子
盒子是我们可以将小部件装入其中的无形容器。将 widget 打包到水平框中时,对象将从左到右或从右到左水平插入,具体取决于使用的是 Gtk.Box.pack_start() 还是 Gtk.Box.pack_end()。在垂直框中,小部件从上到下打包,反之亦然。您可以在其他框内部或旁边使用任意框组合来创建所需的效果。

6.1.1. 示例
让我们看一下带有两个按钮的扩展示例的略微修改版本。
wd_220111b3zl0r63435l55ix.png
先用
self.box = Gtk.Box(spacing=6)
self.add(self.box)
创创建一个水平方向的框容器,其中 6 个像素放置在子对象之间。此框将成为顶级窗。
紧接着使用下面几句加入两个button到box容器中,当然里面也包括了连接响应函数。
 
wd_220111jcjctcjju9r090ep.png
 
使用 Gtk.Box.pack_start() widgets 定位到最左边, Gtk.Box.pack_end() 定位到最右边。
 
6.2. 网格

Gtk.Grid 是一个容器,它将其子小部件排列在行和列中,但你不需要在构造函数中指定维度。使用 Gtk.Grid.attach() 添加子项。它们可以跨多行或多列。Gtk.Grid.attach() 方法有五个参数:

child 参数是要添加的 Gtk.Widget。

left 是将 Child 的左侧附加到的列号。

top 表示要将 Child 的 top 侧附加到的行号。

width 和 height 分别表示子项将跨越的列数和子项将跨越的行数。

也可以使用 Gtk.Grid.attach_next_to() 在现有子项旁边添加一个子项,它也需要五个参数:

child 是要添加的 Gtk.Widget,如上所述。

sibling 是 self (一个 Gtk.Grid 实例) 或 None 的现有子小部件。子小部件将放置在 sibling 旁边,或者如果 sibling 为 None,则放置在网格的开头或结尾。

side 是一个 Gtk.PositionType,表示子项位于该子项旁边的兄弟姐妹的一侧。

width 和 height 分别表示子 widget 将跨越的列数和行数。

最后,Gtk.Grid可以像Gtk.Box一样使用,只需使用Gtk.Grid.add(),它将按照“orientation”属性(默认为Gtk.Orientation.HORIZONTAL)确定的方向将子项彼此相邻放置。
 
6.2.1. Example
 
下面的代码运行后会这样:
wd_220111p8fgp48og47ujp1k.png
wd_220111dherznz0hlna99h4.png
wd_220111c8kv0zbgl6fbigjy.png
6.3. ListBox

Gtk.ListBox 是一个包含 Gtk.ListBoxRow 子项的垂直容器。这些行可以动态排序和筛选,并且可以根据行内容动态添加标题。它还允许键盘和鼠标导航和选择,就像典型的列表一样。

使用 Gtk.ListBox 通常是 Gtk.TreeView 的替代方案,特别是当列表内容的布局比 Gtk.CellRenderer 允许的布局更复杂时,或者当内容是交互式的(例如,里面有一个按钮)时。

虽然 Gtk.ListBox 必须只有 Gtk.ListBoxRow 子项,但你可以通过 Gtk.Container.add() 向它添加任何类型的小部件,并且 Gtk.ListBoxRow 小部件将自动插入到列表和小部件之间。
6.3.1. Example
wd_220111jyq3of9osayws2oe.png
import gi

gi.require_version("Gtk", "3.0")
from gi.repository import Gtk


class ListBoxRowWithData(Gtk.ListBoxRow):
    def __init__(self, data):
        super().__init__()
        self.data = data
        self.add(Gtk.Label(label=data))


class ListBoxWindow(Gtk.Window):
    def __init__(self):
        super().__init__(title="ListBox Demo")
        self.set_border_width(10)

        box_outer = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
        self.add(box_outer)

        listbox = Gtk.ListBox()
        listbox.set_selection_mode(Gtk.SelectionMode.NONE)
        box_outer.pack_start(listbox, True, True, 0)

        row = Gtk.ListBoxRow()
        hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=50)
        row.add(hbox)
        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        hbox.pack_start(vbox, True, True, 0)

        label1 = Gtk.Label(label="Automatic Date & Time", xalign=0)
        label2 = Gtk.Label(label="Requires internet access", xalign=0)
        vbox.pack_start(label1, True, True, 0)
        vbox.pack_start(label2, True, True, 0)

        switch = Gtk.Switch()
        switch.props.valign = Gtk.Align.CENTER
        hbox.pack_start(switch, False, True, 0)

        listbox.add(row)

        row = Gtk.ListBoxRow()
        hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=50)
        row.add(hbox)
        label = Gtk.Label(label="Enable Automatic Update", xalign=0)
        check = Gtk.CheckButton()
        hbox.pack_start(label, True, True, 0)
        hbox.pack_start(check, False, True, 0)

        listbox.add(row)

        row = Gtk.ListBoxRow()
        hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=50)
        row.add(hbox)
        label = Gtk.Label(label="Date Format", xalign=0)
        combo = Gtk.ComboBoxText()
        combo.insert(0, "0", "24-hour")
        combo.insert(1, "1", "AM/PM")
        hbox.pack_start(label, True, True, 0)
        hbox.pack_start(combo, False, True, 0)

        listbox.add(row)

        listbox_2 = Gtk.ListBox()
        items = "This is a sorted ListBox Fail".split()

        for item in items:
            listbox_2.add(ListBoxRowWithData(item))

        def sort_func(row_1, row_2, data, notify_destroy):
            return row_1.data.lower() > row_2.data.lower()

        def filter_func(row, data, notify_destroy):
            return False if row.data == "Fail" else True

        listbox_2.set_sort_func(sort_func, None, False)
        listbox_2.set_filter_func(filter_func, None, False)

        def on_row_activated(listbox_widget, row):
            print(row.data)

        listbox_2.connect("row-activated", on_row_activated)

        box_outer.pack_start(listbox_2, True, True, 0)
        listbox_2.show_all()


win = ListBoxWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()

 

 
6.4. Stack 和 StackSwitcher
Gtk.Stack 是一个一次只显示其一个子项的容器。与 Gtk.Notebook 相比,Gtk.Stack 没有为用户提供更改可见子项的方法。相反,Gtk.StackSwitcher 小部件可以与 Gtk.Stack 一起使用来提供此功能。

页面之间的过渡效果可以动画化为幻灯片或淡化效果。这可以通过 Gtk.Stack.set_transition_type() 进行控制。这些动画遵循 “gtk-enable-animations” 设置。

过渡速度可通过 Gtk.Stack.set_transition_duration() 进行调整

Gtk.StackSwitcher 小部件充当 Gtk.Stack 的控制器;它显示一行按钮,用于在关联的 Stack Widget 的各个页面之间切换。

按钮的所有内容都来自 Gtk.Stack 的子属性。

可以将多个 Gtk.StackSwitcher 小部件与同一个 Gtk.Stack 小部件相关联。

6.4.1. 示例
wd_220112cj3ye6efaile2gaa.png
import gi

gi.require_version("Gtk", "3.0")
from gi.repository import Gtk


class StackWindow(Gtk.Window):
    def __init__(self):
        super().__init__(title="Stack Demo")
        self.set_border_width(10)

        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
        self.add(vbox)

        stack = Gtk.Stack()
        stack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT_RIGHT)
        stack.set_transition_duration(1000)

        checkbutton = Gtk.CheckButton(label="Click me!")
        stack.add_titled(checkbutton, "check", "Check Button")

        label = Gtk.Label()
        label.set_markup("<big>A fancy label</big>")
        stack.add_titled(label, "label", "A label")

        stack_switcher = Gtk.StackSwitcher()
        stack_switcher.set_stack(stack)
        vbox.pack_start(stack_switcher, True, True, 0)
        vbox.pack_start(stack, True, True, 0)


win = StackWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()

 

 
6.5. HeaderBar
Gtk.HeaderBar 类似于水平的 Gtk.Box,它允许将子项放在开头或结尾。此外,它还允许显示标题。标题将相对于框的宽度居中,即使两侧的子对象占用的空间量不同。

由于 GTK+ 现在支持客户端装饰,因此可以使用 Gtk.HeaderBar 代替标题栏(由窗口管理器呈现)。

Gtk.HeaderBar 通常位于窗口的顶部,并且应该包含影响下面内容的常用控件。它们还提供对窗口控件的访问,包括关闭窗口按钮和窗口菜单。

6.5.1. 示例
wd_220112cdeelhd6dw78ii6x.png
import gi

gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gio


class HeaderBarWindow(Gtk.Window):
    def __init__(self):
        super().__init__(title="HeaderBar Demo")
        self.set_border_width(10)
        self.set_default_size(400, 200)

        hb = Gtk.HeaderBar()
        hb.set_show_close_button(True)
        hb.props.title = "HeaderBar example"
        self.set_titlebar(hb)

        button = Gtk.Button()
        icon = Gio.ThemedIcon(name="mail-send-receive-symbolic")
        image = Gtk.Image.new_from_gicon(icon, Gtk.IconSize.BUTTON)
        button.add(image)
        hb.pack_end(button)

        box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
        Gtk.StyleContext.add_class(box.get_style_context(), "linked")

        button = Gtk.Button()
        button.add(
            Gtk.Arrow(arrow_type=Gtk.ArrowType.LEFT, shadow_type=Gtk.ShadowType.NONE)
        )
        box.add(button)

        button = Gtk.Button.new_from_icon_name("pan-end-symbolic", Gtk.IconSize.MENU)
        box.add(button)

        hb.pack_start(box)

        self.add(Gtk.TextView())


win = HeaderBarWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()

 

 
6.6. FlowBox
注意

这个例子至少需要 GTK+ 3.12。

Gtk.FlowBox 是一个容器,它根据子部件的方向按顺序定位子部件。

例如,在水平方向下,小部件将从左到右排列,必要时在上一行下开始新行。在这种情况下,减小宽度将需要更多的行,因此将需要更大的高度。

同样,在垂直方向下,小部件将从上到下排列,必要时从右侧开始一个新的列。减小高度将需要更多的列,因此将需要更大的宽度。

Gtk.FlowBox 的子级可以动态排序和过滤。

虽然 Gtk.FlowBox 必须只有 Gtk.FlowBoxChild 子项,但你可以通过 Gtk.Container.add() 向它添加任何类型的小部件,并且 Gtk.FlowBoxChild 小部件将自动插入到盒子和小部件之间。

6.6.1. 示例
wd_220112vh8edydvotddmtvh.png
import gi

gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk


class FlowBoxWindow(Gtk.Window):
    def __init__(self):
        super().__init__(title="FlowBox Demo")
        self.set_border_width(10)
        self.set_default_size(300, 250)

        header = Gtk.HeaderBar(title="Flow Box")
        header.set_subtitle("Sample FlowBox app")
        header.props.show_close_button = True

        self.set_titlebar(header)

        scrolled = Gtk.ScrolledWindow()
        scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)

        flowbox = Gtk.FlowBox()
        flowbox.set_valign(Gtk.Align.START)
        flowbox.set_max_children_per_line(30)
        flowbox.set_selection_mode(Gtk.SelectionMode.NONE)

        self.create_flowbox(flowbox)

        scrolled.add(flowbox)

        self.add(scrolled)
        self.show_all()

    def on_draw(self, widget, cr, data):
        context = widget.get_style_context()

        width = widget.get_allocated_width()
        height = widget.get_allocated_height()
        Gtk.render_background(context, cr, 0, 0, width, height)

        r, g, b, a = data["color"]
        cr.set_source_rgba(r, g, b, a)
        cr.rectangle(0, 0, width, height)
        cr.fill()

    def color_swatch_new(self, str_color):
        rgba = Gdk.RGBA()
        rgba.parse(str_color)

        button = Gtk.Button()

        area = Gtk.DrawingArea()
        area.set_size_request(24, 24)
        area.connect("draw", self.on_draw, {"color": rgba})

        button.add(area)

        return button

    def create_flowbox(self, flowbox):
        colors = [
            "AliceBlue",
            "AntiqueWhite",
            "AntiqueWhite1",
            "AntiqueWhite2",
            "AntiqueWhite3",
            "AntiqueWhite4",
            "aqua",
            "aquamarine",
            "aquamarine1",
            "aquamarine2",
            "aquamarine3",
            "aquamarine4",
            "azure",
            "azure1",
            "azure2",
            "azure3",
            "azure4",
            "beige",
            "bisque",
            "bisque1",
            "bisque2",
            "bisque3",
            "bisque4",
            "black",
            "BlanchedAlmond",
            "blue",
            "blue1",
            "blue2",
            "blue3",
            "blue4",
            "BlueViolet",
            "brown",
            "brown1",
            "brown2",
            "brown3",
            "brown4",
            "burlywood",
            "burlywood1",
            "burlywood2",
            "burlywood3",
            "burlywood4",
            "CadetBlue",
            "CadetBlue1",
            "CadetBlue2",
            "CadetBlue3",
            "CadetBlue4",
            "chartreuse",
            "chartreuse1",
            "chartreuse2",
            "chartreuse3",
            "chartreuse4",
            "chocolate",
            "chocolate1",
            "chocolate2",
            "chocolate3",
            "chocolate4",
            "coral",
            "coral1",
            "coral2",
            "coral3",
            "coral4",
        ]

        for color in colors:
            button = self.color_swatch_new(color)
            flowbox.add(button)


win = FlowBoxWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()

 

 
6.7. notebook笔记本

Gtk.Notebook 小部件是一个 Gtk.Container,它的子组件是可以在沿一个边缘使用标签标签之间切换的页面。

GtkNotebook 有许多配置选项。除其他外,你可以选择选项卡出现在哪个边缘(参见 Gtk.Notebook.set_tab_pos()),如果选项卡太多而无法容纳笔记本,是否应该放大或添加滚动箭头(参见 Gtk.Notebook.set_scrollable()),以及是否会有一个弹出菜单允许用户切换页面(参见 Gtk.Notebook.popup_enable()、Gtk.Notebook.popup_disable())。

6.7.1. 示例
wd_220112n856608szhgoyhg9.png
import gi

gi.require_version("Gtk", "3.0")
from gi.repository import Gtk


class MyWindow(Gtk.Window):
    def __init__(self):
        super().__init__(title="Simple Notebook Example")
        self.set_border_width(3)

        self.notebook = Gtk.Notebook()
        self.add(self.notebook)

        self.page1 = Gtk.Box()
        self.page1.set_border_width(10)
        self.page1.add(Gtk.Label(label="Default Page!"))
        self.notebook.append_page(self.page1, Gtk.Label(label="Plain Title"))

        self.page2 = Gtk.Box()
        self.page2.set_border_width(10)
        self.page2.add(Gtk.Label(label="A page with an image for a Title."))
        self.notebook.append_page(
            self.page2, Gtk.Image.new_from_icon_name("help-about", Gtk.IconSize.MENU)
        )


win = MyWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()

 

 
                                                                   先写到这里,谢谢

此帖出自stm32/stm8论坛

最新回复

gtk哦?如果不是复杂图形还不如用tcl那个就行了。   详情 回复 发表于 3 天前

回复
举报

7002

帖子

0

TA的资源

五彩晶圆(高级)

关于 Layout容器 布局总结写的真详细了

此帖出自stm32/stm8论坛

点评

感谢支持。学习一下顺便分享。  详情 回复 发表于 2025-3-6 08:39

回复

6174

帖子

4

TA的资源

版主

Jacktang 发表于 2025-3-6 07:31 关于 Layout容器 布局总结写的真详细了

感谢支持。学习一下顺便分享。

此帖出自stm32/stm8论坛

回复

739

帖子

0

TA的资源

纯净的硅(高级)

好像确实没有使用Qt开发来得快啊

此帖出自stm32/stm8论坛

点评

还可以吧。gtk看上去就那么些套路。比较好掌握。 加上 python 可以敲完源代码直接运行。所敲即所得啊。 gtk支持c 还有其他几种语言。    详情 回复 发表于 2025-3-6 10:22

回复

6174

帖子

4

TA的资源

版主

jobszheng5 发表于 2025-3-6 10:10 好像确实没有使用Qt开发来得快啊

还可以吧。gtk看上去就那么些套路。比较好掌握。

加上 python 可以敲完源代码直接运行。所敲即所得啊。

gtk支持c 还有其他几种语言。

 

此帖出自stm32/stm8论坛

回复

7754

帖子

2

TA的资源

五彩晶圆(高级)

gtk哦?如果不是复杂图形还不如用tcl那个就行了。

此帖出自stm32/stm8论坛

点评

有道理。  详情 回复 发表于 3 天前
个人签名

默认摸鱼,再摸鱼。2022、9、28


回复

6174

帖子

4

TA的资源

版主

freebsder 发表于 2025-3-17 15:16 gtk哦?如果不是复杂图形还不如用tcl那个就行了。

有道理。

此帖出自stm32/stm8论坛

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网 5

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表