Reputation: 41
I'm trying to implement custom Gtk.Container with PyGObject. But i got problems and even dont know is this bug, or my implementation is wrong. This is my test code snippet:
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()
All works good until you close window. After closing window i got this:
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:
After some investigation i have found that for some reason my TestContainer moved in memory to other address and lost all my private variables. As you can see, we got in stdout:
do_forall() self = 7f97be2c5140
do_forall() self = 7f97c7cc7820
So the question will be "what i'm doing wrong?"
Upvotes: 4
Views: 698
Reputation: 743
Seems to be a bug, so I've filed https://bugzilla.gnome.org/show_bug.cgi?id=722562
Upvotes: 4