Qt 学習: テキストと画像のカスタム ドラッグ アンド ドロップ操作と PDF ファイルの印刷と出力のインターフェイス


序文

空き時間に、Huo Yafei 氏の Qt Creator クイック スタート ブックを見直し、ドラッグ アンド ドロップ操作とドキュメントの印刷に関する知識を学習してまとめ、次のパートでサンプル コードを修正しました。誰もが学べるように記録および表示されます。間違いがある場合は、誰もが批判して修正することを歓迎します。

事業効果
画像の説明を追加してください


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

1. テキストファイルをドラッグ&ドロップ

元のコンテンツ: 実用的なアプリケーションとして、ファイル メニューからファイルを開くだけでなく、ソース ファイルを Qt Creator にドラッグするのと同じように、デスクトップ上のファイルをプログラム インターフェイスに直接ドラッグして開くこともできればと考えています。同じ。Qt は強力なドラッグ アンド ドロップ メカニズムを提供しており、ヘルプのドラッグ アンド ドロップ キーワードから確認できます。ドラッグ&ドロップの操作はドラッグ(Drag)とドロップ(Drop)の2つの操作に分かれており、データをドラッグした場合はMIME(MultiPurpose Internet Mail Extensions)形式で保存されます。Qt では、MIME タイプのデータを表すために QMimeData クラスが使用され、データ転送を完了するために QDrag クラスが使用されます。また、ドラッグ アンド ドロップ操作全体は、いくつかのマウス イベントとドラッグ アンド ドロップ イベントで完了します。

ここでは主に次のイベント処理関数が書き換えられます。

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

詳細については、以下のサンプルコードを参照してください。

2. カスタム画像のドラッグ アンド ドロップ

/*图片拖放步骤
//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);             //放下事件

詳細については、以下のサンプルコードを参照してください。

3. TextEdit コントロールのコンテンツを PDF として印刷します。

元のコンテンツ: Qt5 の Qt Print Support モジュールは、印刷のサポートを提供します。最も単純な方法では、QPrinter クラスと印刷ダイアログの QPrintDialog クラスを使用するだけでドキュメントの印刷操作を完了できます。

プロジェクトには印刷サポート モジュールが必要であり、次のコードを .pro に追加する必要があります。

QT += printsupport

プロジェクト内の .h ファイルには、対応するクラス名が含まれている必要があります。

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

詳細については、以下のサンプルコードを参照してください。

4. ウィジェットインターフェイスを PDF として印刷します

ここで、この例では、対応するウィジェットの背景色のスタイル シートが UI インターフェイス上で変更されており、後で印刷される PDF にも対応する色が適用されていることがわかります。画像の説明を追加してください

5、完全なコードの例

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.メインウィンドウ.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.メインウィンドウ.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.メインウィンドウ.ui
ここに画像の説明を挿入

6. ダウンロードリンク

私のサンプル Baidu ネットワーク ディスク リンク: https://pan.baidu.com/s/1mytjXEhptve04L5PSUS0iA
抽出コード: xxcj


要約する

この記事では、Qt でのドラッグ アンド ドロップ操作と PDF ファイルの印刷出力を主に説明します。実装された機能は比較的単純です。この例のコードの一部は、Qt Creator Quick Start の原文から取得し、機能を組み合わせていますサンプル コードでは、一部のオリジナルのコンテンツも引用されており、より詳細なコンテンツ ポイントに注釈が付けられていることがわかります。(これは非常に良い本であり、原文はより詳細であり、初心者が学ぶのに適しています)


こんにちは:
一緒に学び、一緒に進歩しましょう。関連する質問がまだある場合は、ディスカッションのためにコメント領域にメッセージを残すことができます。

学習書籍: [Qt Creator Quick Start _ 編集: Huo Yafei]
参考ブログ: (17) QT は PDF ファイルを生成します

おすすめ

転載: blog.csdn.net/XCJandLL/article/details/129471981