QtPdf 开发总结

一、问题

在看论文的过程中,遇到外文版的论文,为了快速阅读,往往需要进行翻译工作,但在翻译过程中,会遇到几个困难,一是 很多pdf阅读器自带的翻译功能有限 ,翻译结果没有参考价值。二是手动在网站翻译的过程中,在复制pdf文本的时候,会出现 “断行”的现象,在翻译前,需要对断行进行处理,然后进行翻译。此过程往往会中断思路,导致论文阅读的效率很低。于是想自己开发一个论文阅读的软件。使在阅读过程中,能随时翻译论文,同时,能够添加不同的翻译引擎,从而提高翻译的可参考性。

二、功能设计

主要有如下的功能:

    文件(File)[mFile]-> 
        打开(Open)[mOpen];
        关闭(Close)[mClose];
        退出(Exit)(mExit);
    编辑(Edit)[mEdit]—> 
        查找(Search)[mSearch];
        选择(Select)[mSelectd];
        复制(copy)[mCopy];
        翻译(trans)[mTrans];
    设置(Config)[mConfig]-> 
        翻译key(App Key)[mAppKey];
        下页(Next Page)[mNextPage];
        前页(Previous Page)[mPrePage];
        首页(First Page)[mFirstPage];
        尾页(Last Page)[mLastPage];
    视图(View)[mView]-> 
        放大(Zoom Out)[mZoomOut];
        缩小 (Zoom In)[mZoomIn];
        适应页面(Fit Page)[mFitPage];
        适应窗口(Fit Windown)[mFitWindown];
        连续(Continuous)[mContinuous];
    关于(About)

三、开发准备

开始准备用Qt+poppler库写,但poppler编译太麻烦,后来发现这篇文章,QT自带PDF库使用方法_ydw93的博客-CSDN博客QT自带PDF库使用方法qt从5.14版本开始就自带有pdf模块 但是在include文件夹中却没有相应的头文件。我使用的是qt5.15.2版本,以下为在vs2019上的使用方法:下载qt源代码,将路径下文件夹复制到路径下,复制文件夹下,替换..\msvc2019_64\...https://blog.csdn.net/ydw93/article/details/111474550

参照其提供的方法,配置成了Qt自带Pdf的效果。

四、开发

1. 界面开发

界面开发中需要记录的有以下几点:

1.1.QSplitter的使用

splitter添加有两种方式:

一是使用设计器进行添加,在使用设计器的时候,需要同时选中要分割的控件,然后设计界面的 splitter选项都会显示为可用状态。

二是使用代码添加,可能看文档+网上搜索具体的使用方法。

1.2.connect使用注意问题

在连接信号与槽的时候,注意,发送与接收方都必须是已经实例化后对象指针,同时 ,一个连接对应一个实例对象。如果后期修改指针的指向,其连接也不会发生作用。

QtPdf 开发总结_第1张图片

 2.功能开发

 2.1 pdf文件加载与关闭

利用QFileDialog获得文件路径的情况下,利用QPdfDocument的load方法加载文件,在调用tabContext(在QTabWidget的基础上编写的一个类的对象)addDocTab中将doc添加到QPdfView中。

// mainwindow.cpp
void MainWindow::OpenDoc(){

    //打开一个文件对话框
    QString fileName = QFileDialog::getOpenFileName(this,tr("Open PDF"), ".", tr("PDF Files (*.pdf)"));
    if(!fileName.isNull())
    {
        QPdfDocument *doc = new QPdfDocument();
        doc->load(fileName);
        ui->tabContext->addDocTab(doc);
    }
}

//____________________________________________________________________________

//doctab.cpp

int doctab::addDocTab(QPdfDocument *pdfdoc)
{
    int index =-1;
    const auto documentTitle = pdfdoc->metaData(QPdfDocument::Title).toString();
    QString title = !documentTitle.isEmpty() ? documentTitle : QStringLiteral("PDF doc");
//    新建一个pdfview的控件
    QPdfView *pdfview = new QPdfView();

    pdfview->setDocument(pdfdoc);
    // 连续页面显示
    pdfview->setPageMode(QPdfView::MultiPage);
    //向内容tab添加页面
    index = QTabWidget::addTab(pdfview,title);

    return index;
}

