PyQt QPushButton 在按下 QPushButton 时离开事件

PyQt QPushButton leaveEvent while press QPushButton

我想要一个按钮。我正在尝试制作一个状态机,因此它将在 QState class.

中使用

如果鼠标光标悬停,按钮会改变它的颜色。

如果在按钮上松开鼠标左键,它应该可以工作。

如果鼠标左键在按钮上按下但在按钮外部松开,(按下时将光标拖到外部)按钮应该不起作用。 (因此用户可以通过拖出来取消他们的误点击。)

这是我的代码,但效果不佳。当我将光标拖到外面并释放鼠标按钮时,该按钮有效。

我测试了几个东西,现在我明白了一些。

  1. 按下鼠标按钮时,QPushButton.enterEvent 和 QPushButton.leaveEvent 不起作用。

  2. 当按下按钮时光标离开 QPushButton,似乎 QPushButton.released 发出信号。

如何制作这个按钮?

class MyButton(QtWidgets.QPushButton):
    selected = QtCore.pyqtSignal(bool)

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setMouseTracking(True)
        self.is_hover = False

    def enterEvent(self, event):
        self.setStyleSheet\
            ("color: black; border-style: solid;\
                border-width: 2px; border-color: white;\
                    background-color: rgba(250,0,0,1);")            
        self.is_hover = True
        print('is_hover = True')

    def leaveEvent(self, event):
        self.setStyleSheet\
            ("color: white; border-style: solid;\
                border-width: 2px; border-color: white;\
                    background-color: rgba(250,50,150,0.5);")
        self.is_hover = False
        print('is_hover = False')

    def mouseReleaseEvent(self, event):
        if event.button() == QtCore.Qt.LeftButton:
            if self.is_hover:
                self.selected.emit(True)
            else:
                return
        else:            
            return

Subclassing 和方法覆盖仅应在 class 未提供您需要的内容时进行,而您的情况并非如此。

clicked signal does exactly what you describe: the signal is emitted when the user presses the left mouse button and releases it while the cursor is inside the button (and when click() or animateClick() 以编程方式调用,但这不是重点)。

如果您还想在悬停按钮时更改外观,则必须使用 :hover 伪状态。请注意,要正确使用样式表选择器,您不能像以前那样使用简单的样式表语法,但 class 必须完全按照标准 CSS 指定。

    self.button = QPushButton()
    self.button.setStyleSheet('''
        QPushButton {
            color: white;
            border: 2px solid white;
            background-color: rgba(250, 50, 150, 128);
        }

        QPushButton:hover {
            background-color: rgba(250, 0, 0, 255);
        }
    ''')
    self.button.clicked.connect(self.someFunction)

一些注意事项:

  • rgb()rgba() 语法接受 0 到 255 之间的整数或百分比,因此您使用的 alpha 值(0.5 和 1)不会按预期工作,因为它们将被认为实际上是透明的(分别为 0 和 1),因为非百分比值始终在 0-255 范围内;
  • 伪状态可以链接,因此您还可以为:hover和[=18设置样式表规范=]
  • 由于按钮的外观应始终反映其状态(最重要的是,无论何时按下),您至少应为 :pressed 状态添加 class 选择器;此外,使用 insetoutset 边框样式(而不是 solid)也被认为是好的做法;请注意,它只适用于较暗的颜色,因此如果您想要“发白”的边框,请使用以下内容:
    self.button.setStyleSheet('''
        QPushButton {
            color: white;
            border: 2px outset lightGray;
            background-color: rgba(250, 50, 150, 128);
        }
        QPushButton:pressed {
            border-style: inset;
        }
        QPushButton:hover {
            background-color: rgba(250, 0, 0, 255);
        }
        QPushButton:hover:pressed {
            /* since no background was set for pressed, hover state takes
            precedence, so we need to specify the "default" color again here */
            background-color: rgba(250, 50, 150, 128);
        }
    ''')
  • setMouseTracking() is useful only when you need to track mouse movements when no mouse button is pressed, and are intercepted by mouseMoveEvent()(你没有实现)通常总是调用鼠标移动按下鼠标按钮后;
  • enter 和 leave 事件只有在没有按下鼠标按钮时才会被接收:只要一个 widget(any widget)接收并接受一个 mousePressEvent(),那个 widget将成为“鼠标抓取器”(参见 mouseGrabber() and grabMouse())并且所有鼠标移动将仅由该小部件接收:no enter/leave/hover 事件将由任何其他小部件接收小部件,直到释放鼠标按钮;
  • 虽然我能理解您的说法(“我搜索有助于实现我的目的的函数”),但您必须考虑到 Qt 是一个 庞大 框架,它是在25 年的跨度:它的所有 classes 已经提供了大部分常用的界面和功能,因此与其查找每个案例所需的内容,不如查看有关 [=75] 的文档=] 你在用,研究一下;考虑到您还应该 总是 对您正在使用的 class 的所有继承 class 执行相同的操作:在您的情况下,不要只看对于 QPushButton,但也请阅读有关 QAbstractButton 和 QWidget 的文档。