I am searching for the best way to automatically write a GObject variable to a widget after formatting it. For example to limit the decimal places of a real variable displayed in the widget.
I think this normally would be done with the functions bind_property_with_closures() or bind_property_full(), but only bind_property() is available.
Now I found the workaround, to first write the real variable with bind_property() to a hidden widget. And then bind it from the hidden widget to the visible widget while modifying it with my python function float_with_2_digits().
#!/usr/bin/python3
import sys
import gi
gi.require_version('Gtk', '4.0')
gi.require_version('Adw', '1')
from gi.repository import Adw, Gtk, Gio, Gdk, GLib, GObject
xml = """\
<interface>
<template class="example2" parent="GtkBox">
<property name="spacing">12</property>
<property name="margin-top">12</property>
<property name="margin-end">12</property>
<property name="margin-bottom">12</property>
<property name="margin-start">12</property>
<child>
<object class="GtkLabel" id='my_hidden_label'>
<property name="visible">FALSE</property>
</object>
</child>
<child>
<object class="GtkLabel">
<binding name="label">
<closure type='gchararray' function='float_with_2_digits'>
<lookup name="label">my_hidden_label</lookup>
</closure>
</binding>
</object>
</child>
</template>
</interface>
"""
class Article(GObject.Object):
price = GObject.Property(type=float)
def __init__(self, price):
super().__init__()
self.price = price
@Gtk.Template(string=xml)
class MyBox(Gtk.Box):
__gtype_name__ = "example2"
my_label = Gtk.Template.Child("my_hidden_label")
@Gtk.Template.Callback()
def float_with_2_digits(self, my_box, real1):
real3=""
if real1:
real2=float(real1.replace(',','.'))
real3=f'{real2:.2f}'
print("real1=<%s> => real3=<%s>" % (real1,real3))
return real3
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
article = Article(0)
# unknown: article.bind_property_with_closures
# not implemented: article.bind_property_full
article.bind_property("price",
self.my_label, "label",
GObject.BindingFlags.SYNC_CREATE)
article.price=1.6666
class MainWindow(Gtk.ApplicationWindow):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
my_box = MyBox()
self.set_child(my_box)
class MyApp(Adw.Application):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.connect('activate', self.on_activate)
def on_activate(self, app):
self.win = MainWindow(application=app)
self.win.present()
app = MyApp(application_id="de.bschu.expression2")
app.run(sys.argv)
The workaround is done with a closure that is defined in a UI template. The workaround is working. But I wonder if there is a better way. How do you solve this ?
If there is no better workaround, I hope at least that my workaround is useful for other people.