批量图片合并生成PDF文档

05 11月
作者:cinjep|分类:代码开源

为解决大量图片合并为pdf文档而写,离线操作,保证数据安全,支持图片左键拖拽或右键菜单添加、调整顺序,图片预览、纸张大小设置、排版方向、边距设置、奇偶页打印边距、图片自动缩放、等常用功能。(文末有封装好的单文件版下载)

开发环境:windows10 LTSC Qt5.9 C++

运行环境:x86 Winows

mainwindow.cpp

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

#include <QFileDialog>
#include <QDebug>
#include <QMenu>
#include <QPoint>

#include <QListWidget>
#include <QCheckBox>

#include <QPixmap>
#include <QDebug>

#include <QDropEvent>
#include <QMimeData>
#include <QPainter>
#include <QPdfWriter>
#include <QProgressBar>
#include <QDesktopServices>
#include <QMessageBox>


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->imgListWidget->setDragDropMode(QAbstractItemView::InternalMove);
    ui->imgListWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);

    QObject::connect(ui->addImgBtn,SIGNAL(clicked(bool)),this,SLOT(onAddImg()));
    QObject::connect(ui->allImgChk,SIGNAL(stateChanged(int)),this,SLOT(onSelectAll()));
    QObject::connect(ui->delImgBtn,SIGNAL(clicked(bool)),this, SLOT(onDelItem()));

    QObject::connect(ui->imgListWidget,SIGNAL(customContextMenuRequested(const QPoint &)),this,SLOT(onCustomContextMenuRequested(const QPoint &)));
    QObject::connect(ui->imgListWidget,SIGNAL(itemSelectionChanged()),this,SLOT(itemSelectedCount()));
    QObject::connect(ui->imgListWidget,SIGNAL(itemSelectionChanged()),this,SLOT(viewImg()));
    QObject::connect(ui->imgListWidget,SIGNAL(itemClicked(QListWidgetItem*)),this,SLOT(viewImg()));
    QObject::connect(ui->selPdfBtn,SIGNAL(clicked(bool)),this,SLOT(pdfFileName()));
    QObject::connect(ui->creatPdfBtn,SIGNAL(clicked(bool)),this,SLOT(creatPdf()));
    QObject::connect(ui->aboutBtn,SIGNAL(clicked(bool)),this,SLOT(openAbout()));

    this->setAcceptDrops(true); //必须设置,不然无法接收拖放事件

    ui->imgListWidget->setContextMenuPolicy(Qt::CustomContextMenu);
    ui->outputTxt->setFocusPolicy(Qt::NoFocus);
    ui->imgInforLabel->setVisible(false);
    ui->hideLabel->setVisible(false);
}

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

void MainWindow::onAddImg()
{
    QStringList FileNames = QFileDialog::getOpenFileNames(this, QStringLiteral("选择图片文件!"), QStandardPaths::writableLocation(QStandardPaths::PicturesLocation),QStringLiteral("图片文件(*.png *.jpg *.bmp)"));
    int index=0,count=0;
    count = FileNames.count();
    for(index=0;index<=count-1;index++)
    {
        QListWidgetItem *item = new QListWidgetItem;
        item->setSizeHint(QSize(0,24));
        item->setText(QFileInfo(FileNames.at(index)).fileName());
        QString suf = QFileInfo(FileNames.at(index)).suffix();
        if(suf == "jpg" || suf == "JPG")
        {
            item->setIcon(QIcon(":/icon/jpg.png"));
        }
        if(suf == "png" || suf == "PNG")
        {
            item->setIcon(QIcon(":/icon/png.png"));
        }
        if(suf == "bmp" || suf == "BMP")
        {
            item->setIcon(QIcon(":/icon/bmp.png"));
        }
        ui->imgListWidget->addItem(item);
        item->setData(Qt::UserRole,QFileInfo(FileNames.at(index)).absoluteFilePath());

    }
    int itemCount = ui->imgListWidget->count();
    ui->countLabel->setText("图片数量:" + QString::number(itemCount));
    if(itemCount ==0){
        ui->imgInforLabel->setVisible(false);
    }
}

