自定义 QSizeGrip 以调整 QListWidget 的大小
Custom QSizeGrip to resize a QListWidget
我想制作一个底部带有调整大小手柄的 QListWidget(类似于您在此类网页上看到的文本字段)。我看到有几个人在那里问同样的问题,但没有找到完整的例子。
我有一些代码几乎就在那里,但它在调整大小时闪烁,所以我猜我缺少关于调整大小策略或布局或其他东西的东西...
这是我的 "working" 示例。理论非常简单,您只需在小部件的 mousePressEvent 中测量鼠标移动的距离,并相应地 resize/reposition。不幸的是,我缺少一些基本的东西,我不知道是什么:
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)
试一试:
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() # <- +++
我认为你应该使用 QSplitter
:
而不是你自己的 QSizeGrip
from PyQt4 import QtCore, QtGui
import sys
class Dialog(QtGui.QDialog):
def __init__(self):
super(Dialog, self).__init__()
layout = QtGui.QVBoxLayout(self)
splitter = QtGui.QSplitter(QtCore.Qt.Vertical)
layout.addWidget(splitter)
list_widget = QtGui.QListWidget()
splitter.addWidget(list_widget)
splitter.addWidget(QtGui.QLabel("Test"))
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
w = Dialog()
w.show()
sys.exit(app.exec_())
对于其他解决方案,您可以使用 QSizeGrip
开箱即用的方式:
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_())
好吧,事实证明我真的很接近。我 post 在这里为任何想解决类似问题的人提供答案!
我真正需要对原始代码进行更改的是引用 globalPos()
而不是本地 pos()
。感谢您的帮助,特别是 S. Nick 发现移动事件导致了问题。
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)
self.setCursor(QtCore.Q.SizeVerCursor)
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.globalPos()
def mouseMoveEvent(self, event):
super(Grip, self).mouseMoveEvent(event)
if self.resizing:
delta = event.globalPos() - 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)
我想制作一个底部带有调整大小手柄的 QListWidget(类似于您在此类网页上看到的文本字段)。我看到有几个人在那里问同样的问题,但没有找到完整的例子。
我有一些代码几乎就在那里,但它在调整大小时闪烁,所以我猜我缺少关于调整大小策略或布局或其他东西的东西...
这是我的 "working" 示例。理论非常简单,您只需在小部件的 mousePressEvent 中测量鼠标移动的距离,并相应地 resize/reposition。不幸的是,我缺少一些基本的东西,我不知道是什么:
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)
试一试:
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() # <- +++
我认为你应该使用 QSplitter
:
QSizeGrip
from PyQt4 import QtCore, QtGui
import sys
class Dialog(QtGui.QDialog):
def __init__(self):
super(Dialog, self).__init__()
layout = QtGui.QVBoxLayout(self)
splitter = QtGui.QSplitter(QtCore.Qt.Vertical)
layout.addWidget(splitter)
list_widget = QtGui.QListWidget()
splitter.addWidget(list_widget)
splitter.addWidget(QtGui.QLabel("Test"))
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
w = Dialog()
w.show()
sys.exit(app.exec_())
对于其他解决方案,您可以使用 QSizeGrip
开箱即用的方式:
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_())
好吧,事实证明我真的很接近。我 post 在这里为任何想解决类似问题的人提供答案!
我真正需要对原始代码进行更改的是引用 globalPos()
而不是本地 pos()
。感谢您的帮助,特别是 S. Nick 发现移动事件导致了问题。
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)
self.setCursor(QtCore.Q.SizeVerCursor)
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.globalPos()
def mouseMoveEvent(self, event):
super(Grip, self).mouseMoveEvent(event)
if self.resizing:
delta = event.globalPos() - 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)