先看一下实现的效果(动态图)
尚未进行后续优化,比如显示文本这些。
做这个控件的初衷,是因为之前做了一个代码助手, 可以把常用代码或者库添加到代码助手里边,然后使用的时候双击,加入到剪贴板,便于操作, 代码助手大概像下边这样
然后突发奇想, 感觉加上一个这种快捷键可以呼出的拖动盘, 会很酷, 所以就有了这次的拖动盘demo, 后期会将拖动盘集成到代码助手里边, 实现类似LOL的效果
有点扯远了, 下边直接上代码
头文件
class MovePanel : public QDialog
{
Q_OBJECT
public:
MovePanel(QWidget *parent = nullptr);
~MovePanel();
signals:
void doSelected(const QString& codeName); //选中了某一块
protected:
void paintEvent(QPaintEvent*) override;
void mouseMoveEvent(QMouseEvent*) override;
void mousePressEvent(QMouseEvent*) override;
void mouseReleaseEvent(QMouseEvent*) override;
protected:
int currentPos(const QPoint& pos); //获取当前鼠标在第几象限
void resetColor(); //重置所有颜色
void initPath(); //初始化坐标位置path;
protected:
void drawBackground(QPainter& p); //绘制背景
void drawPie(QPainter& p); //绘制4个扇形区
void drawCancel(QPainter& p); //绘制中央的取消按钮
void drawArrow(QPainter& p); //绘制鼠标箭头
void drawPath(QPainter& p);
private:
Ui::MovePanel *ui;
QVector<QColor> colors; //4个分块的颜色值
QVector<QPainterPath> paths; //4个分块的rect, 用这4个分块,确认当前鼠标再哪个分组里边
QPoint point; //当前鼠标拖动到了哪里
bool isPress{false}; //是否在中间按下了鼠标
int centerX{0}; //图形中心X
int centerY{0}; //图形中心Y
QRect centerRect; //图形中心的取消按钮
int alpha{255}; //透明系数
};
.cpp文件
#include "movepanel.h"
#include "ui_movepanel.h"
#include <QMouseEvent>
#include <QPaintEvent>
#include <QPainter>
#include <QDebug>
MovePanel::MovePanel(QWidget *parent)
: QDialog(parent)
, ui(new Ui::MovePanel)
{
ui->setupUi(this);
setAutoFillBackground(true);
setWindowFlags( Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint ); //设置无边框窗口,并位于最前
setAttribute( Qt::WA_TranslucentBackground ); //背景透明
move(700, 100);
setMouseTracking(true);
//4个分块初始情况下都是这个颜色
colors.append(QColor(135, 236, 211, alpha)); //第二象限
colors.append(QColor(135, 236, 211, alpha)); //第一象限
colors.append(QColor(135, 236, 211, alpha)); //第三象限
colors.append(QColor(135, 236, 211, alpha)); //第四象限
//4个代表区域的方块
centerX = width()/2;
centerY = height()/2;
centerRect = QRect(centerX-40, centerY-40, 80, 80); //中心区域
initPath();
}
MovePanel::~MovePanel()
{
delete ui;
}
void MovePanel::paintEvent(QPaintEvent *)
{
QPainter p(this);
int side = qMin(width(), height());
p.translate(width()/2, height()/2);
p.scale(side/200.0, side/200.0);
p.setRenderHint(QPainter::Antialiasing);
drawBackground(p);
drawPie(p);
drawArrow(p);
drawCancel(p);
// drawPath(p);
}
void MovePanel::mouseMoveEvent(QMouseEvent *e)
{
if(isPress){
resetColor(); //把所有颜色重置
point = e->pos();
int currentIndex = currentPos(e->pos());
if(currentIndex > -1){
colors[currentIndex] = QColor(84,228,193,alpha); //当前鼠标悬浮位置进行变色
}
update();
}
}
void MovePanel::mousePressEvent(QMouseEvent *e)
{
if(centerRect.contains(e->pos())){
isPress = true;
}
}
void MovePanel::mouseReleaseEvent(QMouseEvent *e)
{
//如果选择了某一个下标,就结束
if(currentPos(e->pos()) > -1){
emit doSelected("");
// close();
}
isPress = false;
resetColor();
update();
}
int MovePanel::currentPos(const QPoint &pos)
{
for(int i=0; i<paths.count(); i++){
if(paths.at(i).contains(pos)){
qDebug() << "cur:" << i;
return i;
}
}
return -1;
}
void MovePanel::resetColor()
{
for(int i=0; i<colors.count(); i++){
colors[i]=QColor(135, 236, 211, alpha);
}
}
void MovePanel::initPath()
{
//构造4个扇形区
for(int i=0; i<4; i++){
QPainterPath path;
//要注意,这里使用的是绝对坐标, 而不是相对side/200的坐标
path.arcTo(QRectF(-200, -200, 400, 400), -45+(i*90), 90);
path.translate(centerX, centerY);
paths.append(path);
}
}
void MovePanel::drawBackground(QPainter &p)
{
p.save();
p.setBrush(QColor(0, 0, 0, 0)); //绘制一个透明的背景
p.setPen(Qt::NoPen);
p.drawEllipse(-100, -100, 200, 200);
p.restore();
}
void MovePanel::drawPie(QPainter &p)
{
p.save();
p.setPen(QColor(0, 220, 176, alpha));
p.rotate(-45);
//绘制第二象限
p.setBrush(colors.at(1));
p.drawPie(QRectF(-90, -90, 180, 180.0), 0*16, 90*16);
//绘制第一象限
p.rotate(-90);
p.setBrush(colors.at(2));
p.drawPie(QRectF(-90, -90, 180, 180.0), 0*16, 90*16);
//绘制第三象限
p.rotate(-90);
p.setBrush(colors.at(3));
p.drawPie(QRectF(-90, -90, 180, 180.0), 0*16, 90*16);
//绘制第四象限
p.rotate(-90);
p.setBrush(colors.at(0));
p.drawPie(QRectF(-90, -90, 180, 180.0), 0*16, 90*16);
p.restore();
}
void MovePanel::drawCancel(QPainter &p)
{
QRect rec;
if(!isPress){
rec = QRect(-5, -5, 10, 10);
}else{
rec = QRect(-2, -2, 4, 4);
}
p.save();
p.setPen(QColor(28,175,244, alpha));
p.setBrush(QColor(84,228,193,alpha));
p.drawEllipse(rec);
p.restore();
}
void MovePanel::drawArrow(QPainter &p)
{
if(isPress){
p.save();
p.setPen(QColor(28,175,244, alpha));
p.drawLine( 0, 0, point.x()/2-100, point.y()/2-100 );
p.setPen(Qt::NoPen);
p.setBrush(QColor(28,175,244, alpha));
p.drawEllipse( point.x()/2-105, point.y()/2-105, 10, 10 );
p.restore();
}
}
void MovePanel::drawPath(QPainter &p)
{
p.save();
p.setPen(Qt::red);
p.setBrush(Qt::yellow);
for(int i=0; i<4; i++){
p.drawPath(paths[i]);
}
p.restore();
}
学无止境,QT冲冲冲