上海响应式网站开发,wordpress整站生成html,甘肃建设厅网站执业注册中心,wordpress后台管理插件开发环境 Qt5.5.1、Qt Creator 3.5.1Qt实现pdf阅读器和MFC实现pdf阅读器#xff0c;其实原理都是差不多的。注意#xff1a;这个是MinGW版本的Qt#xff0c;也就是运行在GCC环境下的库#xff0c;里面只包含 *.dll 和 *.a 。如果是Vistual Studio版本的Qt #xff0c;那么…开发环境 Qt5.5.1、Qt Creator 3.5.1Qt实现pdf阅读器和MFC实现pdf阅读器其实原理都是差不多的。注意这个是MinGW版本的Qt也就是运行在GCC环境下的库里面只包含 *.dll 和 *.a 。如果是Vistual Studio版本的Qt 那么很不幸里面没有 *.lib文件。1、新建项目在项目的根目录新建一个“poppler”文件夹将poppler中qt5目录下的文件都丢进去(*.h头文件另外再将编译好的2个*.a文件和2个*.dll丢进去我这里多丢了实现的*.cc文件因为*.cc已经被编译成动态库了所以可以不用包含在代码中)2、在项目的pro配置文件中添加以下内容引用poppler的头文件和库文件(注意我这里是win32所以前面加了win32前缀)INCLUDEPATH $$PWD/popplerwin32: LIBS -L$$PWD/poppler -llibpopplerwin32: LIBS -L$$PWD/poppler -llibpoppler-qt53、创建pdf工具类(该类负责与poppler库做对接主要负责获取pdf的总页数和每页的图像)(1)pdfutils.h#ifndef PDFUTILS_H#define PDFUTILS_H#include #include #include #include #include poppler-qt5.hclass 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.hPdfUtils::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 0Poppler::Page* pdfPage document-page(pageNumber);if (pdfPage 0) {// ... error message ...return image;}// Generate a QImage of the rendered pageimage pdfPage-renderToImage(72, 72, -1, -1, -1, -1);if (image.isNull()) {// ... error message ...return image;}// after the usage, the page must be deleteddelete 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()delete pdfPage;delete document;}4、pdf显示类(pdf的右侧显示滚动条①拖动滚动条翻页 ②鼠标拖动pdf到最上或最底时翻页)注意本文省略了页面缓存如果是真实的项目的话本着严谨的态度请务必缓存页面(1)mypdfcanvas.h(继承父类的resizeEvent是为了 ①当pdf只有1页时不显示滚动条 ②当用户拖动缩放窗口时动态改变pdf显示尺寸)#ifndef MYPDFCANVAS_H#define MYPDFCANVAS_H#include #include #include #include #include #include #include #include #include #include pdfutils.hclass MyPdfCanvas : public QWidget{Q_OBJECTpublic: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返回falsebool setPath(QString pdfPath);//页码从0开始bool setPage(int pageNumber);//获取页数int getNumPages();float getScaledRatio();//显示裁剪后的图片bool showClipImage(int pageNumber, int x, int y, int w, int h);//取消显示裁剪图片,恢复正常显示void cancelClip();//实际获取的pdf宽高度QSize pdfActualSize;signals:void pageChanged(int currentPage);private:PdfUtils* pdfUtils;QString pdfPath;//最大缓存图片数量int maxCachedNum;//用来缓存pdf的每一个页面的图像(从0开始)QMap cachedImageMap;//用来存储已缓存的pdf页面序号(从0开始)// QQueue cachedPageQueue;//当前页码(从0开始)int currentPage;//总页码(从0开始)int numPages;bool isMouseDown;int lastMouseY;//当前pdf页面的图像QImage image;int imageX;int imageY;int imageMinY;//是否是剪裁状态bool isClip;//获取指定页的图片bool getPdfImage(int pageNumber);void reachTop();void reachBottom();//判断是否需要发送重定位签名框的信号void needLocateSignArea();};#endif // MYPDFCANVAS_H(2)pdfcanvas.cpp#include mypdfcanvas.hMyPdfCanvas::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(radio0) {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(pageNumber0 || 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(currentPage1);}}5、pdf及右侧滑块的装载容器(1)mainwindow.h#ifndef MAINWINDOW_H#define MAINWINDOW_H#include #include #include mypdfcanvas.h#define SCROLLBAR_WIDTH 30class MainWindow : public QMainWindow{Q_OBJECTpublic:explicit MainWindow(QWidget *parent 0);~MainWindow();void resizeEvent(QResizeEvent* e);bool setPdfPath(QString path);//重新调整pdf界面大小void resizeCanvas();void setWidgetVisible(bool pdfCanvasVisible, bool scrollbarVisible);public slots://当拖动pdf上滑到顶(或下滑到底)时触发该方法onPageChange(int currentPage);//当滑动条的滑块被滑动时会调用该方法onScrollBarValueChange();private:MyPdfCanvas *pdfCanvas;QScrollBar *scrollbar;};#endif // MAINWINDOW_H(2)mainwindow.cpp#include mainwindow.hMainWindow::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(numPages1) {scrollbar-setMaximum(numPages-1);scrollbar-setValue(0);}pdfCanvas-setPage(0);}resizeCanvas();return result;}void MainWindow::resizeCanvas() {qDebug()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 0setWidgetVisible(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、调用方式(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、实际效果图更新于2016-08-038、项目下载地址(使用当前最新的库poppler-0.45.0、poppler-0.39.0-win32)http://download.csdn.net/detail/chy555chy/9593364该项目在win7(Qt5.1)、win10(Qt5.7)下测试过了均可正常运行。下图为项目目录中的poppler文件夹(已经删去所有.cc文件)因为只用库和头文件Qt便可隐式调用dll中的函数了。更新于2016-08-22你们评论中遇到的加载库的时候就奔溃现象我还真没遇到过。下面是测试情况(1)当PDF文件未找到的情况会输出错误日志但是并不会崩溃。(2)当路径中包含”中文“且包含空格的情况poppler是可以正常打开的。以上这篇Qt 使用Poppler实现pdf阅读器的示例代码就是小编分享给大家的全部内容了希望能给大家一个参考也希望大家多多支持脚本之家。