[英]How to call gtk_container_remove() on a Gtk.Container in PyGObject?
[英]Custom Gtk.Container with 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 = None
super().__init__()
def do_add(self, widget):
if not widget is None:
if not self.children is None:
self.children.append({ "widget" : widget })
else:
self.children = []
self.children.append({ "widget" : widget })
widget.set_parent(self)
def do_remove(self, widget):
print("do_remove()")
if not widget is None:
if not self.children is None:
for item in self.children:
if item["widget"] == widget:
self.children.remove(item)
widget.unparent()
break
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 self.children is None and not callback is None:
for item in self.children:
widget = item["widget"]
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
if not self.children is None:
length = len(self.children)
for item in self.children:
widget = item["widget"]
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)
if not self.children is None:
for item in self.children:
widget = item["widget"]
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 item in self.children:
self.propagate_draw(item["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 self.children is None and 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 self.children is None and not callback is None:
AttributeError: 'TestContainer' object has no attribute 'children'
Error in sys.excepthook:
Original exception was:
經過一些調查后我發現由於某種原因,我的TestContainer將內存移到其他地址並丟失了所有私有變量。 如你所見,我們進入了stdout:
do_forall() self = 7f97be2c5140
do_forall() self = 7f97c7cc7820
那么問題就是“我做錯了什么?”
似乎是個bug,所以我提交了https://bugzilla.gnome.org/show_bug.cgi?id=722562
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.