Qt Widgets - テキスト・ビューア・プラグインの例
メニュー、ツールバー、ステータスバーを備えたウィジェットの例。
テキストビューアの例は、汎用のドキュメントビューアのプラグインの形で、QPlainTextEdit を中心に構築されたテキストエディタです。
TxtViewer
AbstractViewer
AbstractViewer
は、ビューワとメインウィンドウ間のインタラクションのフレームワークを提供します。このアプリケーションは、 、 、 のエントリーをメニューバーに提供します。File Edit Help
メイン・ウィンドウの下部にあるステータス・バーには、アプリケーションがユーザーに提供するメッセージが表示される。
最近開いたファイルはFile メニューに表示されます。この例では、一度に1つのファイルしかロードできません。
クラス定義
class TxtViewer : public ViewerInterface { Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.Qt.Examples.DocumentViewer.ViewerInterface" FILE "txtviewer.json") Q_INTERFACES(ViewerInterface)
クラス定義は、シグナルとスロットを処理するQ_OBJECT
マクロで始まります。その後に、プラグインの登録に必要なQ_PLUGIN_METADATA
とQ_INTERFACES
マクロが続きます。
このクラスはViewerInterface
を継承し、AbstractViewer
を継承します。ViewerInterface
クラスは、メイン・ウィンドウ・アプリケーションとプラグインの間のインターフェイスを提供するために使用されます。
QPluginLoader
また、プラグインのキーを含むtxtviewer.jsonファイルが必要です:
{ "Keys": [ "txtviewer" ] } public: TxtViewer(); ~TxtViewer() override; void init(QFile *file, QWidget *parent, QMainWindow *mainWindow) override; QString viewerName() const override { return QLatin1StringView(staticMetaObject.className()); }; QStringList supportedMimeTypes() const override; bool saveDocument() override { return saveFile(m_file.get()); }; bool saveDocumentAs() override; bool hasContent() const override; QByteArray saveState() const override { return {}; } bool restoreState(QByteArray &) override { return true; } bool supportsOverview() const override { return false; } #ifdef QT_DOCUMENTVIEWER_PRINTSUPPORT protected: void printDocument(QPrinter *printer) const override; #endif // QT_DOCUMENTVIEWER_PRINTSUPPORT private slots: void setupTxtUi(); private: void openFile(); bool saveFile (QFile *file); QPlainTextEdit *m_textEdit; };
このクラスはコンストラクタを定義していないので、引数のない標準コンストラクタしか利用できません。デストラクタを含む他のすべての関数は、ViewerInterface
の仮想関数を再実装しています。これらは、メイン・アプリケーションとデータ、情報、命令を交換するために使用されます。
設定を保存したり復元したりする機能は実装されていません。supportsOverview
関数は常にfalse
を返し、サムネイル・ナビゲーション用のウィンドウを表示する必要がないことをメイン・アプリケーションに伝えます。
TxtViewerクラスの実装
#include "txtviewer.h" #include <QFileDialog> #include <QMainWindow> #include <QMenu> #include <QMenuBar> #include <QPlainTextEdit> #include <QScrollBar> #include <QToolBar> #include <QGuiApplication> #include <QPainter> #include <QTextDocument> #include <QDir> #ifdef QT_DOCUMENTVIEWER_PRINTSUPPORT #include <QPrinter> #include <QPrintDialog> #endif using namespace Qt::StringLiterals; TxtViewer::TxtViewer() { connect(this, &AbstractViewer::uiInitialized, this, &TxtViewer::setupTxtUi); } TxtViewer::~TxtViewer() = default; void TxtViewer::init(QFile *file, QWidget *parent, QMainWindow *mainWindow) { AbstractViewer::init(file, new QPlainTextEdit(parent), mainWindow); m_textEdit = qobject_cast<QPlainTextEdit *>(widget()); } QStringList TxtViewer::supportedMimeTypes() const { return {"text/plain"_L1}; } void TxtViewer::setupTxtUi() { QMenu *editMenu = addMenu(tr("&Edit")); QToolBar *editToolBar = addToolBar(tr("Edit")); #if QT_CONFIG(clipboard) const QIcon cutIcon = QIcon::fromTheme(QIcon::ThemeIcon::EditCut, QIcon(":/demos/documentviewer/images/cut.png"_L1)); QAction *cutAct = new QAction(cutIcon, tr("Cu&t"), this); cutAct->setShortcuts(QKeySequence::Cut); cutAct->setStatusTip(tr("Cut the current selection's contents to the " "clipboard")); connect(cutAct, &QAction::triggered, m_textEdit, &QPlainTextEdit::cut); editMenu->addAction(cutAct); editToolBar->addAction(cutAct); const QIcon copyIcon = QIcon::fromTheme(QIcon::ThemeIcon::EditCopy, QIcon(":/demos/documentviewer/images/copy.png"_L1)); QAction *copyAct = new QAction(copyIcon, tr("&Copy"), this); copyAct->setShortcuts(QKeySequence::Copy); copyAct->setStatusTip(tr("Copy the current selection's contents to the " "clipboard")); connect(copyAct, &QAction::triggered, m_textEdit, &QPlainTextEdit::copy); editMenu->addAction(copyAct); editToolBar->addAction(copyAct); const QIcon pasteIcon = QIcon::fromTheme(QIcon::ThemeIcon::EditPaste, QIcon(":/demos/documentviewer/images/paste.png"_L1)); QAction *pasteAct = new QAction(pasteIcon, tr("&Paste"), this); pasteAct->setShortcuts(QKeySequence::Paste); pasteAct->setStatusTip(tr("Paste the clipboard's contents into the current " "selection")); connect(pasteAct, &QAction::triggered, m_textEdit, &QPlainTextEdit::paste); editMenu->addAction(pasteAct); editToolBar->addAction(pasteAct); menuBar()->addSeparator(); cutAct->setEnabled(false); copyAct->setEnabled(false); connect(m_textEdit, &QPlainTextEdit::copyAvailable, cutAct, &QAction::setEnabled); connect(m_textEdit, &QPlainTextEdit::copyAvailable, copyAct, &QAction::setEnabled); #endif // QT_CONFIG(clipboard) openFile(); connect(m_textEdit, &QPlainTextEdit::textChanged, this, [&](){ maybeSetPrintingEnabled(hasContent()); }); connect(m_uiAssets.back, &QAction::triggered, m_textEdit, [&](){ auto *bar = m_textEdit->verticalScrollBar(); if (bar->value() > bar->minimum()) bar->setValue(bar->value() - 1); }); connect(m_uiAssets.forward, &QAction::triggered, m_textEdit, [&](){ auto *bar = m_textEdit->verticalScrollBar(); if (bar->value() < bar->maximum()) bar->setValue(bar->value() + 1); }); }
TxtViewer
で使用されるすべてのクラスにアクセスするために必要なヘッダーファイルから始めます。また、txtviewer.h
もインクルードします。
QPrinter
と は、コンパイル・システムで印刷サポートが有効になっている場合にのみインクルードされます。QPrintDialog
なぜこれらのヘッダーをmainwindow.h
に含めないのか不思議に思うかもしれません。その理由は、別のヘッダーファイルから複数の大きなヘッダーをインクルードすると、パフォーマンスが急速に低下する可能性があるからです。しかし、他のヘッダー・ファイルから厳密に必要なヘッダー・ファイルだけをインクルードするのは、一般的に良い考えです。
実装は空のデストラクタで始まる。完全に省略することもできる。コード読者に、デストラクタでは何もする必要がないことを示すために、空で実装するのはよい習慣です。
デストラクタの後には、3つの引数をとる初期化関数が続く:
file
オープンして表示するファイルへのポインタ。parent
エディターが配置されるQWidget
。mainWindow
メニューとメニュー・バーが処理されるアプリケーションのメイン・ウィンドウへのポインタ。
この関数は、AbstractViwer
の基本 init 関数を呼び出します。新しいQPlainTextEdit ウィジェットが作成され、ファイルの内容が表示されます。そして、TxtViewer
のセットアップ関数がベース・クラスのuiInitializedシグナルに接続されます。
次の関数は、テキスト・ビューワがサポートする MIME タイプのリストを返します。プレーンテキストのみがサポートされている。
最後の初期化関数は、メニュー、アイコン、ボタン、ツールチップのようなビューア固有のUIコンポーネントを追加します。AbstractViewer
、これらのコンポーネントがアプリケーションのメインウィンドウから削除されるようにします。
void TxtViewer::openFile() { const QString type = tr("open"); if (!m_file->open(QFile::ReadOnly | QFile::Text)) { statusMessage(tr("Cannot read file %1:\n%2.") .arg(QDir::toNativeSeparators(m_file->fileName()), m_file->errorString()), type); return; } QTextStream in(m_file.get()); #ifndef QT_NO_CURSOR QGuiApplication::setOverrideCursor(Qt::WaitCursor); #endif if (!m_textEdit->toPlainText().isEmpty()) { m_textEdit->clear(); disablePrinting(); } m_textEdit->setPlainText(in.readAll()); #ifndef QT_NO_CURSOR QGuiApplication::restoreOverrideCursor(); #endif statusMessage(tr("File %1 loaded.") .arg(QDir::toNativeSeparators(m_file->fileName())), type); maybeEnablePrinting(); }
openFile
ファイルをオープンし、その内容を に転送し、オープンが成功したかどうかに応じて、ユーザーにステータス・メッセージを表示します。QPlainTextEdit
bool TxtViewer::hasContent() const { return (!m_textEdit->toPlainText().isEmpty()); } #ifdef QT_DOCUMENTVIEWER_PRINTSUPPORT void TxtViewer::printDocument(QPrinter *printer) const { if (!hasContent()) return; m_textEdit->print(printer); } #endif // QT_DOCUMENTVIEWER_PRINTSUPPORT bool TxtViewer::saveFile(QFile *file) { QString errorMessage; QGuiApplication::setOverrideCursor(Qt::WaitCursor); if (file->open(QFile::WriteOnly | QFile::Text)) { QTextStream out(file); out << m_textEdit->toPlainText(); } else { errorMessage = tr("Cannot open file %1 for writing:\n%2.") .arg(QDir::toNativeSeparators(file->fileName())), file->errorString(); } QGuiApplication::restoreOverrideCursor(); if (!errorMessage.isEmpty()) { statusMessage(errorMessage); return false; } statusMessage(tr("File %1 saved") .arg(QDir::toNativeSeparators(file->fileName()))); return true; } bool TxtViewer::saveDocumentAs() { QFileDialog dialog(mainWindow()); dialog.setWindowModality(Qt::WindowModal); dialog.setAcceptMode(QFileDialog::AcceptSave); if (dialog.exec() != QDialog::Accepted) return false; const QStringList &files = dialog.selectedFiles(); if (files.isEmpty()) return false; //newFile(); m_file->setFileName(files.first()); return saveDocument(); }
次に再実装された関数は、ビューア・プラグインが実際にコンテンツを表示しているかどうかをメイン・アプリケーションに伝えます。
コンパイルシステムで印刷がサポートされている場合、次のセクションでそれを実装する。
最後の2つの再実装は、現在のファイルを保存したり、新しい名前で保存したりする機能を提供する。
© 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.