python - 使用 PyGObject 自定义 Gtk.Container

标签 python gtk3 pygobject

我正在尝试使用 PyGObject 实现自定义 Gtk.Container。但是我遇到了问题,甚至不知道是这个错误,还是我的实现是错误的。这是我的测试代码片段:

from gi.repository import Gtk, Gdk
import sys

class TestContainer(Gtk.Container):
    __gtype_name__ = "TestContainer"

    def __init__(self, *args, **kwargs):
        self.children = []
        super().__init__()

    def do_add(self, widget):
        self.children.append(widget)
        widget.set_parent(self)

    def do_remove(self, widget):
        self.children.remove(widget)
        widget.unparent()
                    
    def do_child_type(self):
        print("do_child_type()")
        return(Gtk.Widget.get_type())

    def do_forall(self, include_internals, callback, *callback_parameters):
        print("do_forall() self = %x" % id(self))
        if not callback is None:
            for widget in self.children:
                callback(widget, *callback_parameters)

    def do_get_request_mode(self):
        print("do_get_request_mode()")
        return(Gtk.SizeRequestMode.CONSTANT_SIZE)

    def do_get_preferred_height(self):
        print("do_get_preferred_height()")
        result = (50, 50)
        return(result)

    def do_get_preferred_width(self):
        print("do_get_preferred_width()")
        min_width = 0
        nat_width = 0

        for widget in self.children:
            child_min_width, child_nat_width = widget.get_preferred_width()
            min_width = min_width + child_min_width
            nat_width = nat_width + child_nat_width

        return(min_width, nat_width)

    def do_size_allocate(self, allocation):
        print("do_size_allocate()")
        child_allocation = Gdk.Rectangle()

        self.set_allocation(allocation)

        if self.get_has_window():
            if self.get_realized():
                self.get_window().move_resize(allocation.x, allocation.y, allocation.width, allocation.height)

        for widget in self.children:
            if widget.get_visible():
                min_size, nat_size = widget.get_preferred_size()

                child_allocation.x = 0
                child_allocation.y = 0

                if not widget.get_has_window():
                    child_allocation.x = child_allocation.x + allocation.x
                    child_allocation.y = child_allocation.x + allocation.x

                child_allocation.width = min_size.width
                child_allocation.height = min_size.height

                widget.size_allocate(child_allocation)

    def do_realize(self):
        print("do_realize()")
        allocation = self.get_allocation()
        
        attr = Gdk.WindowAttr()
        attr.window_type = Gdk.WindowType.CHILD
        attr.x = allocation.x
        attr.y = allocation.y
        attr.width = allocation.width
        attr.height = allocation.height
        attr.visual = self.get_visual()
        attr.event_mask = self.get_events() | Gdk.EventMask.EXPOSURE_MASK
        
        WAT = Gdk.WindowAttributesType
        mask = WAT.X | WAT.Y | WAT.VISUAL
        
        window = Gdk.Window(self.get_parent_window(), attr, mask);
        window.set_decorations(0)
        self.set_window(window)
        self.register_window(window)
        self.set_realized(True)

    def do_draw(self, cr):
        allocation = self.get_allocation()
        Gtk.render_background(self.get_style_context(), cr, 0, 0, allocation.width, allocation.height)

        for widget in self.children:
            self.propagate_draw(widget, cr)

class TestWindow(Gtk.Window):
    __gtype_name__ = "TestWindow"
    def __init__(self):
        Gtk.Window.__init__(self, title="GTK3 PyGObject Custom Container Test")

        label = Gtk.Label(label = "Text")

        self.area = TestContainer()
        self.area.add(label)
        self.add(self.area)
        self.show_all()

    def _on_quit(self, widget, event):
        Gtk.main_quit()


MainWindow = TestWindow()
MainWindow.connect("delete-event", MainWindow._on_quit)
MainWindow.show_all()
Gtk.main()

在您关闭窗口之前一切正常。关闭窗口后我得到了这个:

Traceback (most recent call last):
  File "/home/cheatfate/Projects/test_container.py", line 36, in do_forall
    if not callback is None:
AttributeError: 'TestContainer' object has no attribute 'children'
Error in sys.excepthook:
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/apport_python_hook.py", line 58, in apport_excepthook
    from cStringIO import StringIO
  File "<frozen importlib._bootstrap>", line 1565, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1523, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 1475, in _find_module
TypeError: 'NoneType' object is not iterable

Original exception was:
Traceback (most recent call last):
  File "/home/cheatfate/Projects/test_container.py", line 36, in do_forall
    if not callback is None:
AttributeError: 'TestContainer' object has no attribute 'children'
Error in sys.excepthook:

Original exception was:

经过一些调查,我发现由于某种原因,我的 TestContainer 在内存中移动到其他地址并丢失了我所有的私有(private)变量。如您所见,我们进入了标准输出:

do_forall() self = 7f97be2c5140
do_forall() self = 7f97c7cc7820

所以问题将是“我做错了什么?”

最佳答案

似乎是一个错误,所以我已经提交了https://bugzilla.gnome.org/show_bug.cgi?id=722562

关于python - 使用 PyGObject 自定义 Gtk.Container,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21214732/

相关文章:

python - Django REST 框架 : Flatten nested JSON to many objects

python - 使用另一个列表 python 从列表创建索引值数组

python - if 语句和多个条件出错

退出 fork 窗口管理器后无法输入 GtkEntry

python - Gtk.Button 是否有任何事件会在按下按钮时重复执行代码?

python - 如何在笔记本选项卡pygtk中获取输入字段作为密码(*)

python - 如何使用 PyGI 获取带有 Wnck 的窗口列表?

linux - 值错误 : Namespace Gtk not available

python - PyGTK+3 (PyGObject) 创建屏幕截图?

python - 执行python if语句时方法返回值是否存储在任何地方?