QT实现的自定义按键精灵

一个QT实现的按键精灵(只写了鼠标部分,键盘用不到就懒得写了)。这里分享一下思路和一些碰到的问题。

功能思路

(1)重复鼠标点击过程:
		运行方式:
				连点:以固定的时间频率按顺序连续点击设置的点位,可以用来当连点器用。
				顺时:完全重复录制下来的鼠标点击过程,按设录制时的点击顺序和时间间隔循环。
		实现方式:
				录制:录制鼠标点击的轨迹(包括时间间隔)
				保存:以txt格式保存轨迹到制定文件夹下
				打开:打开已保存的鼠标轨迹
				运行:									
					移动:根据当前轨迹,按顺序移动到轨迹点位
					点击:在当前点位上,模拟鼠标的点击
(2)显示模式:
		考虑到某些游戏需要全屏,所以需要开发额外的显示模式:
				置顶:始终保持软件置于最顶层
				图标模式:将完整界面变为小图标,以免遮住游戏界面
					界面变换:保留图标,隐藏其他全部空间,背景变为透明
					图标移动:按住拖动图标
			 	隐藏模式: 隐藏整个界面,只显示游戏界面,通过键盘操作实现功能。
			 		键盘操作:绑定键盘键位,实现对软件的案件操作。
(3)附加功能:
		速度设置:设置连点模式下的点击速度
		时间显示:显示录制时间和运行时间
		点位显示:显示录制或打开的全部点位
		轨迹显示:用QChart同比显示运行轨迹(实时)

部分模块分享

主要是分享一些碰到的问题和一些QT以外的内容(Windwos.h),还有一些QChart的内容。其他东西,基本都是软件本身的架构、逻辑还有一些常用的东西,全放出来太多了,这里就不帖了。

鼠标拖动及图标化显示切换

因为是写在PC端给模拟器用的,所以直接用了C++的 Windows.h 这个类。
而使用Windows.h类的时候,可能会碰到库引用的问题,就是明明你可以在QT安装目录的对应文件夹里找到Windows.h,也可以正常#include它,但是,就是无法编译通过,这种情况下,所有基于Windows.h的变量和函数都会 报错。
解决方式也很简单,在调用该类的.cpp文件下,加入下面这行代码即可(加载#include之下,构造函数之上):

#pragma comment(lib, "user32.lib")

下面是一些虚函数的重载:
重载三个鼠标函数,实现界面拖动,变量的类型,都在后面注释了。

   void Wizard::mousePressEvent(QMouseEvent *event)
{
    //当鼠标左键点击时.
    if (event->button() == Qt::LeftButton)
    {
        m_move = true;  //bool
        //记录鼠标的世界坐标.
        m_startPoint = event->globalPos();  //QPoint
        //记录窗体的世界坐标.
        m_windowPoint = this->frameGeometry().topLeft();  //QPoint
    }
}

void Wizard::mouseMoveEvent(QMouseEvent *event)
{
    if (m_move == true)
    {
        //移动中的鼠标位置相对于初始位置的相对位置.
        QPoint relativePos = event->globalPos() - m_startPoint;
        //然后移动窗体即可.
        this->move(m_windowPoint + relativePos );
    }
}

void Wizard::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
    {
        //改变移动状态.
        m_move = false;
    }
}

图标化显示的时候,绘制透明遮罩,将widget的背景变为透明。

void Wizard::paintEvent(QPaintEvent *event)  
{
    QPainter painter(this);
    painter.fillRect(this->rect(), QColor(255, 255, 255, clarity));
}

本来用 button 来实现界面的点击变换是最方便的,但是拖动图标移动的功能始终无法在 button上实现,每次拖动,鼠标都会自动从按钮上锚定到widget的空白部分拖动,效果就很僵硬,qml里可以直接用mouseArea来实现,但widget我用得不多,所以最后只能用本身可以拖动的label代替button,然后给label加上事件过滤器实现界面变换的效果。

ui->moveIcon->installEventFilter(this);  //给选定的label添加事件过滤器,写在构造函数里

bool Wizard::eventFilter(QObject *watched, QEvent *event)  //label事件过滤器,最小(最大化)
{
    if(watched == ui->moveIcon)
    {
        //判断事件
        if(event->type() == QEvent::MouseButtonDblClick)  //双击图标,进行窗口变换
        {
            if (this->height()>120)  //如果为窗口模式
            {
                clarity = 0;  //通明度设为0
                ui->moveIcon->setPixmap(QPixmap(":/Res/image/最大化.png"));
                ui->exitbtn->hide();
                ui->runtime->hide();
                //…………
                //这边不全放出来了,隐藏所有控件
                this->setFixedSize(ui->moveIcon->width()+20,ui->moveIcon->height()+20);
            }
            else  //如果为图标藐视
            {
                clarity = 255;
                ui->moveIcon->setPixmap(QPixmap(":/Res/image/最小化.png"));
                ui->hideall->show();
                ui->runtime->show();
                //…………
                //显示所有控件
                this->setFixedSize(1040,802);
            }
            return true; //该事件已处理
        }
        else
            return false; //如果是其它事件,可以进行进一步的处理
    }
    else
        return QWidget::eventFilter(watched, event);
}
鼠标点击及键盘设置

