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)
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() # <- +++
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_())
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With