PDF Single Page Viewer Example | Qt PDF (original) (raw)
A Qt Quick PDF viewer that views one page at a time.
PDF Single Page Viewer Example demonstrates how to use the PdfScrollablePageView component to render PDF documents and search for text in them.
Running the Example
To run the example from Qt Creator, open the Welcome mode and select the example from Examples. For more information, see Qt Creator: Tutorial: Build and run.
Creating the Main Window
Instantiate an ApplicationWindow, bind its title to the title of the PDF document, and create a toolbar:
ApplicationWindow { id: root width: 800 height: 1024 color: "lightgrey" title: document.title visible: true required property url source // for main.cpp property real scaleStep: Math.sqrt(2)
header: ToolBar {
[RowLayout](qml-qtquick-layouts-rowlayout.html) {
anchors.fill: parent
anchors.rightMargin: 6
The toolbar has buttons for most of the common actions, plus a SpinBox to show and control the current page number:
[ToolButton](qml-qtquick-controls-toolbutton.html) {
action: Action {
shortcut: StandardKey.Open
icon.source: "qrc:/singlepage/resources/document-open.svg"
onTriggered: fileDialog.open()
}
}
[ToolButton](qml-qtquick-controls-toolbutton.html) {
action: Action {
shortcut: StandardKey.ZoomIn
enabled: view.sourceSize.width < 10000
icon.source: "qrc:/singlepage/resources/zoom-in.svg"
onTriggered: view.renderScale *= root.scaleStep
}
}
[ToolButton](qml-qtquick-controls-toolbutton.html) {
action: Action {
shortcut: StandardKey.ZoomOut
...
[SpinBox](qml-qtquick-controls-spinbox.html) {
id: currentPageSB
from: 1
to: document.pageCount
editable: true
value: view.currentPage + 1
...
Add dialogs to inform the user when an error occurs and to prompt for a password if required:
[Dialog](qml-qtquick-controls-dialog.html) {
id: passwordDialog
title: "Password"
standardButtons: Dialog.Ok | Dialog.Cancel
modal: true
closePolicy: Popup.CloseOnEscape
anchors.centerIn: parent
width: 300
contentItem: TextField {
id: passwordField
placeholderText: qsTr("Please provide the password")
echoMode: TextInput.Password
width: parent.width
onAccepted: passwordDialog.accept()
}
onOpened: function() { passwordField.forceActiveFocus() }
onAccepted: document.password = passwordField.text
}
[Dialog](qml-qtquick-controls-dialog.html) {
id: errorDialog
title: "Error loading " + document.source
standardButtons: Dialog.Close
modal: true
closePolicy: Popup.CloseOnEscape
anchors.centerIn: parent
width: 300
visible: document.status === PdfDocument.Error
contentItem: Label {
id: errorField
text: document.error
}
}
Add the main component, PdfScrollablePageView:
[PdfScrollablePageView](qml-qtquick-pdf-pdfscrollablepageview.html) {
id: view
anchors.fill: parent
anchors.leftMargin: searchDrawer.position * searchDrawer.width
document: PdfDocument {
id: document
source: Qt.resolvedUrl(root.source)
onPasswordRequired: passwordDialog.open()
}
searchString: searchField.text
}
A Drawer holds a ListView to show search results from the searchModel:
[Drawer](qml-qtquick-controls-drawer.html) {
id: searchDrawer
edge: Qt.LeftEdge
// modal: false // dim: false // commented out as workaround for QTBUG-83859 width: 300 y: root.header.height height: view.height clip: true ListView { id: searchResultsList anchors.fill: parent anchors.margins: 2 model: view.searchModel currentIndex: view.searchModel.currentResult ScrollBar.vertical: ScrollBar { } delegate: ItemDelegate { id: resultDelegate required property int index required property int page required property string contextBefore required property string contextAfter width: parent ? parent.width : 0 RowLayout { anchors.fill: parent spacing: 0 Label { text: "Page " + (resultDelegate.page + 1) + ": " } Label { text: resultDelegate.contextBefore elide: Text.ElideLeft horizontalAlignment: Text.AlignRight Layout.fillWidth: true Layout.preferredWidth: parent.width / 2 } Label { font.bold: true text: view.searchString width: implicitWidth } Label { text: resultDelegate.contextAfter elide: Text.ElideRight Layout.fillWidth: true Layout.preferredWidth: parent.width / 2 } } highlighted: ListView.isCurrentItem onClicked: view.searchModel.currentResult = resultDelegate.index } } }
Finally, add a second toolbar as a footer, to hold the search field, search up/down buttons and some status information:
footer: ToolBar {
height: footerRow.implicitHeight
[RowLayout](qml-qtquick-layouts-rowlayout.html) {
id: footerRow
anchors.fill: parent
[ToolButton](qml-qtquick-controls-toolbutton.html) {
action: Action {
icon.source: "qrc:/singlepage/resources/go-up-search.svg"
shortcut: StandardKey.FindPrevious
enabled: view.searchModel.count > 0
onTriggered: view.searchBack()
}
ToolTip.visible: enabled && hovered
ToolTip.delay: 2000
ToolTip.text: "find previous"
}
[TextField](qml-qtquick-controls-textfield.html) {
id: searchField
placeholderText: "search"
Layout.minimumWidth: 150
Layout.maximumWidth: 300
Layout.fillWidth: true
onAccepted: searchDrawer.open()
[Image](qml-qtquick-image.html) {
visible: searchField.text !== ""
source: "qrc:/singlepage/resources/edit-clear.svg"
anchors {
right: parent.right
top: parent.top
bottom: parent.bottom
margins: 3
rightMargin: 5
}
[TapHandler](qml-qtquick-taphandler.html) {
onTapped: searchField.clear()
}
}
}
[ToolButton](qml-qtquick-controls-toolbutton.html) {
action: Action {
icon.source: "qrc:/singlepage/resources/go-down-search.svg"
shortcut: StandardKey.FindNext
enabled: view.searchModel.count > 0
onTriggered: view.searchForward()
}
ToolTip.visible: enabled && hovered
ToolTip.delay: 2000
ToolTip.text: "find next"
}
[Label](qml-qtquick-controls-label.html) {
Layout.fillWidth: true
property size implicitPointSize: document.pagePointSize(view.currentPage)
text: "page " + (view.currentPage + 1) + " of " + document.pageCount +
" scale " + view.renderScale.toFixed(2) +
" original " + implicitPointSize.width.toFixed(1) + "x" + implicitPointSize.height.toFixed(1) + "pts"
visible: document.status === PdfDocument.Ready
}
}
}
}
Files and Attributions
See also PDF Multipage Viewer Example.
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.