1. <ul id="0c1fb"></ul>

      <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
      <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区

      RELATEED CONSULTING
      相關(guān)咨詢
      選擇下列產(chǎn)品馬上在線溝通
      服務(wù)時間:8:30-17:00
      你可能遇到了下面的問題
      關(guān)閉右側(cè)工具欄

      新聞中心

      這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
      Qt使用Poppler實現(xiàn)pdf閱讀器的示例代碼

      開發(fā)環(huán)境 Qt5.5.1、Qt Creator 3.5.1

      在道外等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供網(wǎng)站設(shè)計、網(wǎng)站建設(shè) 網(wǎng)站設(shè)計制作按需策劃設(shè)計,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),成都品牌網(wǎng)站建設(shè),成都全網(wǎng)營銷,成都外貿(mào)網(wǎng)站建設(shè)公司,道外網(wǎng)站建設(shè)費用合理。

      Qt實現(xiàn)pdf閱讀器和MFC實現(xiàn)pdf閱讀器,其實原理都是差不多的。

      需要用到Poppler開源庫,下載地址如下 https://poppler.freedesktop.org/

      如果只是要在window的gcc下運行的話,可以下載已經(jīng)編譯好的庫 https://sourceforge.net/projects/poppler-win32/

      Qt 使用Poppler實現(xiàn)pdf閱讀器的示例代碼 

      注意:這個是MinGW版本的Qt,也就是運行在GCC環(huán)境下的庫,里面只包含 *.dll 和 *.a 。如果是Vistual Studio版本的Qt ,那么很不幸里面沒有 *.lib文件。

      1、新建項目,在項目的根目錄新建一個“poppler”文件夾,將poppler中qt5目錄下的文件都丟進去(*.h頭文件,另外再將編譯好的2個*.a文件和2個*.dll丟進去,我這里多丟了實現(xiàn)的*.cc文件,因為*.cc已經(jīng)被編譯成動態(tài)庫了,所以可以不用包含在代碼中)

      Qt 使用Poppler實現(xiàn)pdf閱讀器的示例代碼 

      2、在項目的pro配置文件中添加以下內(nèi)容,引用poppler的頭文件和庫文件(注意:我這里是win32,所以前面加了win32前綴)

      INCLUDEPATH += $$PWD/poppler
      win32: LIBS += -L$$PWD/poppler -llibpoppler
      win32: LIBS += -L$$PWD/poppler -llibpoppler-qt5

      3、創(chuàng)建pdf工具類(該類負(fù)責(zé)與poppler庫做對接,主要負(fù)責(zé)獲取pdf的總頁數(shù),和每頁的圖像)

      (1)pdfutils.h

      #ifndef PDFUTILS_H
      #define PDFUTILS_H
      #include 
      #include 
      #include 
      #include 
      #include "poppler-qt5.h"
      class PdfUtils
      {
      public:
        explicit PdfUtils(QString filePath);
        ~PdfUtils();
        //獲取指定頁pdf圖像(頁碼從0開始)
        QImage getPdfImage(int pageNumber);
        //獲取pdf總頁碼
        int getNumPages();
        //獲取pdf頁面大小
        QSize getPageSize();
      private:
        QString filePath;
        int numPages;
        QSize pageSize;
        void getPdfInfo();
      };
      #endif // PDFUTILS_H

      (2)pdfutils.cpp

      #include "pdfutils.h"
      PdfUtils::PdfUtils(QString filePath) {
        this->filePath = filePath;
        getPdfInfo();
      }
      PdfUtils::~PdfUtils() {
      }
      QImage PdfUtils::getPdfImage(int pageNumber) {
        QImage image;
        Poppler::Document* document = Poppler::Document::load(filePath);
        if (!document || document->isLocked()) {
          // ... error message ....
          delete document;
          return image;
        }
        // Document starts at page 0
        Poppler::Page* pdfPage = document->page(pageNumber);
        if (pdfPage == 0) {
          // ... error message ...
          return image;
        }
        // Generate a QImage of the rendered page
        image = pdfPage->renderToImage(72, 72, -1, -1, -1, -1);
        if (image.isNull()) {
          // ... error message ...
          return image;
        }
        // after the usage, the page must be deleted
        delete pdfPage;
        delete document;
        return image;
      }
      int PdfUtils::getNumPages() {
        return numPages;
      }
      QSize PdfUtils::getPageSize() {
        return pageSize;
      }
      void PdfUtils::getPdfInfo() {
        numPages = 0;
        Poppler::Document* document = Poppler::Document::load(filePath);
        if (!document || document->isLocked()) {
          // ... error message ....
          delete document;
          return;
        }
        numPages = document->numPages();
        Poppler::Page* pdfPage = document->page(0);
        pageSize = pdfPage->pageSize();
        qDebug()<

      4、pdf顯示類(pdf的右側(cè)顯示滾動條,①拖動滾動條翻頁 ②鼠標(biāo)拖動pdf到最上或最底時翻頁)

      注意:本文省略了頁面緩存,如果是真實的項目的話,本著嚴(yán)謹(jǐn)?shù)膽B(tài)度,請務(wù)必緩存頁面

      (1)mypdfcanvas.h(繼承父類的resizeEvent是為了 ①當(dāng)pdf只有1頁時不顯示滾動條 ②當(dāng)用戶拖動縮放窗口時動態(tài)改變pdf顯示尺寸)

      #ifndef MYPDFCANVAS_H
      #define MYPDFCANVAS_H
      #include 
      #include 
      #include 
      #include 
      #include 
      #include 
      #include 
      #include 
      #include 
      #include "pdfutils.h"
      class MyPdfCanvas : public QWidget
      {
        Q_OBJECT
      public:
        explicit MyPdfCanvas(QWidget *parent = 0);
        ~MyPdfCanvas();
        void resizeEvent(QResizeEvent* e);
        void paintEvent(QPaintEvent *e);
        void mousePressEvent(QMouseEvent *e);
        void mouseReleaseEvent(QMouseEvent *e);
        void mouseMoveEvent(QMouseEvent *e);
        void setMaxCachedNum(int maxCachedNum);
        //如果不能解析pdf返回false
        bool setPath(QString pdfPath);
        //頁碼從0開始
        bool setPage(int pageNumber);
        //獲取頁數(shù)
        int getNumPages();
        float getScaledRatio();
        //顯示裁剪后的圖片
        bool showClipImage(int pageNumber, int x, int y, int w, int h);
        //取消顯示裁剪圖片,恢復(fù)正常顯示
        void cancelClip();
        //實際獲取的pdf寬高度
        QSize pdfActualSize;
      signals:
        void pageChanged(int currentPage);
      private:
        PdfUtils* pdfUtils;
        QString pdfPath;
        //最大緩存圖片數(shù)量
        int maxCachedNum;
        //用來緩存pdf的每一個頁面的圖像(從0開始)
        QMap cachedImageMap;
        //用來存儲已緩存的pdf頁面序號(從0開始)
      //  QQueue cachedPageQueue;
        //當(dāng)前頁碼(從0開始)
        int currentPage;
        //總頁碼(從0開始)
        int numPages;
        bool isMouseDown;
        int lastMouseY;
        //當(dāng)前pdf頁面的圖像
        QImage image;
        int imageX;
        int imageY;
        int imageMinY;
        //是否是剪裁狀態(tài)
        bool isClip;
        //獲取指定頁的圖片
        bool getPdfImage(int pageNumber);
        void reachTop();
        void reachBottom();
        //判斷是否需要發(fā)送重定位簽名框的信號
        void needLocateSignArea();
      };
      #endif // MYPDFCANVAS_H

      (2)pdfcanvas.cpp

      #include "mypdfcanvas.h"
      MyPdfCanvas::MyPdfCanvas(QWidget *parent) : QWidget(parent) {
        pdfUtils = NULL;
        imageX = 0;
        imageY = 0;
        isClip = false;
        setAutoFillBackground(true);
      }
      MyPdfCanvas::~MyPdfCanvas() {
        if(pdfUtils != NULL) delete pdfUtils;
      }
      void MyPdfCanvas::resizeEvent(QResizeEvent *e) {
        image = this->cachedImageMap[currentPage];
        if(!image.isNull()) {
          float radio = (float)e->size().width()/(float)e->oldSize().width();
          int imageHeight = image.height()* e->size().width()/image.width();
          image = image.scaled(e->size().width(), imageHeight);
          if(imageHeight < this->height()) {
            imageY = (this->height()-imageHeight)/2;
            //如果圖片高度小于控件高度,則圖片居中
      //      imageMinY = imageY;
            imageMinY = 0;
            imageY = imageMinY;
          } else {
            if(radio>0) {
              imageY = (int)(imageY*radio);
              if(imageY > 0) {
                imageY = 0;
              }
            } else {
              imageY = 0;
            }
          }
        }
      }
      void MyPdfCanvas::paintEvent(QPaintEvent *e) {
        QPainter* painter = new QPainter(this);
        if(image.isNull()) {
          painter->fillRect(this->rect(), Qt::transparent);
          return;
        }
        painter->drawImage(0, imageY, image);
        delete painter;
      }
      void MyPdfCanvas::mousePressEvent(QMouseEvent *e) {
        isMouseDown = true;
        lastMouseY = e->y();
      }
      void MyPdfCanvas::mouseReleaseEvent(QMouseEvent *e){
        isMouseDown = false;
      }
      void MyPdfCanvas::mouseMoveEvent(QMouseEvent *e){
        if(!isMouseDown || image.isNull()) {
          return;
        }
        int distance = e->y() - lastMouseY;
        lastMouseY = e->y();
        imageY += distance;
        if(imageY > 0) {
          imageY = 0;
          reachTop();
          return;
        } else if(imageY < imageMinY) {
          imageY = imageMinY;
          reachBottom();
          return;
        }
        update();
      }
      void MyPdfCanvas::setMaxCachedNum(int maxCachedNum) {
        this->maxCachedNum = maxCachedNum;
      }
      bool MyPdfCanvas::setPath(QString pdfPath) {
        this->pdfPath = pdfPath;
        if(pdfUtils != NULL) delete pdfUtils;
        pdfUtils = new PdfUtils(pdfPath);
        numPages = pdfUtils->getNumPages();
        if(numPages > 0) {
          isClip = false;
          pdfActualSize = pdfUtils->getPageSize();
        }
        cachedImageMap.clear();
        currentPage = 0;
        imageY = 0;
        lastMouseY = 0;
        return numPages > 0;
      }
      bool MyPdfCanvas::setPage(int pageNumber) {
        if(!getPdfImage(pageNumber)) {
          return false;
        }
        isClip = false;
        isMouseDown = false;
        image = image.scaledToWidth(this->width());
        imageMinY = this->height() - image.height();
        if(image.height() < this->height()) {
          //如果圖片高度小于控件高度,則圖片居中
      //    imageMinY /= 2;
          imageMinY = 0;
          imageY = imageMinY;
        } else {
          imageY = 0;
        }
        update();
        return true;
      }
      int MyPdfCanvas::getNumPages() {
        return numPages;
      }
      float MyPdfCanvas::getScaledRatio() {
        int pdfWidth = pdfUtils->getPageSize().width();
        return (float)this->width()/(float)pdfWidth;
      }
      bool MyPdfCanvas::showClipImage(int pageNumber, int x, int y, int w, int h) {
        if(!getPdfImage(pageNumber)) {
          return false;
        }
        isClip = true;
        imageY = 0;
        image = image.copy(x, y, w, h).scaled(this->size());
        update();
      }
      void MyPdfCanvas::cancelClip() {
        isClip = false;
        setPage(currentPage);
      }
      bool MyPdfCanvas::getPdfImage(int pageNumber) {
        if(pageNumber<0 || pageNumber >= numPages) {
          return false;
        }
        if(cachedImageMap.contains(pageNumber)) {
          image = cachedImageMap.value(pageNumber);
        } else {
          image = pdfUtils->getPdfImage(pageNumber);
          if(!image.isNull()) {
            cachedImageMap[pageNumber] = image;
            pdfActualSize = image.size();
          }
        }
        if(image.isNull()) {
          return false;
        }
        currentPage = pageNumber;
        return true;
      }
      void MyPdfCanvas::reachTop() {
        if(currentPage > 0) {
          emit pageChanged(currentPage-1);
        }
      }
      void MyPdfCanvas::reachBottom() {
        if(currentPage < numPages-1) {
          emit pageChanged(currentPage+1);
        }
      }

      5、pdf及右側(cè)滑塊的裝載容器

      (1)mainwindow.h

      #ifndef MAINWINDOW_H
      #define MAINWINDOW_H
      #include 
      #include 
      #include "mypdfcanvas.h"
      #define SCROLLBAR_WIDTH 30
      class MainWindow : public QMainWindow
      {
        Q_OBJECT
      public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
        void resizeEvent(QResizeEvent* e);
        bool setPdfPath(QString path);
        //重新調(diào)整pdf界面大小
        void resizeCanvas();
        void setWidgetVisible(bool pdfCanvasVisible, bool scrollbarVisible);
      public slots:
        //當(dāng)拖動pdf上滑到頂(或下滑到底)時觸發(fā)該方法
        onPageChange(int currentPage);
        //當(dāng)滑動條的滑塊被滑動時,會調(diào)用該方法
        onScrollBarValueChange();
      private:
        MyPdfCanvas *pdfCanvas;
        QScrollBar *scrollbar;
      };
      #endif // MAINWINDOW_H

      (2)mainwindow.cpp

      #include "mainwindow.h"
      MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
        pdfCanvas = new MyPdfCanvas(this);
        scrollbar = new QScrollBar(Qt::Vertical, this);
        setWidgetVisible(false, false);
        connect(pdfCanvas, SIGNAL(pageChanged(int)), this, SLOT(onPageChange(int)));
        connect(scrollbar, SIGNAL(valueChanged(int)), this, SLOT(onScrollBarValueChange()));
      }
      MainWindow::~MainWindow() {
      }
      void MainWindow::resizeEvent(QResizeEvent *e) {
        resizeCanvas();
      }
      bool MainWindow::setPdfPath(QString path) {
        bool result = pdfCanvas->setPath(path);
        if(result) {
          int numPages = pdfCanvas->getNumPages();
          if(numPages>1) {
            scrollbar->setMaximum(numPages-1);
            scrollbar->setValue(0);
          }
          pdfCanvas->setPage(0);
        }
        resizeCanvas();
        return result;
      }
      void MainWindow::resizeCanvas() {
        qDebug()<<"resize "<rect()<<", "<rect();
        int numPages = pdfCanvas->getNumPages();
        if(numPages == 1) {
          pdfCanvas->setGeometry(this->rect());
          setWidgetVisible(true, false);
        } else if(numPages > 1) {
          pdfCanvas->setGeometry(0, 0, this->width()-SCROLLBAR_WIDTH, this->height());
          scrollbar->setGeometry(this->width()-SCROLLBAR_WIDTH, 0, this->width()-SCROLLBAR_WIDTH, this->height());
          setWidgetVisible(true, true);
        } else {
          //numPages <= 0
          setWidgetVisible(false, false);
        }
      }
      void MainWindow::setWidgetVisible(bool pdfCanvasVisible, bool scrollbarVisible) {
        pdfCanvas->setVisible(pdfCanvasVisible);
        scrollbar->setVisible(scrollbarVisible);
      }
      MainWindow::onPageChange(int currentPage) {
        pdfCanvas->setPage(currentPage);
      }
      MainWindow::onScrollBarValueChange() {
        pdfCanvas->setPage(scrollbar->value());
      }

      6、調(diào)用方式

      (1)main.cpp

      #include "mainwindow.h"
      #include 
      int main(int argc, char *argv[])
      {
        QApplication a(argc, argv);
        MainWindow w;
        w.resize(500, 500);
        w.show();
        QString path = "D://test.pdf";
        w.setPdfPath(path);
        w.setWindowTitle(path);
        return a.exec();
      }

      7、實際效果圖

      Qt 使用Poppler實現(xiàn)pdf閱讀器的示例代碼 

      更新于2016-08-03

      8、項目下載地址(使用當(dāng)前最新的庫poppler-0.45.0、poppler-0.39.0-win32)

      http://download.csdn.net/detail/chy555chy/9593364

      該項目在win7(Qt5.1)、win10(Qt5.7)下測試過了,均可正常運行。

      下圖為項目目錄中的poppler文件夾(已經(jīng)刪去所有.cc文件),因為只用庫和頭文件,Qt便可隱式調(diào)用dll中的函數(shù)了。

      Qt 使用Poppler實現(xiàn)pdf閱讀器的示例代碼 

      更新于2016-08-22

      你們評論中遇到的加載庫的時候就奔潰現(xiàn)象我還真沒遇到過。

      下面是測試情況:

      (1)當(dāng)PDF文件未找到的情況,會輸出錯誤日志,但是并不會崩潰。

      Qt 使用Poppler實現(xiàn)pdf閱讀器的示例代碼 

      (2)當(dāng)路徑中包含”中文“,且包含"空格"的情況,poppler是可以正常打開的。

      Qt 使用Poppler實現(xiàn)pdf閱讀器的示例代碼

      以上這篇Qt 使用Poppler實現(xiàn)pdf閱讀器的示例代碼就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持創(chuàng)新互聯(lián)。


      分享題目:Qt使用Poppler實現(xiàn)pdf閱讀器的示例代碼
      分享URL:http://www.ef60e0e.cn/article/pecgie.html
      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区
      1. <ul id="0c1fb"></ul>

        <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
        <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

        尚义县| 峡江县| 宁津县| 正镶白旗| 灵寿县| 聂拉木县| 博客| 金川县| 家居| 阿拉善左旗| 伊宁市| 松溪县| 稷山县| 东港市| 平安县| 昌宁县| 定南县| 青州市| 任丘市| 元江| 石渠县| 利辛县| 高陵县| 巧家县| 南郑县| 北流市| 黑山县| 吉林省| 霍林郭勒市| 荔波县| 福海县| 洛扎县| 绥阳县| 峨眉山市| 微山县| 江孜县| 洮南市| 清丰县| 金堂县| 陆良县| 洪江市|