相当于WxPython在PyQt / PySide中的冻结和解冻

时间:2014-03-18 17:09:36

标签: python qt pyqt wxpython pyside

当我在wxPython中对窗口小部件进行多次更新时(比如加载表,树,隐藏窗口小部件的内容等)我经常使用Freeze来禁用窗口小部件重绘,当我完成时,我致电Thaw,以便新内容同时显示。 Qt中有类似的方式吗?

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

2 个答案:

答案 0 :(得分:2)

在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); }

答案 1 :(得分: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)