2021-07-16(Qt实现图片拖拽功能)

关于如何使用Qt实现简单的图片拖拽及缩放功能

一、代码实现

首先直接放出相关代码,可以根据注释进行一定修改。

以下为头文件的内容

#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相关知识,在社区中得到了很多帮助,不过许多资源由于积分限制等无法下载学习,在此将自己的一些浅薄见解分享出来,希望可以帮助到各位。

  • 10
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: Qt Image Viewer是基于Qt框架实现图片浏览器。Qt是跨平台的C++应用程序开发框架,它提供了丰富的图形界面控件和功能库,适合用于创建各种类型的应用程序。 在Qt Image Viewer中,我们可以使用QImage类来加载和处理图片。QImage类提供了许多用于处理图片的函数,例如加载图片、缩放、旋转等等。 在实现图片浏览器的时候,我们可以使用QFileDialog类来打开图片文件。用户可以通过该类的getOpenFileName函数选择要打开的图片文件,并将文件路径传递给QImage类进行加载。 为了显示图片,我们可以使用QLabel类作为图片的容器。在QLabel中,我们可以使用setPixmap函数将QImage对象转换为QPixmap,并使用setScaledContents函数将图片自适应地放置在容器中。 为了实现浏览多张图片功能,我们可以在窗口中添加按钮或者菜单栏来供用户选择前一张或者后一张图片。当用户点击这些按钮时,我们可以在加载图片之前判断是否已经加载了一张图片,如果已经加载,则根据用户的操作加载前一张或者后一张图片。 此外,我们还可以添加一些其他的功能,如缩放图片、旋转图片、保存图片等等。这些功能可以通过在窗口中添加一些按钮或者菜单项来实现,并与对应的QImage函数进行连接。 总的来说,Qt Image Viewer通过使用Qt框架提供的函数和控件,可以实现一个简单但功能齐全的图片浏览器。用户可以方便地打开、查看和操作图片。 ### 回答2: Qt是一款功能强大的跨平台应用程序开发框架,它提供了丰富的类库和工具,可用于开发各种类型的应用程序,包括图片浏览器。 在Qt中,可以使用QImage来加载和显示图片。首先,我们可以通过QFileDialog类选择要显示的图片文件,然后使用QImage加载该文件。加载完成后,可以将QImage转换为QPixmap,以便在窗口中显示。我们可以使用QLabel或QGraphicsView来显示QPixmap,从而实现图片浏览器的界面。 为了能够浏览不同图片,我们可以使用QPushButton或QAction添加上一张和下一张图片功能。当点击这些按钮时,可以切换当前显示的图片。另外,我们还可以使用QSlider或QScrollBar添加缩放功能,以实现放大和缩小图片的效果。 此外,为了方便用户对图片进行查看和编辑,我们可以将图片浏览器与其他功能结合起来。例如,我们可以添加图像旋转、翻转、裁剪等操作的功能按钮,以及添加保存图片功能按钮。 最后,为了提高用户体验,我们还可以添加一些便捷的功能,如拖拽图片到窗口中自动加载,支持多种图片格式,添加全屏显示的功能等。 综上所述,使用Qt的QImage和QPixmap,以及QLabel、QGraphicsView、QPushButton、QAction、QSlider等类,我们可以很方便地实现一个简单但功能完善的图片浏览器。通过选取和加载图片文件,并提供方便的浏览和编辑操作,可以满足用户对图片浏览器的基本需求。 ### 回答3: 在使用Qt实现图片浏览器时,我们可以使用Qt的QImage和QPixmap类来处理和显示图片。 首先,我们需要创建一个主窗口,在主窗口中添加一个QGraphicsView作为显示图片的画布。然后,我们可以通过QFileDialog来打开一个图片文件,获取图片的路径。 接下来,我们可以使用QImage类来读取图片的数据,并将其转换为QPixmap格式以便显示在QGraphicsView中。我们可以通过QGraphicsScene来管理QGraphicsView中的显示内容,将QPixmap添加到QGraphicsScene中,并将场景关联到QGraphicsView上。 为了实现图片的浏览功能,我们可以在主窗口中添加两个按钮,一个是“上一张”,一个是“下一张”。点击这些按钮时,我们可以通过改变图片的路径并重新加载图片实现图片的切换。 此外,我们还可以添加其他功能,例如放大缩小图片、旋转图片等,可以使用QTransform类来实现这些功能。 最后,我们还可以使用QScrollBar来实现图片的滚动效果,当图片的大小超过QGraphicsView的大小时,可以通过滚动条来查看完整的图片内容。 总结一下,使用Qt的QImage和QPixmap类结合QGraphicsView和QGraphicsScene,我们可以方便地实现一个简单的图片浏览器,并添加功能图片切换、放大缩小、旋转和滚动等。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

关岭风尘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值