空闲时间回顾了一下霍亚飞老师的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); //放下事件
详细内容见后文示例代码。
原文内容:Qt5中的Qt Print Support模块提供了对打印的支持。最简单的,只需要使用一个QPrinter类和一个打印对话框QPrintDialog类就可以完成文档的打印操作。
项目需要Print Support模块,需要在.pro中添加如下代码:
QT += printsupport
项目中.h文件需要包含相应的类名:
#include
#include
#include
#include
...
详细内容见后文示例代码。
这边的话可以看到我的示例上,将相应的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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
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:"<
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
}
我的示例百度网盘链接:https://pan.baidu.com/s/1mytjXEhptve04L5PSUS0iA
提取码:xxcj
本文主要讲述的是Qt中的拖放操作以及打印输出PDF文件,实现的功能也是比较简单的,本示例部分代码来自Qt Creator快速入门的原文,并将其中的功能进行了相应的结合,可以看到还引用了一些原文内容,更为详细的内容点都在示例代码中进行了相应的注释。(这是一本很好的书籍,原文讲述的也更加详细,适合初学者进行学习)
hello:
共同学习,共同进步,如果还有相关问题,可在评论区留言进行讨论。
学习书籍:【Qt Creator快速入门_霍亚飞编著】
参考博客:(十七)QT生成PDF文件