首先直接放出相关代码,可以根据注释进行一定修改。
以下为头文件的内容
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QMouseEvent>
#include <QLabel>
#include <QPainter>
#include <QImage>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
//重写Qt中鼠标相关事件的函数
void mousePressEvent(QMouseEvent *e);//鼠标按下事件
void mouseMoveEvent(QMouseEvent *e);//鼠标移动事件
void mouseReleaseEvent(QMouseEvent *);//鼠标释放事件
void paintEvent(QPaintEvent *);
private:
Ui::MainWindow *ui;
QLabel label;
QPoint p;
};
#endif // MAINWINDOW_H
以下为实现文件的内容
#include "mainwindow.h"
#include "ui_mainwindow.h"
QPoint readyapply,prereadyapply,afterapply=QPoint(0,0);
//设置了三个QPoint类型变量,后续用以确定绘图点的位置
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->setFixedSize(1080,640);
/*在此固定了窗口的大小,如果不固定,
可以考虑使用布局相关控件控制图片与界面间的关系*/
}
MainWindow::~MainWindow()
{
delete ui;
}
//对鼠标点击事件进行重写
//设定prereadyapply点获得鼠标点击时相对于界面左上角的坐标
void MainWindow::mousePressEvent(QMouseEvent *e)
{
prereadyapply.setX(e->position().x());
prereadyapply.setY(e->position().y());
}
//对鼠标移动事件重写,获得鼠标移动时,相对于点击时所在位置的位移
void MainWindow::mouseMoveEvent(QMouseEvent *e)
{
readyapply.setX(prereadyapply.x()-e->position().x());
readyapply.setY(prereadyapply.y()-e->position().y());
repaint();//重绘,实现鼠标拖拽改变图片的显示情况
}
//对鼠标释放事件重写,通过累加记录图片绘制点的位置,
//并将readyapply点数据重置
void MainWindow::mouseReleaseEvent(QMouseEvent *)
{
afterapply=afterapply+readyapply;
readyapply=QPoint(0,0);
}
void MainWindow::paintEvent(QPaintEvent *)
{
QPainter painter(this);
QImage image;//创建QImage对象,可使用帮助文档查阅相关的用法
QRectF target(0, 0, 400, 400);//设置窗口的绘图区域
QPoint temppoint;//后续用以确定绘图的右下角
QPoint temppointfirst;
temppointfirst.setX(afterapply.x()+readyapply.x());
temppointfirst.setY(afterapply.y()+readyapply.y());
//注意此处要窗口的绘图区域和图片的绘制区域大小均为400*400,
//若大小不同,需要考虑比例的问题,否则会出现图片不能完全跟随鼠标的情况
temppoint.setX(temppointfirst.x()+400);
temppoint.setY(temppointfirst.y()+400);
//两个变量分别为绘图区域的左上角和右下角
QRectF source(temppointfirst,temppoint);
//载入图片路径,根据自身文件路径及名称进行更改
image.load(":/picture.png");
painter.drawImage(target, image, source);
/*绘制图片,变量依次为绘图的目标区域、绘制的图片、
被绘制的图片的区域(例如若只绘制出图片的右下角,
需要将该区域的坐标设定进行相应更改)*/
}
在这里将解释一下相关函数的使用
1、mousePressEvent、mouseMoveEvent、mouseReleaseEvent函数。
以上三者均为Qt自身的事件函数,分别在鼠标按下、移动、释放时自动执行,可以通过对它们进行重写来实现某些关于鼠标的功能,例如这里的图片拖拽功能。
2、QRect函数
如图中说明,该函数可定义一个精度为整数的矩形区域。
以下为官方帮助文档给出的示例。
QRect r1(100, 200, 11, 16);
QRect r2(QPoint(100, 200), QSize(11, 16));
可以通过设定矩形区域左上角和右下角的坐标进行定义,其中设定坐标可以通过依次给出两点的横纵坐标或给出两个QPoint对象实现。
3、QPoint函数
官网文档给出了对一个QPoint对象进行操作的示例,可以通过setX()、setY()函数更改对象的横纵坐标等。
4、drawImage函数
该函数为QPainter类下的一个函数,可以再QPainter类实例对象后使用 . 来调用。该函数有很多重载函数,可以从左至右依次给出窗口绘图区域、图片路径和图片要进行绘制的区域来使用,也是本例所使用的方法。
QRectF target(10.0, 20.0, 80.0, 60.0);
QRectF source(0.0, 0.0, 70.0, 40.0);
QImage image(":/images/myImage.png");
QPainter painter(this);
painter.drawImage(target, image, source);
为方便解释、理解,可以将该功能简化理解为如何在一维的空间上移动显示一条线。
本例中,图片的显示通过一个设定的矩形区域来完成,和矩形区域相同,一条线也需要有一个区域的端点,在此处将这条线的左端作为绘制起点。
若要将这条线在水平方向上进行移动,本质上是改变这条线的绘制起点的位置,从QPoint类的函数中,我们知道可以通过setX、setY等函数改变点的位置。
点击鼠标后,我们期望这条线可以跟随鼠标移动,且与鼠标的相对位置保持不变。通过position函数,我们可以获得鼠标相对于桌面的坐标,但这个相对于桌面的绝对坐标我们无法直接使用。我们需要的是鼠标移动后,相对于点击时的点的坐标,这也正是实现这条线相对于原先位置进行位移的关键。
我们可以设置两个变量分别存储鼠标点击时和移动后的坐标,这里分别用prereadyapply和readyapply进行表示,使用后者的坐标减去前者的坐标,即得到了鼠标相对于点击时的点的位移。通过在移动过程中改变绘图事件绘制区域的端点坐标并不断进行重绘实现图片的拖拽。
在完成图片拖拽后,我们需要记录拖拽后图片的绘制点的坐标,这里使用变量afterapply进行存储,也可使用static局部静态变量进行保存。
此外,在鼠标释放后需要将readyapply变量清零,因为绘图事件会在界面隐藏、显示以及其余多种情况下被触发进行,而本例在绘图事件中通过加上readyapply变量的数据实现图片绘图位置的改变,因此若不及时清零,图片将会在几次绘图事件自动触发后偏离到很远的地方,造成显示异常。
以下为未正确清空变量时,绘图事件多次触发后绘制点的异常变化。
最后再说几句,这段时间由于学校课程要求学习了一些Qt相关知识,在社区中得到了很多帮助,不过许多资源由于积分限制等无法下载学习,在此将自己的一些浅薄见解分享出来,希望可以帮助到各位。