Может быть, , существует более простое решение этого вопроса, но я только что попробовал, и оказалось, что реализация всего поведения при наведении вручную кажется единственным действительно действующим способом.
Как правило, все дело в проверке того, что координаты мыши принадлежат эллипсу (вы можете попробовать другие геометрические соображения).
Что-то, что не работает:
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, это единственный верный способ реализовать желаемое поведение, которое вы описали.