Qt自定义圆形环状菜单
先看实现的效果
可设置圆环背景色、Hover扇形的颜色、箭头颜色、动画速度,核心代码如下
1、初始化设置背景透明,默认打开旋转和缩放动画
q->setFixedSize(180, 180);
diameter = 150;
smallDiameter = calcInCircleRadius() * 2;
q->setMouseTracking(true);
q->setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog);
q->setAttribute(Qt::WA_TranslucentBackground);
q->setRotateAnimationEnabled(true);
q->setZoomAnimationEnabled(true);
2、重写鼠标事件,实现拖动,点击等功能
void CircleMenu::mousePressEvent(QMouseEvent *event)
{
if(event->button() != Qt::LeftButton){
return ;
}
Q_D(CircleMenu);
d->pressed = true;
d->startPos = event->pos();
QPointF center(width() / 2.0, height() / 2.0);
double distance = std::sqrt(std::pow(center.x() - d->startPos.x(), 2) + std::pow(center.y() - d->startPos.y(), 2));
d->pressPosIsInSmallCircle = distance < d->calcInCircleRadius();
}
void CircleMenu::mouseMoveEvent(QMouseEvent *event)
{
Q_D(CircleMenu);
if(d->canMove && d->pressed && d->pressPosIsInSmallCircle){
this->move(this->pos() + event->pos() - d->startPos);
d->moved = true;
}
if(d->isMenuVisible){
auto old = d->currentArea;
d->currentArea = d->calcArea(event->pos());
update();
if(!d->pressed){
d->updateTip(event->globalPos());
}
if(d->pressed && old != d->currentArea && !d->pressPosIsInSmallCircle){
d->pressedMovedArea = d->currentArea;
emit sigAreaChanged(d->currentArea);
}
}
}
void CircleMenu::mouseReleaseEvent(QMouseEvent *event)
{
Q_D(CircleMenu);
d->pressed = false;
if(event->button() != Qt::LeftButton){
return ;
}
if(d->isMenuVisible){
auto old = d->pressedMovedArea;
d->pressedMovedArea = d->calcArea(event->pos());
if(old != d->pressedMovedArea){
emit sigAreaChanged(d->pressedMovedArea);
}
emit sigClicked(d->pressedMovedArea);
}
if(!d->isPopup && !d->moved){
QPoint rela = event->pos() - QPoint(width() / 2, height() / 2);
int dis = std::sqrt(rela.x() * rela.x() + rela.y() * rela.y());
if(dis > d->smallDiameter / 2){
return ;
}
d->isMenuVisible = !d->isMenuVisible;
d->aniGroup->setDirection(d->isMenuVisible ? QVariantAnimation::Forward : QVariantAnimation::Backward);
d->aniGroup->start();
}
d->moved = false;
}
3、重写event事件,点击主界面空白区域关闭窗口
bool CircleMenu::event(QEvent *event)
{
switch (event->type()) {
case QEvent::FocusOut:
case QEvent::WindowDeactivate:
if(d_func()->isPopup){
d_func()->hidePopup();
}
break;
case QEvent::Leave:
d_func()->currentArea = Unknown;
update();
break;
default:
break;
}
return QWidget::event(event);
}
4、最后是绘图代码
void CircleMenu::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
Q_D(CircleMenu);
QPainter painter(this);
if(d->isPopup){
painter.fillRect(rect(), QBrush(QColor(0, 0, 0, 1)));
}
painter.setRenderHints(QPainter::SmoothPixmapTransform | QPainter::Antialiasing);
QPointF center(width() / 2.0, height() / 2.0);
painter.translate(center);
painter.rotate(d->angle);
d->drawCircle(&painter);
d->drawPie(&painter);
d->drawArrow(&painter);
d->drawImages(&painter);
}
工程代码下载链接:Qt圆形环状菜单