Roy_Wood
(Roy Wood)
April 5, 2024, 10:28pm
1
I converted the ConstraintLayout code from the gtk4-demo to Python, and it works well, but I get an error (“Finalizing… but it still has children left”) to stdout when I close the app.
The code is:
import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk
class ConstraintLayoutDemoWidget(Gtk.Widget):
def __init__(self):
super().__init__(hexpand=True, vexpand=True)
self.constraint_layout_manager = Gtk.ConstraintLayout()
self.set_layout_manager(self.constraint_layout_manager)
self.button_1 = Gtk.Button(name='button1', label='Button 1')
self.button_1.set_parent(self)
self.button_2 = Gtk.Button(name='button2', label='Button 2')
self.button_2.set_parent(self)
self.button_3 = Gtk.Button(name='button3', label='Button 3')
self.button_3.set_parent(self)
vfl_constraints = [
"H:|-[button1(==button2)]-12-[button2]-|",
"H:|-[button3]-|",
"V:|-[button1]-12-[button3(==button1)]-|",
"V:|-[button2]-12-[button3(==button2)]-|",
]
views = {'button1': self.button_1, 'button2': self.button_2, 'button3': self.button_3}
self.constraint_layout_manager.add_constraints_from_description(vfl_constraints, hspacing=10, vspacing=10, views=views)
def on_activate(app):
application_window = Gtk.ApplicationWindow(application=app)
constraint_widget = ConstraintLayoutDemoWidget()
box = Gtk.Box()
box.append(constraint_widget)
application_window.set_child(box)
application_window.present()
if __name__ == '__main__':
# Create a new application
app = Gtk.Application(application_id='com.example.GtkApplication')
app.connect('activate', on_activate)
# Run the application
app.run(None)
And the error is:
(python:1266308): Gtk-WARNING **: 18:12:28.256: Finalizing __main__+ConstraintLayoutDemoWidget 0x1a139a0, but it still has children left:
- button1 0x1a079c0
- button2 0x1a06670
- button3 0x19c2990
I need to unparent the buttons from my widget when it’s being destroyed, but I’m not sure what method to override or signal to catch. Any suggestions?
ebassi
(Emmanuele Bassi)
April 6, 2024, 10:14am
3
This is a known limitation of the Python bindings: there is no way to override the dispose virtual function of GObject, which makes it hard to subclass GtkWidget. You can try and remove your widgets in the do_unroot() method, but you will need to recreate the widgets inside the do_root() method if you plan on moving your widget class between different parents.
Roy_Wood
(Roy Wood)
April 6, 2024, 1:56pm
4
Thanks for the quick responses!
I added a __del__
method to unparent the buttons, and that silences the warning. That may not be the best way, but…
import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk
# +-----------------------------+
# | +-----------+ +-----------+ |
# | | Child 1 | | Child 2 | |
# | +-----------+ +-----------+ |
# | +-------------------------+ |
# | | Child 3 | |
# | +-------------------------+ |
# +-----------------------------+
class ConstraintLayoutDemoWidget(Gtk.Widget):
def __init__(self):
super().__init__(hexpand=True, vexpand=True)
self.constraint_layout_manager = Gtk.ConstraintLayout()
self.set_layout_manager(self.constraint_layout_manager)
self.button_1 = Gtk.Button(name='button1', label='Button 1')
self.button_1.set_parent(self)
self.button_2 = Gtk.Button(name='button2', label='Button 2')
self.button_2.set_parent(self)
self.button_3 = Gtk.Button(name='button3', label='Button 3')
self.button_3.set_parent(self)
vfl_constraints = [
"H:|-[button1(==button2)]-12-[button2]-|",
"H:|-[button3]-|",
"V:|-[button1]-12-[button3(==button1)]-|",
"V:|-[button2]-12-[button3(==button2)]-|",
]
views = {'button1': self.button_1, 'button2': self.button_2, 'button3': self.button_3}
self.constraint_layout_manager.add_constraints_from_description(vfl_constraints, hspacing=10, vspacing=10, views=views)
def __del__(self):
self.button_1.unparent()
self.button_2.unparent()
self.button_3.unparent()
def on_activate(app):
application_window = Gtk.ApplicationWindow(application=app)
constraint_widget = ConstraintLayoutDemoWidget()
box = Gtk.Box()
box.append(constraint_widget)
application_window.set_child(box)
application_window.present()
if __name__ == '__main__':
# Create a new application
app = Gtk.Application(application_id='com.example.GtkApplication')
app.connect('activate', on_activate)
# Run the application
app.run(None)
ebassi
(Emmanuele Bassi)
April 6, 2024, 2:00pm
5
That’s also a viable solution, yes. It assumes that the Python wrapper will go away before the underlying C object, which is generally the case as the Python wrapper keeps the C object alive and is responsible for dropping the last reference on the object.
system
(system)
Closed
April 20, 2024, 2:01pm
6
This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.