文件在关闭时,首先要释放其相关的文档对象 ,pdfview对象,然后再关闭tabwidget中tab。

//MainWindow.cpp
void MainWindow::Close(int index)
{
    if(index != -1)
        ui->tabContext->tabClose(index);
    else
        QMessageBox::information(this, tr("提示"),tr("未打开文档."));
}


// doctab.cpp
//    关闭操作
void doctab::tabClose(int index)
{
    if(index !=-1)
    {
        //获得文档类对象的指针
        QPdfDocument *doc = getDoc(index);
        //关闭文档类
        doc->close();
        //从tabWidget中移除相应的页
        this->removeTab(index);
    }

}

2.2 文件导航功能

导航功能由QPdfPageNavigation 类实现,其具体的操作过程如下:

1. 其实例化的时候,不需要利用构造函数,需要获得一个由QpdfView的pageNavigation()方法返回的对象,也就是将QPdfPageNavigation与QPdfView对象绑定到一起。

2.其具体函数接口如下所示:

  • bool canGoToNextPage() const
    bool canGoToPreviousPage() const
    int currentPage() const
    QPdfDocument * document() const
    int pageCount() const
    void setCurrentPage(int page)
    void setDocument(QPdfDocument *document)

3.我的代码实现

void MainWindow::tabChanged(int index)
{
    if(index != -1)
    {
        //在页改变的情况下,需要改变选择器与导航对象的文档
        //新建一个标签页对象
        QPdfBookmarkModel *bookmarkModel = new QPdfBookmarkModel(this);
        //获取当前的文档对象
        m_document = ui->tabContext->getDoc(index);
        //获取pdf显示窗口的控件
        m_pdfView = ui->tabContext->getView(index);
        //为标签对象设置文档
        bookmarkModel->setDocument(m_document);
        //更新标签页控件
        ui->trBookMarkView->setModel(bookmarkModel);

//      设置导航器
        setPageNavigation(m_pdfView->pageNavigation());

//      设置缩放窗口
        setZoomOpt(m_pdfView);
    }
}


void MainWindow::setPageNavigation(QPdfPageNavigation *pageNavigation)
{
    m_pageNavi = pageNavigation;
//    在导航进来时,显示当前导航页数
    ui->le_PageNum->setText(QString::number(m_pageNavi->currentPage()+1));
    connect(ui->actionPrePage,&QAction::triggered,m_pageNavi,&QPdfPageNavigation::goToPreviousPage);
    connect(ui->tb_PrePage,&QToolButton::clicked,m_pageNavi,&QPdfPageNavigation::goToPreviousPage);
//    ui->tb_PrePage->setDefaultAction(ui->actionPrePage);

    connect(ui->actionNextPage,&QAction::triggered,m_pageNavi,&QPdfPageNavigation::goToNextPage);
    connect(ui->tb_NextPage,&QToolButton::clicked,m_pageNavi,&QPdfPageNavigation::goToNextPage);
//    ui->tb_NextPage->setDefaultAction(ui->actionNextPage);

    //第一页 菜单
    connect(ui->actionFirstPage,&QAction::triggered,m_pageNavi,[=](){
        m_pageNavi->setCurrentPage(0);
    });

   //第一页 工具按键
    connect(ui->tb_FirstPage,&QToolButton::clicked,m_pageNavi,[=](){
        m_pageNavi->setCurrentPage(0);
    });
   //最后一页 菜单
    connect(ui->actionLastPage,&QAction::triggered,m_pageNavi,[=](){
        m_pageNavi->setCurrentPage(m_pageNavi->pageCount()-1);
    });
    //最后一页 工具按钮
    connect(ui->tb_LastPage,&QToolButton::clicked,m_pageNavi,[=](){
        m_pageNavi->setCurrentPage(m_pageNavi->pageCount()-1);
    });
    //通过修改显示页面
    connect(ui->le_PageNum, &QLineEdit::editingFinished, this,[=](){
        const QString text = ui->le_PageNum->text();

        bool ok = false;
        const int pageNumber = text.toInt(&ok);

        if (!ok)
            ui->le_PageNum->setText(QString::number(this->m_pageNavi->currentPage()));
        else
            m_pageNavi->setCurrentPage(qBound(0, pageNumber - 1, this->m_pageNavi->pageCount() - 1));
    });
    //导航当前面改变时修改页面显示的页数
    connect(m_pageNavi,&QPdfPageNavigation::currentPageChanged,this,[=](int page){
        ui->le_PageNum->setText(QString::number(page+1));
    });

}

