PDF シングルページビューアの例

一度に1ページを表示するQt Quick PDFビューア。

PDF Single Page Viewer Exampleは、PdfScrollablePageView コンポーネントを使用して PDF 文書をレンダリングし、その中のテキストを検索する方法を示します。

サンプルを実行する

Qt Creator からサンプルを実行するには、Welcome モードを開き、Examples からサンプルを選択します。詳しくは、Building and Running an Example を参照してください。

メインウィンドウの作成

ApplicationWindow をインスタンス化し、そのタイトルを PDF 文書のタイトルにバインドし、ツールバーを作成します:

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 {
            anchors.fill: parent
            anchors.rightMargin: 6

こ のツールバーには、 一般的な操作のほ と ん ど に対応す る ボ タ ン と 、 カ レ ン ト ページ番号を表示 ・ 制御す る ためのSpinBox があ り ます:

            ToolButton {
                action: Action {
                    shortcut: StandardKey.Open
                    icon.source: "qrc:/singlepage/resources/document-open.svg"
                    onTriggered: fileDialog.open()
                }
            }
            ToolButton {
                action: Action {
                    shortcut: StandardKey.ZoomIn
                    enabled: view.sourceSize.width < 10000
                    icon.source: "qrc:/singlepage/resources/zoom-in.svg"
                    onTriggered: view.renderScale *= root.scaleStep
                }
            }
            ToolButton {
                action: Action {
                    shortcut: StandardKey.ZoomOut
    ...
            SpinBox {
                id: currentPageSB
                from: 1
                to: document.pageCount
                editable: true
                value: view.currentPage + 1
    ...

エ ラ ーが発生 し た と き にユーザーに通知 し 、 必要に応 じ てパ ス ワー ド を入力す る よ う 求めるダ イ ア ロ グ を追加 し ます:

    Dialog {
        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 {
        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
        }
    }

メインコンポーネントのPdfScrollablePageView

    PdfScrollablePageView {
        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
    }

DrawerListView を保持し、searchModel からの検索結果を表示する:

    Drawer {
        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
            }
        }
    }

最後に、フッターとして2つ目のツールバーを追加し、検索フィールド、検索アップ/ダウンボタン、ステータス情報を表示する:

    footer: ToolBar {
        height: footerRow.implicitHeight
        RowLayout {
            id: footerRow
            anchors.fill: parent
            ToolButton {
                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 {
                id: searchField
                placeholderText: "search"
                Layout.minimumWidth: 150
                Layout.maximumWidth: 300
                Layout.fillWidth: true
                onAccepted: searchDrawer.open()
                Image {
                    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 {
                        onTapped: searchField.clear()
                    }
                }
            }
            ToolButton {
                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 {
                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
            }
        }
    }
}

ファイルと帰属

サンプルプロジェクト @ code.qt.io

PDF Multipage Viewer Exampleもご覧ください

©2024 The Qt Company Ltd. 本書に含まれるドキュメントの著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。