Qt学习:文本图片自定义拖放操作及界面打印输出PDF文件


前言

空闲时间回顾了一下霍亚飞老师的Qt Creator快速入门书籍,对其中的拖放操作和打印文档部分知识进行了学习总结,并修改了下部分的示例代码,这里将相关内容进行记录展示,以便大家学习,如有错误之处,欢迎大家批评指正。

项目效果
请添加图片描述


提示:以下是本篇文章正文内容,下面案例可供参考

一、拖放文本文件

原文内容:对于一个实用的应用程序,不仅希望能从文件菜单中打开一个文件,更希望可以通过拖动,直接将桌面上的文件拖入程序界面来打开,就像将源文件拖入Qt Creator中打开一样。Qt提供了强大的拖放机制,可以在帮助中通过 Drag and Drop 关键字查看。拖放操作分为拖动(Drag)和放下(Drop)两种操作,当数据拖动时会被存储为MIME(Multipurpose Internet Mail Extensions)类型。Qt中使用QMimeData类来表示 MIME类型的数据,并使用QDrag类来完成数据的转移,而整个拖放操作都是在几个鼠标事件和拖放事件中完成的。

此处主要重写了以下事件处理函数:

protected:
    void dragEnterEvent(QDragEnterEvent *event);   //拖动进入事件
    void dropEvent(QDropEvent *event);             //放下事件

详细内容见后文示例代码。

二、自定义拖放图片

/*图片拖放步骤
//1.获取图片
//2.自定义HIME类型
//3.将数据放入QMimeData中
//4.将QMimeData数据放入QDrag中
//5.给原图片添加阴影
//6.执行拖放操作
*/

此时主要重写了以下事件处理函数:

protected:
	void mousePressEvent(QMouseEvent *event);      //鼠标按下事件
    void dragMoveEvent(QDragMoveEvent *event);     //拖动事件
    void dragEnterEvent(QDragEnterEvent *event);   //拖动进入事件
    void dropEvent(QDropEvent *event);             //放下事件

详细内容见后文示例代码。

三、TextEdit控件内容打印为PDF

原文内容:Qt5中的Qt Print Support模块提供了对打印的支持。最简单的,只需要使用一个QPrinter类和一个打印对话框QPrintDialog类就可以完成文档的打印操作。

项目需要Print Support模块,需要在.pro中添加如下代码:

QT += printsupport

项目中.h文件需要包含相应的类名:

#include <QPrinter>
#include <QPrintDialog>
#include <QPrintPreviewDialog>
#include <QtPrintSupport>
...

详细内容见后文示例代码。

四、Widget界面打印为PDF

这边的话可以看到我的示例上,将相应的Widget在ui界面进行了背景色样式表的修改,后面打印出来的PDF上也有相应的颜色。请添加图片描述

五、示例完整代码

1.myDrag.pro

QT       += core gui
QT       += printsupport

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11

DEFINES += QT_DEPRECATED_WARNINGS

SOURCES += \
    main.cpp \
    mainwindow.cpp

HEADERS += \
    mainwindow.h

FORMS += \
    mainwindow.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${
    
    TARGET}/bin
else: unix:!android: target.path = /opt/$${
    
    TARGET}/bin
!isEmpty(target.path): INSTALLS += target

2.mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QMoveEvent>
#include <QDragMoveEvent>
#include <QDragEnterEvent>
#include <QDropEvent>
#include <QPainter>
#include <QDrag>
#include <QUrl>
#include <QFile>
#include <QTextStream>
#include <QMimeData>
#include <QPrinter>
#include <QPrintDialog>
#include <QPrintPreviewDialog>
#include <QtPrintSupport>
#include <QFileDialog>
#include <QFileInfo>
#include <QPageSize>
#include <QMessageBox>
#include <QDebug>

QT_BEGIN_NAMESPACE
namespace Ui {
    
     class MainWindow; }
QT_END_NAMESPACE

class QPrinter;
class MainWindow : public QMainWindow
{
    
    
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

    void initWidget();

protected:
    void mousePressEvent(QMouseEvent *event);
    void dragMoveEvent(QDragMoveEvent *event);
    void dragEnterEvent(QDragEnterEvent *event);
    void dropEvent(QDropEvent *event);

private slots:
    void on_cb_copy_toggled(bool checked);

    void on_action_print_triggered();
    void on_action_preview_triggered();
    void on_action_pdf_triggered();
    void printPreview(QPrinter *printer);

    void on_pb_printWidget_clicked();

private:
    Ui::MainWindow *ui;

    Qt::DropAction myAction;
};
#endif // MAINWINDOW_H

3.mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    
    
    ui->setupUi(this);
    initWidget();
}

MainWindow::~MainWindow()
{
    
    
    delete ui;
}

