微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何使用 Python+PyGObject 的 GObject.bind_property 函数进行 2 路数据绑定?

如何解决如何使用 Python+PyGObject 的 GObject.bind_property 函数进行 2 路数据绑定?

这个问题的背景(以及我的总体目标)是以一种很好的方式构建 Python GTK 应用程序。我正在尝试使用 GTK's bidirectional data bindings 将小部件属性绑定到模型属性

我的期望是双向绑定应该保持两个属性同步。我发现即使我使用了 GObject.BindingFlags.BIDIRECTIONAL 标志,变化也只会在一个方向上传播。我创建了以下最小示例和失败的测试用例 test_widget_syncs_to_model 来说明问题。请注意,在更实际的示例中,模型对象可以是 Gtk.Application 的实例,小部件对象可以是 Gtk.Entry 的实例。

import gi

gi.require_version('Gtk','3.0')
from gi.repository import Gtk,GObject
import unittest


class Obj(GObject.Object):
    """A very simple GObject with a `txt` property."""

    name = "default"
    txt = GObject.Property(type=str,default="default")

    def __init__(self,name,*args,**kwargs):
        super().__init__(*args,**kwargs)
        self.name = name
        self.connect("notify",self.log)

    def log(self,source,parameter_name):
        print(
            f"The '{self.name}' object received a notify event,"
            f"its txt Now is '{self.txt}'."
        )


class TestBindings(unittest.TestCase):
    def setUp(self):
        """Sets up a bidirectional binding between a model and a widget"""
        print(f"\n\n{self.id()}")
        self.model = Obj("model")
        self.widget = Obj("widget")
        self.model.bind_property(
            "txt",self.widget,"txt",flags=GObject.BindingFlags.BIDIRECTIONAL
        )

    @unittest.skip("suceeds")
    def test_properties_are_found(self):
        """Verifies that the `txt` properties are correctly set up."""
        for obj in [self.model,self.widget]:
            self.assertIsNotNone(obj.find_property("txt"))

    @unittest.skip("suceeds")
    def test_model_syncs_to_widget(self,data="hello"):
        """Verifies that model changes propagate to the widget"""
        self.model.txt = data
        self.assertEqual(self.widget.txt,data)

    def test_widget_syncs_to_model(self,data="world"):
        """Verifies that widget changes propagate back into the model"""
        self.widget.txt = data
        self.assertEqual(self.widget.txt,data)  # SUCCEEDS
        self.assertEqual(self.model.txt,data)  # FAILS


if __name__ == "__main__":
    unittest.main()

以上程序输出

ssF
======================================================================
FAIL: test_widget_syncs_to_model (__main__.TestBindings)
Verifies that widget changes propagate back into the model
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/jh/.config/JetBrains/PyCharmCE2021.1/scratches/scratch_14.py",line 52,in test_widget_syncs_to_model
    self.assertEqual(self.model.txt,data)  # FAILS
AssertionError: 'default' != 'world'
- default
+ world


----------------------------------------------------------------------
Ran 3 tests in 0.001s

Failed (failures=1,skipped=2)


__main__.TestBindings.test_widget_syncs_to_model
The 'widget' object received a notify event,its txt Now is 'world'.

Process finished with exit code 1

我的具体问题是,如何让双向数据绑定工作?...如果有人可以修复我的示例或提供另一个工作示例,我会很高兴。

从更广泛的意义上说,双向绑定是否是在结构良好的 Python GTK 应用程序中同步 UI 状态和模型状态的方法?这样做的预期和得到充分支持方法是什么?谢谢!

解决方法

我在 gnome discourse thread about bidirectional property bindings in python 得到了答复。

为了更清楚,下面的代码不起作用,因为标志没有正确传递:

# broken,flags are passed incorrectly as keywords argument:
self.model.bind_property("txt",self.widget,"txt",flags=GObject.BindingFlags.BIDIRECTIONAL)

相反,必须按如下方式传递标志:

# functioning,flags are passed correctly as a positional argument:
self.model.bind_property("txt",GObject.BindingFlags.BIDIRECTIONAL)

更多示例代码:例如,在 test_bidirectional_binding test case 中的 pygobject 源代码中演示了正确使用双向绑定。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?