Qt自定義圓形環狀選單
阿新 • • 發佈:2021-01-09
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圓形環狀選單