使用 Qt WebEngineView 在特定页面打开 PDF

Posted

技术标签:

【中文标题】使用 Qt WebEngineView 在特定页面打开 PDF【英文标题】:Open PDF at specific page with Qt WebEngineView 【发布时间】:2020-03-06 08:59:51 【问题描述】:

我想在我的 Qt 应用程序中创建一个简单的 PDF 查看器。一切正常,接受通过 URL 在特定页面打开 PDF。 例如:

url = "file:///D://Repo//PdfViewer//PdfViewer//test.pdf";

有效,但是

url = "file:///D://Repo//PdfViewer//PdfViewer//test.pdf#page=9";

剂量。 我在某处读到,chrome dosent 正式支持 #page=x 了,但我找不到如何解决这个问题的更多信息。 我在 Qt 的 Nano-Browser 示例中遇到了同样的问题。

PdfViewer::PdfViewer(const QString &pdf_path, QWidget *parent)
: QWidget(parent), m_View(new QWebEngineView(this)), m_ExitButton(new QPushButton())

  QUrl url = QUrl::fromLocalFile(pdf_path);

  m_View->settings()->setAttribute(QWebEngineSettings::PluginsEnabled, true);
  m_View->settings()->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, true);
  m_View->settings()->setAttribute(QWebEngineSettings::PdfViewerEnabled, true);
  m_View->load(url);

  m_ExitButton->setIcon(QIcon("Ok.png"));

  QVBoxLayout *layout = new QVBoxLayout();
  layout->addWidget(m_View);
  layout->addWidget(m_ExitButton);
  this->setLayout(layout);

  connect(m_ExitButton, &QPushButton::clicked, this, &PdfViewer::close);

我使用的是 Qt 5.13。

【问题讨论】:

我使用的是 5.13。 【参考方案1】:

Qt WebEngine使用chromium pdf查看器,所以分析the source code发现了实现页面移动的函数:window.viewer.viewport_.goToPage(page),可以使用QWebEnginePage的runjavascript()方法执行。

综合以上,解决办法是:

#include <QtWebEngineWidgets>

class PdfViewer: public QWidget
    Q_OBJECT
public:
    PdfViewer(const QString &pdf_path, QWidget *parent=nullptr)
        : QWidget(parent), m_View(new QWebEngineView(this)), m_ExitButton(new QPushButton())
    
        QUrl url = QUrl::fromLocalFile(pdf_path);

        m_View->settings()->setAttribute(QWebEngineSettings::PluginsEnabled, true);
        m_View->settings()->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, true);
        m_View->settings()->setAttribute(QWebEngineSettings::PdfViewerEnabled, true);
        m_View->load(url);

        m_ExitButton->setIcon(QIcon("Ok.png"));

        QVBoxLayout *layout = new QVBoxLayout();
        layout->addWidget(m_View);
        layout->addWidget(m_ExitButton);
        this->setLayout(layout);

        connect(m_ExitButton, &QPushButton::clicked, this, &PdfViewer::close);
        connect(m_View, &QWebEngineView::loadFinished, this, &PdfViewer::on_finished);
    
private Q_SLOTS:
    void on_finished(bool ok)
        if(ok)
            QTimer::singleShot(100, this, [this]() goToPage(9); );
        
    
private:
    void goToPage(int page)
        m_View->page()->runJavaScript(QString("window.viewer.viewport_.goToPage(%1)").arg(page));
    
    QWebEngineView *m_View;
    QPushButton *m_ExitButton;
;
int main(int argc, char *argv[])

    QApplication a(argc, argv);
    QString fileName = QFileDialog::getOpenFileName(nullptr,
                                                    QObject::tr("Open Image"),
                                                    QDir::homePath(),
                                                    QObject::tr("PDF Files (*.pdf)"));
    if(fileName.isEmpty())
        return 0;
    PdfViewer w(fileName);
    w.resize(640, 480);
    w.show();
    return a.exec();


#include "main.moc"

【讨论】:

【参考方案2】:

这是 QtWebEngine 中缺少的功能,但现在最新的 Qt 5.15 版本(或 Qt 6.2)支持它。 https://bugreports.qt.io/browse/QTBUG-86152

【讨论】:

以上是关于使用 Qt WebEngineView 在特定页面打开 PDF的主要内容,如果未能解决你的问题,请参考以下文章

Qt 5.7 WebEngineView、HTML5 音频/视频和 WebRTC

qt webengineview 加载本地资源方式

Qt/QML:WebEngineView 和 ScrollView

如何忽略 qml WebEngineView 上的证书错误

将鼠标点击发送到 WebEngineView Qt C++

QtCreator 4.1.0 不显示 MainWindow 表单编辑器的 webengineview(QT 5.7)