也许,有一个更直接的解决方案,但我刚刚尝试过,发现手动实现所有悬停行为似乎是唯一真正可行的方法。
一般来说,都是检查鼠标坐标是否属于椭圆(你可以尝试其他几何考虑)。
有些东西不起作用:
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,这是实现您所描述的所需行为的唯一可靠方法。