当我在wxPython中对窗口小部件进行多次更新时(比如加载表,树,隐藏窗口小部件的内容等)我经常使用Freeze来禁用窗口小部件重绘,当我完成时,我致电Thaw,以便新内容同时显示。 Qt中有类似的方式吗?
相关问题:Python/Tkinter: Turn on/off screen updates like wxPython Freeze/Thaw?
答案 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)