문제

When I do multiple updates on a widget in wxPython (like loading content of tables, trees, un-hiding widgets etc.) I often use Freeze to disable the widget re-drawing and when I am done, I call Thaw so the new content appears all at once. Is there a similar way in Qt?

Related question: Python/Tkinter: Turn on/off screen updates like wxPython Freeze/Thaw?

도움이 되었습니까?

해결책 2

In Qt it shouldn't be necessary to do it, since the update events are compressed and won't be delivered until the control returns to the event loop. For example, the following will only result in one repaint of the label:

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

If you are certain that your updates are interspersed with returns to the event loop, then you can implement the freeze/thaw as follows by filtering the update events. The below is in C++, feel free to translate it to 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); }

다른 팁

I know that this is an old post, but I found this at Turn off PyQt Event Loop While Editing Table

There is a way to do this:

blockSignals(bool) is intended for suppressing QObjects and their subclasses from emitting signals, thus preventing any other objects from receiving them in slots. But this is a QObject method. If you are specifically trying to prevent one object from emitting signals in response to changes that you are making, which might trigger calculations or some other expensive processing in a slot, then this is what you want.

But if your situation is that making repeated changes is causing expensive paint operations over and over (or other expensive events being generated on the widget), then you have the ability to disable updates with updatesEnabled(bool). A benefit of this method is that it recursively disables the children of the target widget, preventing them from being updated as well. So nothing in the hierarchy will receive updates until you enable again.

mainWidget.setUpdatesEnabled(False)
# do a bunch of operations that would trigger expensive events
# like repaints
mainWidget.setUpdatesEnabled(True)
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top