【问题标题】:Equivalent to wxPython's Freeze and Thaw in PyQt / PySide相当于 wxPython 在 PyQt/PySide 中的 Freeze and Thaw
【发布时间】:2014-04-24 13:00:56
【问题描述】:

当我在 wxPython 中对小部件进行多次更新时(例如加载表格、树、取消隐藏小部件等的内容),我经常使用 Freeze 来禁用小部件重新绘制,当我完成后,我调用Thaw 所以新内容会同时出现。 Qt中是否有类似的方法?

相关问题:Python/Tkinter: Turn on/off screen updates like wxPython Freeze/Thaw?

【问题讨论】:

  • 也许我读错了,你的相关问题怎么不是骗人的?
  • @wnnmaw 我要Qt,相关问题要Tkinter
  • 好的,谢谢,我知道我错过了什么

标签: python qt pyqt wxpython pyside


【解决方案1】:

在 Qt 中没有必要这样做,因为更新事件被压缩并且在控制返回到事件循环之前不会被传递。例如,以下内容只会导致标签重绘一次:

void test(QLabel * label) {
  label->setText("foo");
  // update is called internally by setText, but the extra call is harmless here
  label->update(); 
  label->setText("bar");
  label->setText("baz");
}

如果你确定你的更新穿插返回到事件循环,那么你可以通过过滤更新事件来实现冻​​结/解冻,如下所示。以下是 C++,请随意翻译成 Python :)

class UpdateFilter : public QObject {
  Q_OBJECT
  QSet<QObject> m_deferredUpdates;
  Q_SLOT void isDestroyed(QObject * obj) {
    m_deferredUpdates.remove(obj);
  }
  Q_OBJECT bool eventFilter(QObject * obj, QEvent * ev) {
    if (ev->type() == QEvent::UpdateRequest) {
      if (! m_deferredUpdates.contains(obj) {
        m_deferredUpdates.insert(obj);
        connect(obj, SIGNAL(destroyed(QObject*)), SLOT(isDestroyed(QObject*)));
      }
      return true;
    }
    return false;
  }
public:
  void thaw(QWidget * w) {
    if (m_deferredUpdates.contains(w)) {
      w->update();
      m_deferredUpdates.remove(w);
    }
};

// This instance is only created on the first call to freeze.
Q_GLOBAL_STATIC(UpdateFilter, updateFilter)

void freeze(QWidget * w) { w->installEventFilter(&updateFilter()); }
void thaw(QWidget * w) { updateFilter().thaw(w); }

【讨论】:

  • 很抱歉很久没有研究这个问题。我有一个示例,您的答案的第一部分似乎不适用。您对“更新事件被压缩”有任何参考吗?我的情况是我尝试调整窗口大小(由于取消隐藏某些元素),然后移动窗口使其仍位于屏幕中心。但是我可以看到它弹了一会儿,所以事件似乎没有被压缩。
  • @Fenikso 更新事件被压缩,调整大小事件也是如此,但这可能不足以防止在某些情况下闪烁 - 尤其是在调整大小期间,当事件循环经常被 Windows 本身饿死时。
  • 哦,你说,事件被压缩了,但是操作系统窗口管理器在调整大小和移动时很慢?
【解决方案2】:

我知道这是一个旧帖子,但我在 Turn off PyQt Event Loop While Editing Table 找到了这个

有办法做到这一点:

blockSignals(bool) 旨在抑制QObjects 及其子类发出信号,从而防止任何其他对象在槽中接收它们。但这是一个QObject 方法。如果您特别试图阻止一个对象发出信号以响应您所做的更改,这可能会触发计算或插槽中的其他一些昂贵的处理,那么这就是您想要的。

但是,如果您的情况是重复更改会导致反复进行昂贵的绘制操作(或在小部件上生成其他昂贵的事件),那么您可以使用updatesEnabled(bool) 禁用更新。这种方法的一个好处是它递归地禁用目标小部件的子部件,从而阻止它们被更新。因此,在您再次启用之前,层次结构中的任何内容都不会收到更新。

mainWidget.setUpdatesEnabled(False)
# do a bunch of operations that would trigger expensive events
# like repaints
mainWidget.setUpdatesEnabled(True)

【讨论】:

  • 看起来很有趣。我将在我的问题上对此进行测试。
  • 它对我遇到的原始问题没有帮助,但是在其他情况下,这可能是一个不错的选择。谢谢+1。
猜你喜欢
  • 2019-06-04
  • 2014-02-15
  • 2012-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多