【问题标题】:Pyqt5: How to limit the dragging area of a QPushButton in QMainWindow?Pyqt5:如何限制QMainWindow中QPushButton的拖动区域?
【发布时间】:2021-07-07 07:48:10
【问题描述】:

在 QWidget 中拖动 QPushButton 时,直到它消失一旦它通过(越过)MainWindow (QWidget) 的边界

我想限制这个 QPushButton 不越过它的容器的边界,但在 QWidget 内保持可见

from PyQt5.QtWidgets import QApplication, QWidget, QPushButton
from PyQt5.QtCore import Qt

class DragButton(QPushButton):
    def mousePressEvent(self, event):
        self.__mousePressPos = None
        self.__mouseMovePos = None
        if event.button() == Qt.LeftButton:
            self.__mousePressPos = event.globalPos()
            self.__mouseMovePos = event.globalPos()
        super(DragButton, self).mousePressEvent(event)

    def mouseMoveEvent(self, event):
        if event.buttons() == Qt.LeftButton:
            # adjust offset from clicked point to origin of widget
            currPos = self.mapToGlobal(self.pos())
            globalPos = event.globalPos()
            diff = globalPos - self.__mouseMovePos
            newPos = self.mapFromGlobal(currPos + diff)
            self.move(newPos)
            self.__mouseMovePos = globalPos
        super(DragButton, self).mouseMoveEvent(event)

    def mouseReleaseEvent(self, event):
        if self.__mousePressPos is not None:
            moved = event.globalPos() - self.__mousePressPos 
            if moved.manhattanLength() > 3:
                event.ignore()
                return
        super(DragButton, self).mouseReleaseEvent(event)

def clicked():
    print ("click as normal!")

if __name__ == "__main__":
    app = QApplication([])
    w   = QWidget()
    w.resize(800,600)
    button = DragButton("Drag", w)
    button.clicked.connect(clicked)
    w.show()
    app.exec_() 

有没有办法做到这一点?

【问题讨论】:

    标签: pyqt5 qwidget qpushbutton


    【解决方案1】:

    由于要求是确保子级在父级边界内,您需要检查子级rect()(翻译到新位置)是否在该区域内,在移动之前它。

    请注意,要实现“自我”运动,不必不断平移全局位置。

    class DragButton(QPushButton):
        def mousePressEvent(self, event):
            self.__mousePressPos = None
            self.__mouseMovePos = None
            if event.button() == Qt.LeftButton:
                self.__mousePressPos = event.globalPos()
                self.__mouseMovePos = event.pos()
            super(DragButton, self).mousePressEvent(event)
    
        def mouseMoveEvent(self, event):
            if event.buttons() == Qt.LeftButton:
                delta = event.pos() - self.__mouseMovePos
                newPos = self.pos() + delta
                if self.parent():
                    geo = self.rect().translated(newPos)
                    parentRect = self.parent().rect()
                    if geo.x() < 0:
                        geo.moveLeft(0)
                    elif geo.right() > parentRect.right():
                        geo.moveRight(parentRect.right())
                    if geo.y() < 0:
                        geo.moveTop(0)
                    elif geo.bottom() > parentRect.bottom():
                        geo.moveBottom(parentRect.bottom())
                    self.move(geo.topLeft())
                else:
                    self.move(newPos)
            super(DragButton, self).mouseMoveEvent(event)
    

    还要考虑拖动已启用的按钮不是一个好主意,因为它可能会导致不需要的、不直观的和意外的行为。您的实现显示了这一点,因为如果按钮移动超过 3 像素限制,它将保持按下状态。

    【讨论】:

    • 这个类 DragButton(QPushButton): 创建一个新按钮,但是有没有办法直接从我的 .ui 文件继承按钮?并应用您的类的属性(因为我在 Qt Designer 上设置按钮的样式并使用 loadUi() 加载它)。 "dragbtn" 是 Qt Designer 中按钮的名称
    • 你需要对Designer中的“widget Promotion”做一些研究。
    • 非常感谢您的回答
    • 请问您有youtube频道或群组吗,...我想向您学习
    猜你喜欢
    • 2020-03-25
    • 2020-01-13
    • 1970-01-01
    • 2011-03-15
    • 1970-01-01
    • 2017-08-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多