模拟鼠标点击,mouse_event 为Windwos.h自带库函数。

//写在执行函数里
        SetCursorPos(pos_x,pos_y);//更改鼠标坐标,Window.h库函数,直接调即可,不用声明
        mouseaction(1,1, m_Pos);  //左键按下
        mouseaction(1,0, m_Pos);  //左键松开


void TimerRun::mouseaction(int key, int flag, const QPoint &point)
{
 //key: 1左键,0右键;  flag:1按下,0松开
    if (key == 1)
    {
        if (flag == 1)
            mouse_event(MOUSEEVENTF_LEFTDOWN, point.x(), point.y(), 0, 0);
        else
            mouse_event(MOUSEEVENTF_LEFTUP, point.x(), point.y(), 0, 0);
    }
    else
    {
        if (flag == 1)
            mouse_event(MOUSEEVENTF_RIGHTDOWN, point.x(), point.y(), 0, 0);
        else
            mouse_event(MOUSEEVENTF_RIGHTUP, point.x(), point.y(), 0, 0);
    }
}

键盘键位功能的设置。

void Wizard::keyPressEvent(QKeyEvent *event)
{
    int keyValue = event->key();

    if (keyValue == Qt::Key_F1)  //开始录制
        ui->beginrecord->click();
    if (keyValue == Qt::Key_F2)  //开始运行
        ui->startrun->click();
    if (keyValue == Qt::Key_F3)  //保存轨迹
        ui->savdfile->click();
    if (keyValue == Qt::Key_F4)  //打开文件
        ui->openfile->click();
    if (keyValue == Qt::Key_F5)  //隐藏界面
        ui->hideall->click();
    if (keyValue == Qt::Key_F9)  //退出软件
        ui->exitbtn->click();

//按住Ctrl,然后点击鼠标左键,实现点位录入
    if (keyValue == Qt::Key_Control && ui->beginrecord->text().compare("结束录制") == 0)  
    {
        //获取鼠标位置
        m_pos = QCursor::pos();//获取鼠标的绝对位置  QPoint
        int currenttime = rec_h*3600*1000+rec_min*60*1000+rec_s*1000;
        pos.insert(QString::number(poskey), tr("%1,%2,%3").arg(m_pos.x()).arg(m_pos.y()).arg(currenttime));  //QJsonObject
        QString str = tr("Point%1:(%2,%3)-%4").arg(poskey).arg(m_pos.x()).arg(m_pos.y()).arg(currenttime);
        ui->pointrecord->appendPlainText(str);  //打印显示点位
        poskey++;  //int,点位标志名
        chart->GenerateData_slot(m_pos.x(), 1080-m_pos.y());  //QChart图标实时更新
    }
}
QChart轨迹同步显示

这里直接把我自己设置的QChart全放出来吧,因为我也是第一次用这个,所以注释还是比较详细的
.h

#ifndef DYNAMICCHART_H
#define DYNAMICCHART_H

#include <QtCharts/QChart>
#include <QtCharts/QSplineSeries>
#include <QtCharts/QValueAxis>
#include <QTimer>

QT_CHARTS_USE_NAMESPACE

class DynamicChart : public QChart
{
    Q_OBJECT
public:
    DynamicChart(QChart *parent = nullptr);
    ~DynamicChart();

public slots:
    void GenerateData_slot(const int &x, const int &y);
    void ClearData_slot();

private:
    QLineSeries *m_series;//存放所有图表中点的坐标,如果想要显示2条或者以上的图表,则需要声明多个对象
    QValueAxis *m_axisX;
    QValueAxis *m_axisY;
};

#endif // DYNAMICCHART_H

.cpp

