鼠标在圆角QPushButton时如何不触发悬停状态?

Posted

技术标签:

【中文标题】鼠标在圆角QPushButton时如何不触发悬停状态?【英文标题】:How to not trigger the hover state when mouse is at the corner of a round QPushButton? 【发布时间】:2019-08-21 01:54:41 【问题描述】:

我有一个带圆角的 QPushButton:

现在,我想在鼠标移动时更改按钮的样式:

我使用了 QPushButton 的 setStyleSheet:

QPushButton
    width:100px;
    height:80px;
    border-radius:40px;
    border: 1px solid #ffffff;

QPushButton:hover
    background: red;    

但不是四个角:

如第三张图片所示,光标指向按钮的右下角,但也触发了按钮的悬停状态。有没有一种简单的方法可以防止这种行为?

【问题讨论】:

这是正常行为。在我看来,没有简单的方法可以做到这一点。通过使用伪元素和所有可能有一个复杂的 jQuery 方式。但话又说回来,我认为这很正常。 当光标在轮廓之外时,您还想防止单击吗? 【参考方案1】:

也许,有一个更直接的解决方案,但我刚刚尝试过,发现手动实现所有悬停行为似乎是唯一真正可行的方法。

一般来说,都是检查鼠标坐标是否属于椭圆(你可以尝试其他几何考虑)。

有些东西不起作用:

ui->myButton->installEventFilter(this);

//----------------------------------------

bool SomeWidget::eventFilter(QObject *obj, QEvent *event)

    if (event->type() == QEvent::HoverEnter || event->type() == QEvent::HoverMove)
    
        QHoverEvent* hoverEvent = static_cast<QHoverEvent *>(event);
        QWidget* target = qobject_cast<QWidget *>(obj);
        qreal a = target->width() / 2;
        qreal b = target->height() / 2;
        qreal x = hoverEvent->posF().x() - a;
        qreal y = hoverEvent->posF().y() - b;

        double val = (x / a) * (x / a) + (y / b) * (y / b);
        bool isInside = val <= 1;
        if (!isInside)
            return true;
        else
            return QObject::eventFilter(obj, event);
     
        return QObject::eventFilter(obj, event);

使用 SomeWidget,包含安装的按钮和事件过滤器,这看起来很有希望,但效果非常好 =(

作为概念验证的东西:

CustomButton::CustomButton(QWidget *parent)
    : QPushButton(parent)

    setProperty("my_hover", "not_hovered");


void CustomButton::mouseMoveEvent(QMouseEvent *event)

    qreal a = width() / 2;
    qreal b = height() / 2;
    qreal x = event->pos().x() - a;
    qreal y = event->pos().y() - b;

    double val = (x / a) * (x / a) + (y / b) * (y / b);
    bool isInside = val <= 1;
    setProperty("my_hover", isInside ? "hovered" : "not_hovered" );
    style()->unpolish(this);
    style()->polish(this);

子类化 QPushButton 效果更好(上面的代码是一个可读的示例,当然你可以改进它)。实现时,它为按钮类提供了一个自定义属性,可以这样使用:

QPushButton[my_hover="hovered"]

  background: red;    

要使其成为完美的解决方案,您可能还需要关注mouseLeaveEvent,从而消除偶尔出现的故障。此外,如果它与您的 Qt 一起使用,该属性可能会被设为布尔值。

AFAIK,这是实现您所描述的所需行为的唯一可靠方法。

【讨论】:

以上是关于鼠标在圆角QPushButton时如何不触发悬停状态?的主要内容,如果未能解决你的问题,请参考以下文章

子 QMenu 中的 QPushButton,悬停时更改背景

仅当鼠标悬停在元素上至少特定时间时,如何触发 MouseMove 事件?

如何同时对 QPushButton 应用悬停和格式化?

如何通过将鼠标悬停在同一页面上的图像上来触发 CSS 动画按钮

CSS:圆角 + 不透明度 = 图像在 Firefox 19 中消失

如何测试在悬停/鼠标悬停时调用了 Vue 指令?