【问题标题】:PyQt QPushButton leaveEvent while press QPushButtonPyQt QPushButton leaveEvent 同时按下 QPushButton
【发布时间】:2021-01-08 09:10:38
【问题描述】:

我想要一个按钮。我正在尝试制作一个状态机,所以它将用于 QState 类。

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

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

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

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

我测试了几件事,现在我明白了一些。

  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

【问题讨论】:

  • 为什么不能使用默认的clicked() 信号并避免整个*事件覆盖?如果要为悬停状态设置样式表,请在按钮的全局 css 中使用 :hover 选择器。
  • @musicamante 谢谢,clicked() 有效。我对 clicked() 有误解。我认为 clicked() 在单击按钮时会立即发出信号。之前没有学过 PyQt 和 python,所以我搜索了有助于实现目的的函数。
  • @musicamante 感谢 ':hover',我试过了,但没用。我不知道为什么。 'enterEvent' 和 'leaveEvent' 效果很好,所以我会使用它。

标签: python pyqt qpushbutton


【解决方案1】:

子类化和方法覆盖只有在类不能提供你需要的东西时才应该进行,而这不是你的情况。

clicked 信号完全符合您的描述:当用户按下鼠标左键并在光标位于按钮内部时(以及当click()animateClick() 以编程方式调用,但这不是重点)。

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

    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:pressed 设置两个 的样式表规范
  • 由于按钮的外观应该始终反映其状态(最重要的是,无论何时按下),您至少应该为:pressed 状态添加类选择器;此外,使用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() 仅在您需要在未按下鼠标按钮时跟踪鼠标移动时有用,并且被 mouseMoveEvent()(您没有实现)拦截,通常总是在鼠标移动 之后 已按下鼠标按钮;
  • 只有在没有按下鼠标按钮时才会收到进入和离开事件:一旦小部件(任何小部件)接收并接受mousePressEvent(),该小部件将成为“鼠标抓取器” (请参阅mouseGrabber()grabMouse())并且所有鼠标移动将仅由该小部件接收:no 任何其他小部件将接收进入/离开/悬停事件,直到释放鼠标按钮;
  • 虽然我可以理解您的陈述(“我搜索有助于实现我的目的的函数”),但您必须考虑到 Qt 是一个在 25 年的跨度内开发的巨大框架:它的所有类都已经提供了大部分常用的接口和特性,所以与其为每个单独的案例寻找你需要的东西,不如去看看你正在使用的类的文档,并研究它;考虑到您还应该始终对您正在使用的类的所有继承类执行相同操作:在您的情况下,不要只查找 QPushButton,而是阅读有关 QAbstractButton 和 @987654329 的文档@也是。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-01
    • 2014-01-07
    • 2016-11-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多