Qt learning: custom drag and drop operation of text and pictures and interface printing and outputting PDF files


foreword

In my free time, I reviewed Mr. Huo Yafei’s Qt Creator quick start book, learned and summarized some of the knowledge about drag and drop operations and printing documents, and modified the sample code in the next part. Here, the relevant content will be recorded and displayed for everyone to learn , If there are any mistakes, everyone is welcome to criticize and correct.

Project effect
Please add a picture description


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

1. Drag and drop text files

Original content: For a practical application, I hope not only to open a file from the file menu, but also to drag the file on the desktop directly into the program interface to open it, just like dragging the source file into Qt Creator Open the same. Qt provides a powerful drag and drop mechanism, which can be viewed through the Drag and Drop keyword in the help. Drag and drop operations are divided into two operations: drag (Drag) and drop (Drop). When data is dragged, it will be stored as MIME (Multipurpose Internet Mail Extensions) type. In Qt, the QMimeData class is used to represent the MIME type data, and the QDrag class is used to complete the data transfer, and the whole drag-and-drop operation is completed in several mouse events and drag-and-drop events.

The following event handling functions are mainly rewritten here:

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

See the sample code below for details.

2. Custom drag and drop pictures

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

At this time, the following event handling functions are mainly rewritten:

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

See the sample code below for details.

3. Print the content of the TextEdit control as PDF

Original content: The Qt Print Support module in Qt5 provides support for printing. The simplest, you only need to use a QPrinter class and a print dialog QPrintDialog class to complete the document printing operation.

The project requires the Print Support module, and the following code needs to be added to the .pro:

QT += printsupport

The .h file in the project needs to contain the corresponding class name:

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

See the sample code below for details.

4. Print the Widget interface as PDF

Here, you can see that in my example, the background color style sheet of the corresponding Widget has been modified on the UI interface, and the PDF printed later also has the corresponding color.Please add a picture description

Five, example complete code

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
insert image description here

6. Download link

My sample Baidu network disk link: https://pan.baidu.com/s/1mytjXEhptve04L5PSUS0iA
Extraction code: xxcj


Summarize

This article mainly describes the drag-and-drop operation in Qt and the printout of PDF files. The functions implemented are relatively simple. Part of the code in this example comes from the original text of Qt Creator Quick Start, and the functions are combined accordingly. You can see Some original content is also quoted, and more detailed content points are annotated in the sample code. (This is a very good book, and the original text is more detailed, suitable for beginners to learn)


hello:
Learn together and make progress together. If you still have related questions, you can leave a message in the comment area for discussion.

Learning books: [Qt Creator Quick Start _ edited by Huo Yafei]
Reference blog: (17) QT generates PDF files

Guess you like

Origin blog.csdn.net/XCJandLL/article/details/129471981