void MainWindow::onSelectAll()
{
    if(ui->allImgChk->isChecked())
    {
        ui->imgListWidget->selectAll();
    }
    else{
       ui->imgListWidget->clearSelection();
    }
}

//图片项右键
void MainWindow::onCustomContextMenuRequested(const QPoint &pos)
{
  QListWidgetItem* curItem = ui->imgListWidget->itemAt(pos);
      if( curItem == NULL )
          return;

      QIcon icon1 = QIcon(":/icon/up.png");
      QIcon icon2 = QIcon(":/icon/down.png");
      QIcon icon3 = QIcon(":/icon/delete.png");
      QMenu *popMenu = new QMenu(ui->imgListWidget);
      QAction *Menu1 = new QAction(icon1,"上移");
      QAction *Menu2 = new QAction(icon2,"下移");
      QAction *Menu3 = new QAction(icon3,"删除");
      popMenu->addAction(Menu1);
      popMenu->addAction(Menu2);
      popMenu->addAction(Menu3);
      connect(Menu1, SIGNAL(triggered(bool)), this, SLOT(itemUp()));
      connect(Menu2, SIGNAL(triggered(bool)), this, SLOT(itemDown()));
      connect(Menu3, SIGNAL(triggered(bool)), this, SLOT(onDelItem()));
      popMenu->exec( QCursor::pos());
}

//删除选中
void MainWindow::onDelItem()
{
    QList<QListWidgetItem*> list = ui->imgListWidget->selectedItems();
     if(list.size() == 0)
      return;
     for(int i=0;i<list.count();i++){
        QListWidgetItem *sel = list[i];
        if(sel){
            if(ui->hideLabel->text() == sel->data(Qt::UserRole).toString()){
                ui->showImgLabel->clear();
                ui->imgInforLabel->setText("");
                ui->imgInforLabel->setVisible(false);
            }
            ui->imgListWidget->removeItemWidget(sel);
            delete sel;
         }
     }
     int itemCount = ui->imgListWidget->count();
     ui->countLabel->setText("图片数量:" + QString::number(itemCount));
     if(itemCount ==0){
         ui->imgInforLabel->setVisible(false);
     }
}

void MainWindow::itemUp()
{
    QList<QListWidgetItem*> list = ui->imgListWidget->selectedItems();
     if(list.size() == 0)
     return;
     for(int i=0;i<list.count();i++){
         QListWidgetItem *sel = list[i];
         if (sel)
         {
             ui->imgListWidget->setCurrentItem(sel);
             int currentRow = ui->imgListWidget->currentRow();
             if (currentRow == -1)
               return;
             int arriveRow = currentRow - 1 < 0 ? 0 : currentRow - 1;
             ui->imgListWidget->insertItem(std::min(currentRow, arriveRow), ui->imgListWidget->takeItem(std::max(currentRow, arriveRow)));
             ui->imgListWidget->setCurrentRow(arriveRow);
         }
     }
    ui->imgListWidget->setCurrentItem(NULL);
}

void MainWindow::itemDown()
{
    QList<QListWidgetItem*> list = ui->imgListWidget->selectedItems();
     if(list.size() == 0)
     return;
     for(int i=0;i<list.count();i++){
         QListWidgetItem *sel = list[i];
         if (sel)
         {
             ui->imgListWidget->setCurrentItem(sel);
             int currentRow = ui->imgListWidget->currentRow();
             if (currentRow == -1)
               return;
             int arriveRow = currentRow + 1 >= ui->imgListWidget->count() ? ui->imgListWidget->count() - 1 : currentRow + 1;
             ui->imgListWidget->insertItem(std::min(currentRow, arriveRow), ui->imgListWidget->takeItem(std::max(currentRow, arriveRow)));
             ui->imgListWidget->setCurrentRow(arriveRow);
         }
     }
    ui->imgListWidget->setCurrentItem(NULL);
}

