Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom QSizeGrip to resize a QListWidget

I want to make a QListWidget with a resize handle at the bottom (similar to text fields you see on webpages like this one). I've seen a few people asking the same question out there but did not find a complete example.

I have some code which is nearly there, but it flickers during resize so I'm guessing there is something I am missing about resize policies or layouts or something...

Here's my "working" example. The theory is pretty simple, you just measure the distance of the mouse move in the widget's mousePressEvent and resize/reposition accordingly. Unfortunately I'm missing something basic and I don't know what:

from PyQt4 import QtGui
import sys

class Grip(QtGui.QLabel):
    def __init__(self, parent, move_widget):
        super(Grip, self).__init__(parent)
        self.move_widget = move_widget
        self.setText("+")
        self.min_height = 50

        self.mouse_start = None
        self.height_start = self.move_widget.height()
        self.resizing = False
        self.setMouseTracking(True)


    def showEvent(self, event):
        super(Grip, self).showEvent(event)
        self.reposition()

    def mousePressEvent(self, event):
        super(Grip, self).mousePressEvent(event)
        self.resizing = True
        self.height_start = self.move_widget.height()
        self.mouse_start = event.pos()

    def mouseMoveEvent(self, event):
        super(Grip, self).mouseMoveEvent(event)
        if self.resizing:
            delta = event.pos() - self.mouse_start
            height = self.height_start + delta.y()
            if height > self.min_height:
                self.move_widget.setFixedHeight(height)
            else:
                self.move_widget.setFixedHeight(self.min_height)

            self.reposition()

    def mouseReleaseEvent(self, event):
        super(Grip, self).mouseReleaseEvent(event)
        self.resizing = False

    def reposition(self):
        rect = self.move_widget.geometry()
        self.move(rect.right(), rect.bottom())


class Dialog(QtGui.QDialog):
    def __init__(self):
        super(Dialog, self).__init__()
        layout = QtGui.QVBoxLayout()
        self.setLayout(layout)
        list_widget = QtGui.QListWidget()
        layout.addWidget(list_widget)
        gripper = Grip(self, list_widget)

        layout.addWidget(QtGui.QLabel("Test"))

        self.setGeometry(200, 500, 200, 500)
like image 337
Spencer Avatar asked Dec 24 '22 04:12

Spencer


2 Answers

Try it:

def mouseMoveEvent(self, event):
    super(Grip, self).mouseMoveEvent(event)
    if self.resizing:
        delta = event.pos() - self.mouse_start
        height = self.height_start + delta.y()
        if height > self.min_height:
            self.move_widget.setFixedHeight(height)
        else:
            self.move_widget.setFixedHeight(self.min_height)

        #self.reposition()                                       # <-  ---

def mouseReleaseEvent(self, event):
    super(Grip, self).mouseReleaseEvent(event)
    self.resizing = False

    self.reposition()                                             # <- +++
like image 160
S. Nick Avatar answered Dec 25 '22 16:12

S. Nick


Alternatively to the other solutions, you could use QSizeGrip the way it comes out of the box:

from PyQt4 import QtCore, QtGui
import sys

class Dialog(QtGui.QDialog):
    def __init__(self):
        super(Dialog, self).__init__()
        layoutMain = QtGui.QVBoxLayout(self)
        listWidget = QtGui.QListWidget(self)
        gripper = QtGui.QSizeGrip(listWidget)
        l = QtGui.QHBoxLayout(listWidget)

        l.setContentsMargins(0, 0, 0, 0)
        l.addWidget(gripper, 0, QtCore.Qt.AlignRight | QtCore.Qt.AlignBottom)

        layoutMain.addWidget(listWidget)
        layoutMain.addWidget(QtGui.QLabel("Test", self))

        self.setGeometry(200, 500, 200, 500)

if __name__ == '__main__':
    import sys
    app = QtGui.QApplication(sys.argv)
    w = Dialog()
    w.show()
    sys.exit(app.exec_())
like image 38
scopchanov Avatar answered Dec 25 '22 17:12

scopchanov