QWidget resize signal?
Asked Answered
S

6

32

I want to take an action when a widget was resized.

Is there a way to catch that without installing an event filter on that widget (and, obviously, without subclassing it)? AFAIK, QWidget does not have a resized signal.

Scorpio answered 21/1, 2012 at 19:1 Comment(1)
No, you cannot. The bset way is: Create your own QWidget that emits Resized in resizeEvent(), then promote your widgets to it :)Poulenc
V
18

If you have any other QObject that can have strict relation to that QWidget you may use QObject::installEventFilter(QObject * filter) and overload bool eventFilter(QObject *, QEvent *). See more at Qt docs

Vassalage answered 21/1, 2012 at 22:4 Comment(0)
D
29

You can derive from widget class and reimplement resizeEvent event

Diver answered 21/1, 2012 at 19:19 Comment(4)
note that warwaruk wrote "and, obviously, without subclassing it"Vassalage
@KamilKlimek, ... after I posted the answer :)Diver
I will not remove the answer, I think it could be useful for someone, who could search this questionDiver
I didn't tell anything about removing your answerVassalage
V
18

If you have any other QObject that can have strict relation to that QWidget you may use QObject::installEventFilter(QObject * filter) and overload bool eventFilter(QObject *, QEvent *). See more at Qt docs

Vassalage answered 21/1, 2012 at 22:4 Comment(0)
V
10

In case you are using Python with PyQt4, you can set widget.resizeEvent to your function without sublclassing it:

#!/usr/bin/env python
import sys
from PyQt4 import QtCore, QtGui

def onResize(event):
    print event

if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    widget = QtGui.QPushButton('Test')
    widget.resizeEvent = onResize
    widget.resize(640, 480)
    widget.show()
    sys.exit(app.exec_())
Verduzco answered 28/1, 2012 at 10:38 Comment(2)
This prevents the base class implementation of resizeEvent from running. It might be doing something important. And with the monkey-patch solution, you'd have to keep a reference to the original method as a separate variable. Messy.Claybourne
@Claybourne The docs say that by the time resizeEvent is called the widget already has its new geometry so if you don't have anything else to do on the main widget you can just override the function. I use this technique to resize the contents of a QScrollArea.Hirsutism
B
6

Sorry, it looks like a hack, but I use this:

    some_widget.resizeEvent = (lambda old_method: (lambda event: (self._on_resized(event), old_method(event))[-1]))(some_widget.resizeEvent)
Beauvoir answered 15/1, 2016 at 0:29 Comment(2)
So much for Python being designed for legibility. However, +1 for retaining the super implementation.Walkabout
Thank you, Spencer! Every answer here forgets to re-invoke a previous callback after doing his stuff.Beauvoir
W
3

This is a couple of years too late, but I was working on a transparent overlay widget that would completely cover the parent. You can not do what you want without subclassing, but you can restrict the subclassing to an instance as @reclosedev suggests, meaning that you don't have to actually create a subclass.

I wrote the following snippet (which works in PyQt4) for following the size of any widget that the widget is added to:

class TransparentOverlay(QtGui.QWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setAttribute(QtCore.Qt.WA_NoSystemBackground)
        self._updateParent(self.parentWidget())

    def setParent(self, parent, *args):
        prevParent = self.parentWidget()
        super().setParent(parent, *args)
        self._updateParent(parent, prevParent)

    def unsetParent(self, parent=None):
        if parent is None:
            parent = self.parentWidget()
        if parent is not None and hasattr(parent.resizeEvent, '_original'):
            parent.resizeEvent = parent.resizeEvent._original

    def _updateParent(self, parent, prevParent=None):
        if parent is not prevParent:
            self.unsetParent(prevParent)
            if parent is not None:
                original = parent.resizeEvent
                def resizeEventWrapper(event):
                    original(event)
                    self.resize(event.size())
                resizeEventWrapper._original = original
                parent.resizeEvent = resizeEventWrapper
                self.resize(parent.size())

This code uses a couple of neat tricks that are possible with Python:

  • The original method is stashed in the _original attribute of the new one. This is possible because functions are objects.
  • The new method truly subclasses any QWidget instance, meaning that you do not have to create an actual subclass. Each parent instance will effectively become an instance of a subclass by virtue of the tacked on method.

If you need a one-time thing, all of the code for removing the subclassed resizeEvent method and replacing it with the original can be trashed. In that case, the solution is basically a fancier version of @reclosedev's solution, but with @Chris's comments about preserving the original addressed.

The only caveat with this code is that it does not support GL widgets correctly, so for example the overlay can not always be added to the viewport of a QGraphicsView. It can, however, be added to the QGraphicsView itself.

Walkabout answered 14/4, 2016 at 18:3 Comment(0)
S
3

You can override the resizeEvent by

def resizeEvent(self, newSize):
    #do code here
Sister answered 12/12, 2016 at 21:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.