//当图片被全选后设置全选复选框的状态
void MainWindow::itemSelectedCount()
{
    QList<QListWidgetItem*> list = ui->imgListWidget->selectedItems();
    int itemCount = ui->imgListWidget->count();
    if(list.size() == itemCount){
        ui->allImgChk->setChecked(true);
    }
    else{
        ui->allImgChk->setChecked(false);
    }
}

//拖动文件到窗口,触发
void MainWindow::dragEnterEvent(QDragEnterEvent *event)
{
    if(event->mimeData()->hasUrls())
    {
        event->acceptProposedAction(); //事件数据中存在路径,方向事件
    }
    else
    {
        event->ignore();
    }
}



//拖动文件到窗口释放文件,触发
void MainWindow::dropEvent(QDropEvent *event)
{
    const QMimeData *mimeData = event->mimeData();
    if(mimeData->hasUrls())
    {
        QList<QUrl> urls = mimeData->urls();
        for(int i=0;i<urls.count();i++)
        {
            QListWidgetItem *item = new QListWidgetItem;
            item->setSizeHint(QSize(0,24));
            QString fileName = urls.at(i).toLocalFile();
            QFileInfo fileinfo = QFileInfo(fileName);
            item->setText(fileinfo.fileName());
            QString suf = fileinfo.suffix();
            if(suf == "jpg" || suf == "JPG")
            {
                item->setIcon(QIcon(":/icon/jpg.png"));
                ui->imgListWidget->addItem(item);
                item->setData(Qt::UserRole,fileName);
            }
            if(suf == "png" || suf == "PNG")
            {
                item->setIcon(QIcon(":/icon/png.png"));
                ui->imgListWidget->addItem(item);
                item->setData(Qt::UserRole,fileName);
            }
            if(suf == "bmp" || suf=="BMP")
            {
                item->setIcon(QIcon(":/icon/bmp.png"));
                ui->imgListWidget->addItem(item);
                item->setData(Qt::UserRole,fileName);
            }
        }
    }
    int itemCount = ui->imgListWidget->count();
    ui->countLabel->setText("图片数量:" + QString::number(itemCount));
    if(itemCount ==0){
        ui->imgInforLabel->setVisible(false);
    }
}

//图片预览
void MainWindow::viewImg()
{
    ui->showImgLabel->clear();
    ui->imgInforLabel->setText("");
    ui->imgInforLabel->setVisible(false);
    QList<QListWidgetItem*> list = ui->imgListWidget->selectedItems();
    int selectCount = list.size();
    int itemCount = ui->imgListWidget->count();
    if(selectCount == 0 || itemCount == 0)
    return;



    QListWidgetItem *currentItem = list[0];
    QString imgFullName = currentItem->data(Qt::UserRole).toString();

    QImage *img = new QImage();
    if(!img->load(imgFullName)){
        ui->showImgLabel->setText("预览失败");
    }
    ui->imgInforLabel->setVisible(true);
    QString imgInfor = "水平:"+QString::number(img->width())+"像素,宽度:"+QString::number(img->widthMM()/10)+"cm  垂直:"+QString::number(img->height())+"像素,高度: "+QString::number(img->heightMM()/10)+"cm" ;
    ui->imgInforLabel->setText(imgInfor);


    ui->hideLabel->setText(imgFullName);


    float sw = 420.0/img->width();
    float sh = 390.0/img->height();
    float scal =(sw>=1 && sh>=1)?1.0:sw>sh?sh:sw;
    QImage* imgScaled = new QImage;
    *imgScaled = img->scaled(img->width()*scal,img->height()*scal,Qt::KeepAspectRatio,Qt::SmoothTransformation);
    ui->showImgLabel->setPixmap(QPixmap::fromImage(*imgScaled));

    delete img;
    delete imgScaled;

}

void MainWindow::pdfFileName()
{
    QString fileName = QFileDialog::getSaveFileName(this,QStringLiteral("文件保存为"),QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation),QStringLiteral("*.pdf"));
    ui->outputTxt->setText(fileName);
}