void MainWindow::initWidget()
{
    
    
    setAcceptDrops(true);   //设置窗口可以接收放下事件
    ui->textEdit->setReadOnly(true);   //文本文件拖入主窗口界面或者TextEdit部件都能显示文本内容

    myAction = Qt::MoveAction;
    ui->cb_copy->setChecked(false);

    QPixmap pix("D:/QT/Project/my_Project/23_myDrag/test.PNG");   //图片路径
    ui->lb_photo->setPixmap(pix);
    ui->lb_photo->resize(pix.size());
    ui->lb_photo->move(100,100);
    ui->lb_photo->setAttribute(Qt::WA_DeleteOnClose);   //当窗口关闭时销毁图片
}

void MainWindow::mousePressEvent(QMouseEvent *event)   //鼠标按下事件
{
    
    
    /*图片拖放步骤
    //1.获取图片
    //2.自定义HIME类型
    //3.将数据放入QMimeData中
    //4.将QMimeData数据放入QDrag中
    //5.给原图片添加阴影
    //6.执行拖放操作
    */
    QLabel *child = static_cast <QLabel *> (childAt(event->pos()));   //将鼠标指针所在位置的部件强制转换为QLabel类型
    if(!child->inherits("QLabel"))
    {
    
    
        return;
    }
    if((child->objectName() == "label") || (child->objectName() == "label_2"))   //避免程序崩溃
    {
    
    
        return;
    }
    QPixmap pixmap = *child->pixmap();   //获取图片,注意QLabel部件中需要存在pixmap
    QByteArray itemData;   //创建字节数组
    QDataStream dataStream(&itemData,QIODevice::WriteOnly);   //创建数据流
    dataStream << pixmap << QPoint(event->pos() - child->pos());   //将图片及位置信息输入到字节数组中
    QMimeData *mimeData = new QMimeData;   //创建QMimeData用来存放要移动的数据
    mimeData->setData("myimage/png",itemData);   //将字节数组放入QMimeData中,自定义HIME类型
    QDrag *drag = new QDrag(this);   //创建QDrag,用来移动数据
    drag->setMimeData(mimeData);
    drag->setPixmap(pixmap);   //设置移动过程中显示图片
    drag->setHotSpot(event->pos() - child->pos());
    QPixmap tempPixmap = pixmap;   //使原图片添加阴影
    QPainter painter;   //创建QPainter绘制QPixmap
    painter.begin(&tempPixmap);
    painter.fillRect(pixmap.rect(),QColor(127,127,127,127));
    painter.end();
    child->setPixmap(tempPixmap);   //移动图片过程中,让原图片添加一层黑色阴影
    if(drag->exec(Qt::CopyAction | Qt::MoveAction,Qt::CopyAction) == Qt::MoveAction)
    {
    
    
        child->close();   //如果是移动操作,拖放完成后关闭原标签
    }
    else
    {
    
    
        child->show();
        child->setPixmap(pixmap);   //如果是复制操作,拖放完成后显示原标签,并不再使用阴影
    }
}

void MainWindow::dragMoveEvent(QDragMoveEvent *event)   //拖动事件
{
    
    
    if(event->mimeData()->hasUrls())   //数据中是否包含URL(文本文件)
    {
    
    
        event->acceptProposedAction();
    }
    else if(event->mimeData()->hasFormat("myimage/png"))   //数据中是否包含自定义的MIME类型(图片)
    {
    
    
        event->setDropAction(myAction);   //设置移动或复制动作
        event->accept();
    }
    else
    {
    
    
        event->ignore();
    }
}

void MainWindow::dragEnterEvent(QDragEnterEvent *event)   //拖动进入事件
{
    
    
    if(event->mimeData()->hasUrls())
    {
    
    
        event->acceptProposedAction();
    }
    else if(event->mimeData()->hasFormat("myimage/png"))
    {
    
    
        event->setDropAction(myAction);
        event->accept();
    }
    else
    {
    
    
        event->ignore();
    }
}

void MainWindow::dropEvent(QDropEvent *event)   //放下事件
{
    
    
    if(event->mimeData()->hasUrls())   //文本文件拖入界面,TextEdit显示文件内容
    {
    
    
        QList <QUrl> urlList = event->mimeData()->urls();
        QString fileName = urlList.at(0).toLocalFile();
        //qDebug()<<"fileName:"<<fileName;
        if(!fileName.isEmpty())
        {
    
    
            QFile file(fileName);
            if(!file.open(QIODevice::ReadOnly))
            {
    
    
                return;
            }
            QTextStream in(&file);
            QString fileData = in.readAll().toLocal8Bit();   //防止中文乱码
            ui->textEdit->setText(fileData);
        }
    }
    else if(event->mimeData()->hasFormat("myimage/png"))   //对界面上图片进行拖动操作
    {
    
    
        QByteArray itemData = event->mimeData()->data("myimage/png");
        QDataStream dataStream(&itemData,QIODevice::ReadOnly);
        QPixmap pixmap;
        QPoint offset;
        dataStream >> pixmap >> offset;   //使用数据流将字节数组中的数据读入到QPixmap和QPoint变量中
        QLabel *newLabel = new QLabel(this);   //新建标签,根据图片大小设置标签的大小
        newLabel->setPixmap(pixmap);
        newLabel->resize(pixmap.size());
        newLabel->move(event->pos() - offset);   //将图片移动到放下的位置
        newLabel->show();
        newLabel->setAttribute(Qt::WA_DeleteOnClose);
        event->setDropAction(myAction);
        event->accept();
    }
    else
    {
    
    
        event->ignore();
    }
}

