Dokument-Viewer
Eine Widgets-Anwendung zum Anzeigen und Drucken von JSON-, Text- und PDF-Dateien.
Document Viewer demonstriert die Verwendung einer QMainWindow mit statischen und dynamischen Symbolleisten, Menüs und Aktionen. Außerdem werden die folgenden Funktionen in Widget-basierten Anwendungen demonstriert:
- Verwendung von QSettings zum Abfragen und Speichern von Benutzereinstellungen und zum Verwalten des Verlaufs zuvor geöffneter Dateien.
- Steuerung des Cursor-Verhaltens, wenn der Mauszeiger über Widgets bewegt wird.
- Erstellen von dynamisch geladenen Plugins.
Erstellen einer Anwendung und des Hauptfensters
Die Anwendung und ihr Hauptfenster werden in main.cpp
erstellt. Die Funktion main() verwendet QCommandLineParser, um Befehlszeilenargumente zu verarbeiten - help, version und ein optionales Positionsargument, file. Wenn der Benutzer beim Starten der Anwendung einen Pfad zu einer Datei angegeben hat, wird diese im Hauptfenster geöffnet:
int main(int argc, char *argv[]) { QApplication app(argc, argv); QCoreApplication::setOrganizationName("QtProject"_L1); QCoreApplication::setApplicationName("DocumentViewer"_L1); QCoreApplication::setApplicationVersion("1.0"_L1); QCommandLineParser parser; parser.setApplicationDescription(QApplication::translate("main", "A viewer for JSON, PDF and text files")); parser.addHelpOption(); parser.addVersionOption(); parser.addPositionalArgument("File"_L1, QApplication::translate("main", "JSON, PDF or text file to open")); parser.process(app); const QStringList &positionalArguments = parser.positionalArguments(); const QString &fileName = (positionalArguments.count() > 0) ? positionalArguments.at(0) : QString(); MainWindow w; // Start application only if plugins are available if (!w.hasPlugins()) { QMessageBox::critical(nullptr, "No viewer plugins found"_L1, "Unable to load viewer plugins. Exiting application."_L1); return 1; } w.show(); if (!fileName.isEmpty()) w.openFile(fileName); return app.exec(); }
MainWindow-Klasse
Die Klasse MainWindow
bietet einen Anwendungsbildschirm mit Menüs, Aktionen und einer Symbolleiste. Sie kann eine Datei öffnen und erkennt automatisch ihren Inhaltstyp. Sie verwaltet außerdem eine Liste der zuvor geöffneten Dateien und verwendet QSettings, um die Einstellungen zu speichern und beim Start neu zu laden. Das MainWindow erstellt einen geeigneten Betrachter für die geöffnete Datei, basierend auf ihrem Inhaltstyp, und bietet Unterstützung für das Drucken eines Dokuments.
Der Konstruktor von MainWindow initialisiert die in Qt Designer erstellte Benutzeroberfläche. Die Datei mainwindow.ui
bietet auf der linken Seite eine QTabWidget, die Lesezeichen und Miniaturansichten anzeigt. Auf der rechten Seite befindet sich ein QScrollArea zur Anzeige des Dateiinhalts.
ViewerFactory-Klasse
Die Klasse ViewerFactory
verwaltet Viewer für bekannte Dateitypen. Diese Betrachter werden als Plugins implementiert. Wenn eine Instanz einer ViewerFactory erstellt wird, werden Zeiger auf den Ansichtsbereich und das Hauptfenster an den Konstruktor übergeben:
m_factory.reset(new ViewerFactory(ui->viewArea, this));
ViewerFactory lädt alle verfügbaren Plugins bei der Erstellung. Sie bietet eine öffentliche API um die geladenen Plugins, ihre Namen und unterstützten MIME Typen abzufragen:
using ViewerList = QList<AbstractViewer *>; QStringList viewerNames(bool showDefault = false) const; ViewerList viewers() const; AbstractViewer *findViewer(const QString &viewerName) const; AbstractViewer *defaultViewer() const; QStringList supportedMimeTypes() const;
Die Funktion viewer()
gibt einen Zeiger auf das Plugin zurück, das zum Öffnen des als Argument übergebenen QFile geeignet ist:
m_viewer = m_factory->viewer(file);
Wenn die Anwendungseinstellungen einen Abschnitt für den Viewer enthalten, wird dieser an die virtuelle Funktion restoreState()
des Viewers übergeben:
void MainWindow::restoreViewerSettings() { if (!m_viewer) return; QSettings settings; settings.beginGroup(settingsViewers); QByteArray viewerSettings = settings.value(m_viewer->viewerName(), QByteArray()).toByteArray(); settings.endGroup(); if (!viewerSettings.isEmpty()) m_viewer->restoreState(viewerSettings); }
Dann werden die Standard-UI-Assets an den Viewer übergeben und der Hauptbildlaufbereich wird so eingestellt, dass er das Anzeige-Widget des Viewers anzeigt:
m_viewer->initViewer(ui->actionBack, ui->actionForward, ui->menuHelp->menuAction(), ui->tabWidget); restoreViewerSettings(); ui->scrollArea->setWidget(m_viewer->widget()); return true; }
AbstractViewer-Klasse
AbstractViewer
bietet eine verallgemeinerte API zum Anzeigen, Speichern und Drucken eines Dokuments. Eigenschaften sowohl des Dokuments als auch des Viewers können abgefragt werden:
- Hat das Dokument einen Inhalt?
- Wurde es geändert?
- Wird eine Übersicht (Miniaturansichten oder Lesezeichen) unterstützt?
AbstractViewer bietet geschützte Methoden für abgeleitete Klassen, um Aktionen und Menüs im Hauptfenster zu erstellen. Damit diese Elemente im Hauptfenster angezeigt werden können, werden sie diesem übergeordnet. AbstractViewer ist für das Entfernen und Zerstören der von ihm erstellten UI-Assets verantwortlich. Er erbt von QObject, um Signale und Slots zu implementieren.
Signale
void uiInitialized();
Dieses Signal wird ausgegeben, nachdem ein Viewer alle notwendigen Informationen über UI-Assets im Hauptfenster erhalten hat.
void printingEnabledChanged(bool enabled);
Dieses Signal wird ausgegeben, wenn der Dokumentendruck entweder aktiviert oder deaktiviert ist. Dies geschieht, nachdem ein neues Dokument erfolgreich geladen wurde oder z. B. der gesamte Inhalt entfernt wurde.
void printStatusChanged(AbstractViewer::PrintStatus status);
Nach dem Start des Druckvorgangs informiert dieses Signal über Änderungen in dessen Verlauf.
void documentLoaded(const QString &fileName);
Dieses Signal teilt der Anwendung mit, dass ein Dokument erfolgreich geladen wurde.
TxtViewer-Klasse
TxtViewer
ist ein einfacher Textbetrachter, der von AbstractViewer erbt. Sie unterstützt das Bearbeiten von Textdateien, Kopieren/Ausschneiden und Einfügen, Drucken und Speichern von Änderungen.
JsonViewer-Klasse
JsonViewer
zeigt eine JSON-Datei in einem QTreeView an. Intern lädt sie den Inhalt einer Datei in ein QJsonDocument und verwendet ihn, um ein benutzerdefiniertes Baummodell mit JsonItemModel
zu füllen.
Das JSON-Viewer-Plugin demonstriert, wie ein von QAbstractItemModel geerbtes benutzerdefiniertes Elementmodell implementiert wird. Die Klasse JsonTreeItem
bietet eine grundlegende API für die Bearbeitung von JSON-Daten und deren Rückübertragung an die zugrunde liegende QJsonDocument.
JsonViewer verwendet die Top-Level-Objekte des Dokuments als Lesezeichen für die Navigation. Andere Knoten (Schlüssel und Werte) können als zusätzliche Lesezeichen hinzugefügt oder aus der Lesezeichenliste entfernt werden. Ein QLineEdit wird als Suchfeld verwendet, um durch den JSON-Baum zu navigieren.
PdfViewer-Klasse
Die Klasse PdfViewer
(und das Plugin) ist ein Fork des PDF Viewer Widget Beispiels. Sie demonstriert die Verwendung von QScroller, um reibungslos durch ein Dokument zu blättern.
Andere relevante Klassen
HoverWatcher-Klasse
Die Klasse HoverWatcher
setzt einen Override-Cursor, wenn die Maus über einem Widget schwebt, und stellt ihn beim Verlassen wieder her. Um zu verhindern, dass mehrere HoverWatcher-Instanzen für dasselbe Widget erstellt werden, ist sie als Singleton pro Widget implementiert.
HoverWatcher erbt von QObject und nimmt das QWidget, das er beobachtet, als Elternteil der Instanz. Er installiert einen Ereignisfilter, um Hover-Ereignisse abzufangen, ohne sie zu konsumieren:
HoverWatcher::HoverWatcher(QWidget *watched) : QObject(watched), m_watched(watched) { Q_ASSERT(watched); m_cursorShapes[Entered].emplace(Qt::OpenHandCursor); m_cursorShapes[MousePress].emplace(Qt::ClosedHandCursor); m_cursorShapes[MouseRelease].emplace(Qt::OpenHandCursor); // no default for Left => restore override cursor m_watched->installEventFilter(this); }
Das HoverAction
enum listet die Aktionen auf, auf die HoverWatcher reagiert:
enum HoverAction { Entered, MousePress, MouseRelease, Left, Ignore };
Statische Funktionen erstellen Beobachter, prüfen deren Existenz für eine bestimmte QWidget, oder beenden einen Beobachter:
static HoverWatcher *watcher(QWidget *watched); static const HoverWatcher *watcher(const QWidget *watched); static bool hasWatcher(QWidget *widget); static void dismiss(QWidget *watched);
Für jede HoverAction kann eine Cursorform gesetzt oder nicht gesetzt werden. Wenn es keine zugehörige Cursorform gibt, wird der Override-Cursor der Anwendung wiederhergestellt, wenn die Aktion ausgelöst wird.
public slots: void setCursorShape(HoverAction type, Qt::CursorShape shape); void unSetCursorShape(HoverAction type);
Die Eigenschaft mouseButtons
enthält die zu berücksichtigenden Maustasten für eine MousePress
Aktion:
void setMouseButtons(Qt::MouseButtons buttons); void setMouseButton(Qt::MouseButton button, bool enable);
Aktionsspezifische Signale werden nach der Verarbeitung einer Aktion ausgegeben:
signals: void entered(); void mousePressed(); void mouseReleased(); void left();
Es wird ein allgemeines Signal ausgegeben, das die verarbeitete Aktion als Argument übergibt:
void hoverAction(HoverAction action);
Die Klasse RecentFiles
RecentFiles
ist eine QStringList, die darauf spezialisiert ist, eine Liste von kürzlich geöffneten Dateien zu verwalten.
RecentFiles hat Slots, um entweder eine einzelne Datei oder mehrere Dateien auf einmal hinzuzufügen. Ein Eintrag wird in die Liste der zuletzt geöffneten Dateien aufgenommen, wenn der Pfad auf eine Datei zeigt, die existiert und geöffnet werden kann. Befindet sich eine Datei bereits in der Liste, wird sie von ihrer ursprünglichen Position entfernt und an den Anfang gesetzt.
public slots: void addFile(const QString &fileName) { addFile(fileName, EmitPolicy::EmitWhenChanged); } void addFiles(const QStringList &fileNames);
Dateien werden entweder nach Namen oder nach Index aus der Liste entfernt:
void removeFile(const QString &fileName) { removeFile(m_files.indexOf(fileName)); } void removeFile(qsizetype index) {removeFile(index, RemoveReason::Other); }
Slots, die das Speichern und Wiederherstellen von QSettings ermöglichen:
void saveSettings(QSettings &settings, const QString &key) const; bool restoreFromSettings(QSettings &settings, const QString &key);
Bei der Wiederherstellung von Einstellungen werden nicht vorhandene Dateien ignoriert. Die Eigenschaft maxFiles
enthält die maximale Anzahl der zu speichernden aktuellen Dateien (Standard ist 10).
qsizetype maxFiles();
void setMaxFiles(qsizetype maxFiles);
RecentFiles
prüft, ob eine Datei gelesen werden kann, bevor sie akzeptiert wird.
RecentFileMenu-Klasse
RecentFileMenu
ist eine QMenu, die darauf spezialisiert ist, ein RecentFiles-Objekt als Untermenü anzuzeigen.
Ihr Konstruktor nimmt einen Zeiger auf ein übergeordnetes QObject und einen Zeiger auf ein RecentFiles-Objekt entgegen, dessen Inhalt sie visualisieren wird. Das Signal fileOpened()
, das ausgelöst wird, wenn der Benutzer eine neue Datei aus der Liste auswählt, übergibt den absoluten Pfad zu der Datei als Argument.
Hinweis: RecentFileMenu
wird entweder durch sein übergeordnetes Widget oder durch das RecentFiles
Objekt, das an seinen Konstruktor übergeben wird, zerstört.
© 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.