void MainWindow::creatPdf()
{
    //纸张选择
    int paperIndex = ui->paperSizeCbox->currentIndex();
    //是否纸张横向
    bool isPaperLayout = ui->paperLayoutChk->isChecked();
    //是否双面
    bool isDoublePrint = ui->doublePrintChk->isChecked();
    //内容是否水平居中
    bool isHorizonCenter = ui->horizonChk->isChecked();
    //内容是否垂直居中
    bool isVerticalCenter = ui->verticalChk->isChecked();
    //图片自动缩放
    bool isAutoScal = ui->autoScalChk->isChecked();
    //上边距
    float topMargin = ui->topSpinBox->value()*10;
    //下边距
    float bottomMargin = ui->bottomSpinBox->value()*10;
    //左边距
    float leftMargin = ui->leftSpinBox->value()*10;
    //右边距
    float rightMargin = ui->rightSpinBox->value()*10;
    //pdf输出路径
    QString pdfpath = ui->outputTxt->text();

    //生成后是否打开,默认为true
    bool isView = ui->viewPdfChk->isChecked();

    QFile pdfFile(pdfpath);
    pdfFile.open(QIODevice::WriteOnly);
    QPdfWriter *pWriter = new QPdfWriter(&pdfFile);
    pWriter->setResolution(300);
    pWriter->setPageMargins(QMarginsF(leftMargin, topMargin, rightMargin, bottomMargin),QPageLayout::Millimeter);
    //定义纸张大小,像素
    int pageSizeWidth = 0;
    int pageSizeHeight = 0;
    //定义图像大小,像素
    int imgSizeWidth = 0;
    int imgSizeHeight = 0;
    //定义图像可用区域大小
    int areaWidht = 0;
    int areaHeight = 0;

    //纸张大小
    switch(paperIndex)
    {
        case 0:
            pWriter->setPageSize(QPagedPaintDevice::Custom);
            pageSizeWidth = isPaperLayout?3508:2479;
            pageSizeHeight = isPaperLayout?2479:3508;
            break;
        case 1:
            pWriter->setPageSize(QPagedPaintDevice::Custom);
            pageSizeWidth = isPaperLayout?3071:2185;
            pageSizeHeight = isPaperLayout?2185:3071;
            break;
    }
    //是否横向
    if(isPaperLayout){
        pWriter->setPageOrientation(QPageLayout::Landscape);
    }
    else{
        pWriter->setPageOrientation(QPageLayout::Portrait);
    }

    //可用图像区域大小
    areaWidht = pageSizeWidth - (leftMargin+rightMargin)/25.4*300;
    areaHeight = pageSizeHeight - (topMargin+bottomMargin)/25.4*300;

    QMessageBox msgBox;
    msgBox.setWindowTitle("操作提示");

    //判断图像数量是否为0
    int itemCount = ui->imgListWidget->count();
    if(itemCount == 0){
        msgBox.setInformativeText("请添加用于生成PDF文件的图像!");
        msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
        msgBox.setButtonText(QMessageBox::Ok, QStringLiteral("确定"));
        msgBox.setButtonText(QMessageBox::Cancel, QStringLiteral("取消"));
        int reply = msgBox.exec();
        if(reply == QMessageBox::Ok){
            this->onAddImg();
            return;
        }
        return;
    }

    //判断文件保存路径是否为空
    if(ui->outputTxt->text().isEmpty()){
        msgBox.setInformativeText("请设置PDF文件保存路径!");
        msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
        msgBox.setButtonText(QMessageBox::Ok, QStringLiteral("确定"));
        msgBox.setButtonText(QMessageBox::Cancel, QStringLiteral("取消"));
        int reply = msgBox.exec();
        if(reply == QMessageBox::Ok)
        {
            this->pdfFileName();
            return;
        }
    }

    QPainter *pPainter = new QPainter(pWriter);
    QProgressBar *pProgressBar = new QProgressBar(this);
    pProgressBar->setOrientation(Qt::Horizontal);  // 水平方向
    pProgressBar->setMinimum(1);  // 最小值
    pProgressBar->setMaximum(100);  // 最大值
    pProgressBar->setMaximumHeight(15);
    pProgressBar->setMinimumWidth(60);
    pProgressBar->setVisible(true);
    ui->statusbar->addPermanentWidget(pProgressBar,1);

    for(int i = 0; i<itemCount;i++)
    {
        if(i>0){
            if(isDoublePrint){
                float tmp;
                tmp = leftMargin;
                leftMargin = rightMargin;
                rightMargin = tmp;
            }
            pWriter->setPageMargins(QMarginsF(leftMargin, topMargin, rightMargin, bottomMargin),QPageLayout::Millimeter);
            pWriter->newPage();
        }

        QString imgFullName = ui->imgListWidget->item(i)->data(Qt::UserRole).toString();
        QImage *image = new QImage;
        image->load(imgFullName);

        imgSizeWidth = image->width();   //获取图片宽度,像素
        imgSizeHeight = image->height(); //获取图片高度,像素

        ////////////////////////////////////////////////////////////////////////////////////////
        if(isAutoScal && imgSizeWidth < areaWidht && imgSizeHeight < areaHeight){
            float sW = (float)areaWidht/imgSizeWidth;
            float sH = (float)areaHeight/imgSizeHeight;
            float scal = (sW < sH) ? sW : sH;
            *image = image->scaled((int)(imgSizeWidth*scal),(int)(imgSizeHeight*scal),Qt::KeepAspectRatio,Qt::SmoothTransformation);
            imgSizeWidth = image->width();   //获取图片宽度,像素
            imgSizeHeight = image->height(); //获取图片高度,像素
        }
        //////////////////////////////////////////////////////////////////////////////////////////

        if(imgSizeWidth > areaWidht || imgSizeHeight > areaHeight){
            float sw = (float)areaWidht/imgSizeWidth;
            float sh = (float)areaHeight/imgSizeHeight;
            float scal =(sw>=1.0 && sh>=1.0)?1.0:sw>sh?sh:sw;
            *image = image->scaled((int)(imgSizeWidth*scal),(int)(imgSizeHeight*scal),Qt::KeepAspectRatio,Qt::SmoothTransformation);
            imgSizeWidth = image->width();   //获取图片宽度,像素
            imgSizeHeight = image->height(); //获取图片高度,像素
        }

        int top = 0;
        int left = 0;

        if(isHorizonCenter && imgSizeWidth<areaWidht){
            left = (int)(areaWidht-imgSizeWidth)/2;
        }

        if(isVerticalCenter && imgSizeHeight<areaHeight){
            top = (areaHeight-imgSizeHeight)/2;
        }
        pPainter->drawImage(QRect(left, top, image->width(), image->height()),*image);
        pProgressBar->setValue(i);
        delete image;
    }
    pProgressBar->setVisible(false);
    pPainter->end();


    delete pProgressBar;


    delete pPainter;
    delete pWriter;
    pdfFile.close();

    if(isView){
        QDesktopServices::openUrl(QUrl::fromLocalFile(pdfpath));
    }
}

void MainWindow::openAbout()
{
    about *a = new about(this);
    a->setModal(false);
    a->show();
}


mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "about.h"

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

    void dragEnterEvent(QDragEnterEvent*event) Q_DECL_OVERRIDE;
    void dropEvent(QDropEvent *event) Q_DECL_OVERRIDE;

private slots:
    void onAddImg();
    void onSelectAll();
    void onCustomContextMenuRequested(const QPoint &);
    void onDelItem();
    void itemUp();
    void itemDown();
    void itemSelectedCount();
    void viewImg();
    void pdfFileName();
    void creatPdf();
    void openAbout();

private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

imgTopdf_单文件版下载

浏览144
返回
目录
返回
首页
视频直播客户端 课堂随机点名应用