//修改图片拖动方式
void MainWindow::on_cb_copy_toggled(bool checked)
{
    
    
    if(checked)
    {
    
    
        myAction = Qt::CopyAction;   //复制操作
    }
    else
    {
    
    
        myAction = Qt::MoveAction;   //移动操作
    }
}

/*****************************打印操作Action对应槽函数*******************************/
void MainWindow::on_action_print_triggered()   //打印
{
    
    
    QPrinter printer;
    QPrintDialog dlg(&printer,this);
    if(ui->textEdit->textCursor().hasSelection())
    {
    
    
        dlg.addEnabledOption(QAbstractPrintDialog::PrintSelection);
    }
    if(dlg.exec() == QDialog::Accepted)
    {
    
    
        ui->textEdit->print(&printer);
    }
}

void MainWindow::on_action_preview_triggered()   //打印预览
{
    
    
    QPrinter printer;
    QPrintPreviewDialog preview(&printer,this);
    connect(&preview,&QPrintPreviewDialog::paintRequested,this,&MainWindow::printPreview);
    preview.exec();
}

void MainWindow::on_action_pdf_triggered()
{
    
    
    QString fileName = QFileDialog::getSaveFileName(this,"导出PDF文件",QString(),"*.pdf");
    if(!fileName.isEmpty())
    {
    
    
        if(QFileInfo(fileName).suffix().isEmpty())
        {
    
    
            fileName.append(".pdf");
        }
        QPrinter printer;
        printer.setOutputFormat(QPrinter::PdfFormat);
        printer.setOutputFileName(fileName);
        ui->textEdit->print(&printer);
    }
}

void MainWindow::printPreview(QPrinter *printer)   //生成pdf
{
    
    
    ui->textEdit->print(printer);
}

/*****************************将Widget界面打印为pdf*******************************/
void MainWindow::on_pb_printWidget_clicked()
{
    
    
    //界面背景色在ui中进行了样式表的修改
    QFile pdfFile("D:/QT/Project/my_Project/23_myDrag/test.pdf");   //输出文件名
    if(!pdfFile.open(QIODevice::WriteOnly))
    {
    
    
        QMessageBox::warning(this,"write File",QString("Cannot open file:\n%1").arg("D:/QT/Project/my_Project/23_myDrag/test.pdf"));
        return;
    }
    QPdfWriter *pdfWriter = new QPdfWriter(&pdfFile);       //实例化QPdfWriter 可以设置PDF文件的一些参数
    pdfWriter->setPageSize(QPageSize(QPageSize::A4));       //设置纸张为A4纸
    pdfWriter->setResolution(QPrinter::ScreenResolution);   //设置分辨率 屏幕分辨率 打印机分辨率 高分辨率
    pdfWriter->setPageMargins(QMarginsF(40,40,40,40));      //设置页边距 顺序是:左上右下

    QPixmap pixmap = QWidget::grab(ui->wg_photo->rect());   //获取widget的界面 控制你要抓取的widget

    QPainter painter_pixmap;
    painter_pixmap.begin(pdfWriter);
    QRect rect = painter_pixmap.viewport();
    int scale = rect.width()/pixmap.width();
    painter_pixmap.scale(scale,scale);       //图像缩放 不然图片太大或者太小都不好看
    painter_pixmap.drawPixmap(0,0,pixmap);   //画图
    painter_pixmap.end();
    QDesktopServices::openUrl(QUrl::fromLocalFile("D:/QT/Project/my_Project/23_myDrag/test.pdf"));   //打开生成的pdf
}

4.mainwindow.ui
在这里插入图片描述

六、下载链接

我的示例百度网盘链接:https://pan.baidu.com/s/1mytjXEhptve04L5PSUS0iA
提取码:xxcj


总结

本文主要讲述的是Qt中的拖放操作以及打印输出PDF文件,实现的功能也是比较简单的,本示例部分代码来自Qt Creator快速入门的原文,并将其中的功能进行了相应的结合,可以看到还引用了一些原文内容,更为详细的内容点都在示例代码中进行了相应的注释。(这是一本很好的书籍,原文讲述的也更加详细,适合初学者进行学习)


hello:
共同学习,共同进步,如果还有相关问题,可在评论区留言进行讨论。

学习书籍:【Qt Creator快速入门_霍亚飞编著】
参考博客:(十七)QT生成PDF文件

猜你喜欢

转载自blog.csdn.net/XCJandLL/article/details/129471981
今日推荐