DynamicChart::DynamicChart(QChart *parent):
    QChart(parent),
    m_series(nullptr),
    m_axisX(new QValueAxis()),
    m_axisY(new QValueAxis())
{
    m_series = new QLineSeries(this);
    QPen DisplayStyle;
    DisplayStyle.setColor(QColor(11,80,240));//设置图表显示颜色
    DisplayStyle.setWidth(3);//设置图表显示宽度
    m_series->setPen(DisplayStyle);//将设置好的样式应用到series中,如果想要在一张图上显示多种样式
                                   //,那就要对多个series分别设置样式
    m_series->setPointsVisible(true);

    addSeries(m_series);
    addAxis(m_axisX,Qt::AlignBottom);//设置x轴以及对齐样式
    addAxis(m_axisY,Qt::AlignLeft);//设置y轴以及对齐样式

    m_axisX->setLabelFormat("%d");  //设置坐标轴数据格式
    m_axisX->setTickCount(10);//设置x轴之间的间隔
    m_axisX->setRange(0, 1920);//设置X轴的范围
    m_axisX->setGridLineColor(Qt::black);
    m_axisX->setMinorTickCount(1);
    m_axisX->setMinorGridLineColor(Qt::lightGray);

    m_axisY->setLabelFormat("%d");
    m_axisY->setTickCount(6);//设置Y轴之间的间隔
    m_axisY->setRange(0, 1080);//设置Y轴的范围
    m_axisY->setGridLineColor(Qt::black);
    m_axisY->setMinorTickCount(1);
    m_axisY->setMinorGridLineColor(Qt::lightGray);

    m_series->attachAxis(m_axisX);//将设置好的X轴放入series中
    m_series->attachAxis(m_axisY);//将设置好的Y轴放入series中
}

DynamicChart::~DynamicChart()
{
    delete m_axisY;
    delete m_axisX;
    delete m_series;
}

void DynamicChart::GenerateData_slot(const int &x, const int &y)
{
    m_series->append(x, y);//将数据放入series中,每加入一组数据,图表就会自动重画一次

}

void DynamicChart::ClearData_slot()
{
    m_series->clear();
}

效果演示

成品在下面,不保证没有bug,要用的自己下吧,发现bug了可以到下面留言,虽然我也大概率懒得改。
完整源码就不放了,像我这样的菜鸟写得代码,没什么借鉴意义,就不骗你们积分了。

在这里插入图片描述

链接:https://pan.baidu.com/s/1TtbntYaDi5P-hIR_euLFGw 
提取码:15m4
  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
好的,这里给你一个简单的 Qt 实现自定义旋钮的案例。 首先,我们需要在 Qt Designer 中创建一个自定义控件。打开 Qt Designer 后,选择 "Widget",新建一个空白的窗口,然后在左侧的 "Widget Box" 中选择 "Dial" 控件,将其拖拽到窗口中。这时候你就可以在窗口中看到一个简单的旋钮了。接着,我们需要对其进行自定义。 在左侧的 "Object Inspector" 中,选择 "dial" 控件,然后在右侧的 "Property Editor" 中修改其属性。比如,你可以修改它的 "minimum" 值和 "maximum" 值,使其能够旋转到任意角度。你还可以修改其样式,使其更符合你的设计需求。 接下来,我们需要在代码中实现这个自定义控件。打开 Qt Creator,创建一个新的 Qt Widgets 项目,并在其中添加一个自定义控件类。在这个类中,我们需要重写一些事件处理函数,以实现自定义旋钮的功能。以下是一个简单的实现: ```cpp class MyDial : public QDial { Q_OBJECT public: MyDial(QWidget* parent = nullptr) : QDial(parent) {} signals: void valueChanged(double value); protected: void mouseMoveEvent(QMouseEvent* event) override { if (event->buttons() & Qt::LeftButton) { QPoint pos = event->pos() - rect().center(); double angle = atan2(-pos.y(), pos.x()) * 180 / M_PI; setValue(static_cast<int>(angle)); emit valueChanged(angle); } } }; ``` 在这个示例中,我们重写了 `mouseMoveEvent` 函数,以处理鼠标移动事件。当鼠标左键按下时,我们计算出鼠标相对于旋钮中心的角度,然后调用 `setValue` 函数设置旋钮的值,并发出 `valueChanged` 信号。这个信号可以让其他对象在旋钮值发生改变时做出相应的响应。 最后,我们将这个自定义控件添加到主窗口中。打开主窗口的头文件,添加以下代码: ```cpp #include "mydial.h" class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget* parent = nullptr) : QMainWindow(parent) { MyDial* dial = new MyDial(this); dial->setGeometry(50, 50, 100, 100); connect(dial, &MyDial::valueChanged, this, &MainWindow::onDialValueChanged); } private slots: void onDialValueChanged(double value) { qDebug() << "Dial value changed:" << value; } }; ``` 在这个示例中,我们创建了一个 `MyDial` 对象,并将其添加到主窗口中。我们还连接了 `valueChanged` 信号,以在旋钮值发生改变时输出调试信息。 这就是一个简单的 Qt 实现自定义旋钮的案例。希望对你有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值