Qt编写自定义控件:左上角圆形菜单控件
Posted 友善啊,朋友
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Qt编写自定义控件:左上角圆形菜单控件相关的知识,希望对你有一定的参考价值。
代码:
#ifndef ROUNDMMENUINUPPERLEFTCORNERWIDGET_H
#define ROUNDMMENUINUPPERLEFTCORNERWIDGET_H
#include <QWidget>
#include <QTimer>
#include <QPainterPath>
class RoundMmenuInUpperLeftCornerWidget : public QWidget
Q_OBJECT
public:
RoundMmenuInUpperLeftCornerWidget(QWidget *parent = nullptr);
~RoundMmenuInUpperLeftCornerWidget()override;
protected:
void paintEvent(QPaintEvent *event)override;
void mousePressEvent(QMouseEvent *event)override;
void resizeEvent(QResizeEvent *event)override;
void mouseReleaseEvent(QMouseEvent *event)override;
void mouseMoveEvent(QMouseEvent *event)override;
private:
void onTimer();
enum class State
Shrink,//收缩
Popped,//已弹出
Popping//正在弹出
;
State widgetStateState::Shrink;
State lastWidgetStateState::Shrink;
QRect homeBtnRect;
QTimer timer;
int Length0;
int radius0;
int outSideRadius0;
QList<QPixmap> imgList;
QList<QRect> menuRectList;
int pressIndexInMenuRectList-1;
QPoint pressPos0,0;
QPainterPath arcAreaPath;
int allBeforeAngleOffset0;
int currentOffset0;
;
#endif // ROUNDMMENUINUPPERLEFTCORNERWIDGET_H
#include "roundmmenuinupperleftcornerwidget.h"
#include <QPainter>
#include <QPaintEvent>
#include <QDebug>
RoundMmenuInUpperLeftCornerWidget::RoundMmenuInUpperLeftCornerWidget(QWidget *parent)
: QWidget(parent)
setPalette(Qt::white);
setMouseTracking(true);
connect(&timer,&QTimer::timeout,this,&RoundMmenuInUpperLeftCornerWidget::onTimer);
timer.setInterval(40);
imgList << QPixmap(":/img/F1.png");
imgList << QPixmap(":/img/F2.png");
imgList << QPixmap(":/img/F3.png");
imgList << QPixmap(":/img/F4.png");
imgList << QPixmap(":/img/F5.png");
imgList << QPixmap(":/img/F6.png");
imgList << QPixmap(":/img/F7.png");
imgList << QPixmap(":/img/F8.png");
imgList << QPixmap(":/img/F9.png");
imgList << QPixmap(":/img/F10.png");
imgList << QPixmap(":/img/F11.png");
imgList << QPixmap(":/img/F12.png");
auto it = std::inserter(menuRectList,menuRectList.begin());
for(int i = 0;i < imgList.size();++i,++it)
*it = QRect();
RoundMmenuInUpperLeftCornerWidget::~RoundMmenuInUpperLeftCornerWidget()
void RoundMmenuInUpperLeftCornerWidget::paintEvent(QPaintEvent *event)
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing,true);
painter.setRenderHint(QPainter::SmoothPixmapTransform,true);
const auto rect = event->rect();
auto width = rect.width();
auto height = rect.height();
Length = std::min(width,height);
if(widgetState == State::Shrink)
radius = 0.33 * Length / 1.2;
auto ellipseCenter = QPointF(radius*0.2,radius*0.2);
painter.save();
QRadialGradient radialGradient;
radialGradient.setCenter(ellipseCenter);
radialGradient.setRadius(radius * 1.2);
radialGradient.setFocalPoint(ellipseCenter);
radialGradient.setColorAt(0.0,QColor("#EAEAEA"));
radialGradient.setColorAt(1.0,QColor("#AFAFAF"));
painter.setBrush(radialGradient);
painter.setPen(QColor("#808080"));
painter.drawEllipse(ellipseCenter,radius,radius);
painter.restore();
homeBtnRect = QRect(radius*0.05,radius*0.05,radius*0.8,radius*0.8);
painter.drawPixmap(homeBtnRect,QPixmap(":/img/home.png"));
if(widgetState != State::Shrink)
QPainterPath p1;
p1.addEllipse(ellipseCenter,outSideRadius,outSideRadius);
QPainterPath p2;
p2.addEllipse(ellipseCenter,radius,radius);
arcAreaPath = p1 - p2;
painter.setBrush(QColor("#E2E2D0"));
painter.setPen(Qt::transparent);
painter.drawPath(arcAreaPath);
if(widgetState != State::Shrink)
int cha = outSideRadius - radius;
int imgX = (1.2 * radius) + (cha - radius*0.8) / 2;
int imgY = 0.2 *radius;
QRect imgRect;
if(widgetState == State::Popping)
imgRect = QRect(imgX,imgY,cha * 0.6,cha * 0.6);
else
imgRect = QRect(imgX,imgY,radius*0.8,radius*0.8);
int size = imgList.size();
QTransform transform;
QPoint temp(static_cast<int>(radius*0.4),static_cast<int>(radius*0.4));
for (int i = 0;i < size;++i)
auto angle = 360 / size * i + allBeforeAngleOffset + currentOffset;
painter.save();
painter.rotate(angle);
painter.drawPixmap(imgRect,imgList.at(i));
painter.restore();
transform.reset();
transform.rotate(angle);
QPoint transform_p = transform.map(imgRect.center());
menuRectList[i] = QRect(transform_p - temp,transform_p + temp);
if(pressIndexInMenuRectList >= 0)
QColor slightlyOpaqueBlack(0, 0, 0, 63);
painter.setBrush(slightlyOpaqueBlack);
painter.drawEllipse(menuRectList.at(pressIndexInMenuRectList));
void RoundMmenuInUpperLeftCornerWidget::mousePressEvent(QMouseEvent *event)
QRegion ellipseRegion(homeBtnRect, QRegion::Ellipse);
auto pos = event->pos();
if(ellipseRegion.contains(pos))
if(widgetState == State::Shrink)
lastWidgetState = State::Shrink;
radius = 0.5 * Length / 1.2;
outSideRadius = radius;
widgetState = State::Popping;
else if(widgetState == State::Popped)
lastWidgetState = State::Popped;
radius = 0.33 * Length / 1.2;
widgetState = State::Popping;
timer.start();
else
pressIndexInMenuRectList = -1;
if(widgetState == State::Popped)
for(int i = 0;i < menuRectList.size();++i)
if(menuRectList.at(i).contains(pos))
pressIndexInMenuRectList = i;
break;
if(pressIndexInMenuRectList == -1)
if(arcAreaPath.contains(pos))
pressPos = pos;
setCursor(Qt::OpenHandCursor);
update();
QWidget::mousePressEvent(event);
void RoundMmenuInUpperLeftCornerWidget::onTimer()
if(widgetState == State::Popping)
if(lastWidgetState == State::Shrink)
outSideRadius += Length * 0.1;
if(outSideRadius >= (Length - radius * 0.2))
timer.stop();
widgetState = State::Popped;
outSideRadius = Length - radius * 0.2;
else if(lastWidgetState == State::Popped)
outSideRadius -= Length * 0.1;
if(outSideRadius < radius)
timer.stop();
widgetState = State::Shrink;
outSideRadius = radius;
update();
void RoundMmenuInUpperLeftCornerWidget::resizeEvent(QResizeEvent *event)
widgetState = State::Shrink;
update();
QWidget::resizeEvent(event);
void RoundMmenuInUpperLeftCornerWidget::mouseReleaseEvent(QMouseEvent *event)
if(widgetState == State::Popped)
pressIndexInMenuRectList = -1;
pressPos = QPoint(0,0);
allBeforeAngleOffset += currentOffset;
currentOffset = 0;
setCursor(Qt::ArrowCursor);
update();
QWidget::mouseReleaseEvent(event);
void RoundMmenuInUpperLeftCornerWidget::mouseMoveEvent(QMouseEvent *event)
auto pos = event->pos();
bool mouseInAbtnZonefalse;
QRegion ellipseRegion(homeBtnRect, QRegion::Ellipse);
if(ellipseRegion.contains(pos))
mouseInAbtnZone = true;
else
if(widgetState == State::Popped)
for(const auto & rect : menuRectList)
QRegion ellipseRegion(rect, QRegion::Ellipse);
if(ellipseRegion.contains(pos))
mouseInAbtnZone = true;
break;
if(pressPos.isNull())
setCursor(mouseInAbtnZone ? Qt::PointingHandCursor : Qt::ArrowCursor);
else
QLineF line1(QPoint(radius*0.2,radius*0.2),pressPos);
QLineF line2(QPoint(radius*0.2,radius*0.2),pos);
int angle = line2.angleTo(line1);
if(angle > 200)
if(pos.x() > 0 && pos.y() > 0)
angle = -(360 - angle);
currentOffset = angle;
setCursor(Qt::OpenHandCursor);
update();
QWidget::mouseMoveEvent(event);
效果:
放在主窗口左上角:
#include "roundmmenuinupperleftcornerwidget.h"
#include <QApplication>
#include <QMainWindow>
#include <QHBoxLayout>
#include <QPushButton>
#include <QVBoxLayout>
int main(int argc, char *argv[])
QApplication a(argc, argv);
QMainWindow mainWindow;
mainWindow.resize(1000,600);
QVBoxLayout * vb = new QVBoxLayout;
for(int i = 0;i < 5;++i)
QHBoxLayout * hb = new QHBoxLayout;
hb->addWidget(new QPushButton);
hb->addWidget(new QPushButton);
hb->addWidget(new QPushButton);
hb->addWidget(new QPushButton);
vb->addLayout(hb);
QWidget * widget = new QWidget;
widget->setLayout(vb);
mainWindow.setCentralWidget(widget);
RoundMmenuInUpperLeftCornerWidget w(&mainWindow);
w.setFixedSize(300,300);
mainWindow.show();
return a.exec();
UI参考:jQuery左上角圆形菜单展开收缩特效
以上是关于Qt编写自定义控件:左上角圆形菜单控件的主要内容,如果未能解决你的问题,请参考以下文章