【问题标题】:Custom QSizeGrip to resize a QListWidget自定义 QSizeGrip 以调整 QListWidget 的大小
【发布时间】:2019-02-28 09:46:45
【问题描述】:

我想制作一个 QListWidget,底部有一个调整大小的句柄(类似于您在此类网页上看到的文本字段)。我看到有人问过同样的问题,但没有找到完整的例子。

我有一些代码几乎就在那里,但在调整大小时它会闪烁,所以我猜我在调整大小策略或布局或其他方面缺少一些东西......

这是我的“工作”示例。理论非常简单,您只需在小部件的 mousePressEvent 中测量鼠标移动的距离并相应地调整大小/重新定位。不幸的是,我错过了一些基本的东西,我不知道是什么:

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)

【问题讨论】:

    标签: python pyqt pyqt4 qlistwidget


    【解决方案1】:

    试试看:

    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()                                             # <- +++
    

    【讨论】:

    • 有趣!那么为什么当小部件移动时会导致闪烁呢?这确实有效,但看起来有点难看,它几乎解决了我的问题,但我希望小部件跟随鼠标。但它确实给了我一个看的方向......
    • 好的,解决方案一如既往地简单。请参阅我的最终解决方案的答案!
    【解决方案2】:

    作为其他解决方案的替代方案,您可以使用 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_())
    

    【讨论】:

    • 这太完美了!我从文档中认为 SizeGrips 调整了主窗口的大小,但这按预期工作。
    • 稍微超出了问题的范围,但我还是会问:知道如何将 sizegrip 限制为仅垂直缩放吗?
    • @Spencer,让我测试一个解决方案,我会尽快回复您。同时,如果您喜欢,请考虑为答案投票。顺便说一句,其他答案也很好,值得点赞。
    • @Spencer,在self.setGeometry(200, 500, 200, 500) 之后添加self.setFixedWidth(200)
    • 当然,我对他们投了赞成票!你说的对,mouseMoveEvent 比我想象的要复杂得多,我尝试潜入其中却一无所获。但是我确实设法解决了这个问题,我只是引用了本地空间,当小部件试图自行移动时,这显然会卡住。请参阅我发布的答案!希望这对其他人有所帮助,因为我在网上看到一些人有同样的问题。
    【解决方案3】:

    我认为与其实现自己的QSizeGrip,不如使用QSplitter

    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_())
    

    【讨论】:

    • 感谢 eyllanesc,但在这种情况下,我不想要拆分器。虽然我肯定会不时使用它们;)
    【解决方案4】:

    好吧,事实证明我真的很接近。我在这里为其他希望解决类似问题的人发布答案!

    我真正需要对原始代码进行更改的只是引用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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-09-14
      • 1970-01-01
      • 2013-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多