为什么 gtk.Table 花费的 space 是应该的两倍?

Why does gtk.Table takes twice as much space than it should?

我正在使用 gtk.Table 结合 EventBox 为每个单元格绘制彩色网格。在尝试了一个最小的例子后,我发现 window 是实际 table 的两倍。此外,当应用程序为 运行 时,无法进一步缩小 window。

似乎出现了可怕的错误,但我无法找出原因。这是重现不当行为的最小示例:

#!/usr/bin/env python

import pygtk
pygtk.require('2.0')
import gtk

class MyProgram:

    def __init__(self):
        app_window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        app_window.set_border_width(10)
        app_window.connect("delete_event", lambda w,e: gtk.main_quit())
        vbox_app = gtk.VBox(False, 0)
        table_layout = gtk.Table(rows=1,columns=1, homogeneous=True)
        for col in range(1,10):
                for row in range(1,5):
                        event_box = gtk.EventBox()
                        label_day = gtk.Label("")
                        label_day.set_size_request(18,18)
                        label_day.show()
                        event_box.add(label_day)
                        event_box.modify_bg(gtk.STATE_NORMAL,
                                event_box.get_colormap().alloc_color("orange"))
                        event_box.set_border_width(25)
                        event_box.show()
                        table_layout.attach(event_box, 0, col, 0, row, 0,0,0,0)
        vbox_app.pack_start(table_layout)
        app_window.add(vbox_app)
        app_window.show_all()
        return

def main():
    gtk.main()
    return 0

if __name__ == "__main__":
    MyProgram()
    main()

原来是你的event_box.set_border_width(25)受伤了。如果你只想 space 均匀你的标签,请改用 GtkTable::attach 的填充参数。

以下是不相关的改进: 不要将 gtk_main_quit 连接到 delete-event 信号,而是将其连接到 destroy 信号。 delete-event 是当你想在退出前做一些事情(例如,显示一个弹出窗口 "are you sure ? yes/no"),但是你想要的是当 window 真的被销毁时退出 gtk。

此外,在 table 中添加小部件时,不要将它们放在前面,而是附加它们并使用从 0 开始的范围,以便更容易看到小部件的添加位置([=48 中的索引=] 是 zero-based).

至于你的 VBox,在这种情况下是没有用的。如果您只有内容占用整个 window 的小部件,只需将其直接添加到您的 GtkWindow 中即可(但在我们未剥离的程序版本中可能需要它)。

最后,您不需要在每个小部件上调用 gtk_widget_show。只需专注于构建您的小部件层次结构,然后在顶层 运行 gtk_widget_show_all window。它将递归地显示其中的所有小部件。

最后给我们:

#!/usr/bin/env python

import pygtk
pygtk.require('2.0')
import gtk

class MyProgram:

    def __init__(self):
        app_window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        app_window.set_border_width(10)
        app_window.connect('destroy', lambda w: gtk.main_quit())
        table = gtk.Table(rows=1, columns=1, homogeneous=True)

        for col in range(0,9):
            for row in range(0,4):
                event_box = gtk.EventBox()
                label_day = gtk.Label('')
                label_day.set_size_request(18, 18)
                event_box.add(label_day)
                event_box.modify_bg(gtk.STATE_NORMAL,
                        event_box.get_colormap().alloc_color("orange"))
#                event_box.set_border_width(25)
                table.attach(event_box, col, col + 1, row, row + 1, 0, 0, 12, 12)
        app_window.add(table)
        app_window.show_all()


if __name__ == '__main__':
    MyProgram()
    gtk.main()

您还有一个名为 gtk-inspector 的工具,但我不知道它是否适用于 GTK 2。如果不能,请回退到 gtk-parasite。这些工具将帮助您分析 运行ning gtk 用户界面并查看其小部件的特征。

此外,GTK 3 已经推出几年了,GTK 4 也在路上。考虑将 GTK 3 用于新代码。它不再使用 pygtk,它是 pygobject 而不是通过 gi 包(GObject 自省)。

这里是python官方教程中的GTK 3:

https://python-gtk-3-tutorial.readthedocs.io/en/latest/index.html