2.3 窗口缩放功能

由QPdfView实现,在进行缩放之前,首先要利用setZoomMode方法设置缩放模式,

  • QPdfView::FitToWidth:适合页面宽度
  • QPdfView::FitInView :适合窗口宽度
  • QPdfView::CustomZoom :自定义缩放

前两种缩放模式不需要进行缩放因子的设定,而后面一种,则需要利用

setZoomFactor();

方法进行缩放因子的设置。

void MainWindow::setZoomOpt(QPdfView *pdfView)
{
    m_pdfView = pdfView;
    //--- 菜单栏 ----
    // 适合页面
    connect(ui->actionFitPage,&QAction::triggered,m_pdfView,[=](){
        m_pdfView->setZoomFactor(1);
        m_pdfView->setZoomMode(QPdfView::FitInView);

    });
     // 适合窗口
    connect(ui->actionFitWindown,&QAction::triggered,m_pdfView,[=](){
        m_pdfView->setZoomFactor(1);
        m_pdfView->setZoomMode(QPdfView::FitToWidth);
    });

    //放大
    connect(ui->actionZoomOut,&QAction::triggered,m_pdfView,[=](){
        m_pdfView->setZoomMode(QPdfView::CustomZoom);
        m_pdfView->setZoomFactor(m_pdfView->zoomFactor()*2);
    });
    //缩小
    connect(ui->actionZoomIn,&QAction::triggered,m_pdfView,[=](){
        m_pdfView->setZoomMode(QPdfView::CustomZoom);
        m_pdfView->setZoomFactor(m_pdfView->zoomFactor()/2);
    });
    //--- 工具栏 ----
    // 适合页面
    connect(ui->tb_FitPage,&QToolButton::clicked,m_pdfView,[=](){
        m_pdfView->setZoomFactor(1);
        m_pdfView->setZoomMode(QPdfView::FitInView);
    });
    // 适合窗口
    connect(ui->tb_FitWindown,&QToolButton::clicked,m_pdfView,[=](){
        m_pdfView->setZoomFactor(1);
        m_pdfView->setZoomMode(QPdfView::FitToWidth);
    });
    //放大
    connect(ui->tb_ZoomOut,&QToolButton::clicked,m_pdfView,[=](){
        m_pdfView->setZoomMode(QPdfView::CustomZoom);
        m_pdfView->setZoomFactor(m_pdfView->zoomFactor()*2);
    });
    //缩小
    connect(ui->tb_ZoomIn,&QToolButton::clicked,m_pdfView,[=](){
        m_pdfView->setZoomMode(QPdfView::CustomZoom);
        m_pdfView->setZoomFactor(m_pdfView->zoomFactor()/2);
    });
}

五、后续

本来想将文本选择与翻译功能实现的,今天(2022年3月28日)在刷视屏的过程中,突然发现此工作已经有人做了,而且做的非常棒,因此,此工作结束。有需要的朋友可以参考 Zetro6 + Pdf翻译(链接上了不让发)。

你可能感兴趣的:(技术分享,学习笔记,qt5,个人开发,c++)