c++ Qt:从数据更新UI时如何避免信号递归

zbdgwd5y  于 2023-03-09  发布在  其他
关注(0)|答案(1)|浏览(155)

我正在开发一个游戏编辑器。我想做的事情之一是显示游戏对象的信息,并在游戏中发生任何变化时更新它。
伪代码:

struct GameObject
{
  //Some data over here
  void AddDataListener(DataListener);
};

class GameObjectPanel:QWidget, DataListener
{
  void Initialize()
  {
    //Create all UI elements and setup signals for them, this is called once when window first appears
    //signals are setup so they call various versions of OnValueChanged()

  }

  void SetGameObject(GameObject*)
  {
    //Update the UI elements with the values from the game object
  }

  void OnDataChanged(GameObject*)
  {
    //Update all UI elements
  }

  slot OnValueChanged(...)
  {
    //Update the object
  }
};

现在问题来了:每次调用OnValueChanged()时,它都会将更改应用于游戏对象,然后通知面板它发生了更改,面板随后更新所有UI元素,面板随后调用OnValueChanged(),面板随后更改对象,等等。
幸运的是,这个循环不会永久发生,因为值很快就稳定下来了(主要原因是转换,我有一个显示全局转换的小部件,但我存储了本地转换,所以每次全局转换小部件发生变化时,它都需要重新计算),但我认为这个循环根本不应该发生。
是否有一种方法可以订阅插槽,但只有当用户更改数据时才激活它们,或者是否有一种方法可以一次启用/禁用所有插槽?逐个检查每个连接并禁用它们,然后重新启用它们对我来说似乎不太可行,因为它们非常多,而且很容易错过。
我目前的解决方案包括添加一个“blockGameObjectSignals”布尔值,我在每次收到值更改信号时设置该布尔值,并且每次从游戏对象更新时都设置该布尔值,但这是大量重复性很强且容易出错的额外代码,因此如果知道是否有“正确”的方法来解决此问题,将非常有益。
提前感谢您的任何帮助!

vc6uscn9

vc6uscn91#

在任一方法中:OnDataChangedOnValueChanged您可以在所考虑的对象上使用QSignalBlocker,以防止它们发射***changed信号。
这是一个常见的做法,UI元素之间有循环依赖关系,例如DEC-〉HEX和HEX-〉DEC转换器与2 QLineEdit,其中一个改变,因为你在另一个键入。

相关问题