Exemple ApplicationFichiers :
Images :
L'exemple Application montre comment impl�menter une application fen�tr�e standard avec des menus, barres d'outils et une barre d'�tat. L'exemple lui-m�me est un simple �diteur de texte construit autour de QPlainTextEdit. La quasi-totalit� du code de l'exemple Application se trouve dans la classe MainWindow, qui d�rive de QMainWindow. QMainWindow fournit l'infrastructure pour des fen�tres poss�dant menus, barres d'outils, fen�tres dockables et barre d'�tat. L'application contient des entr�es File (fichier), Edit (�diter) et Help (aide) dans la barre de menu, avec les menus popup suivants : La barre d'�tat en bas de la fen�tre principale affiche une description de l'entr�e de menu ou du bouton de la barre d'outils sous le pointeur de souris. Pour ne pas compliquer l'exemple, les fichiers r�cemment ouverts ne sont pas affich�s dans le menu File, bien que cette fonction soit d�sirable dans 90 % des applications. L'exemple fichiers r�cents montre comment impl�menter cette fonction. De plus, cet exemple ne peut charger qu'un fichier � la fois. Les exemples SDI et MDI montrent comment lever ces restrictions. D�finition de la classe MainWindowVoici la d�finition de la classe : class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(); protected: void closeEvent(QCloseEvent *event); private slots: void newFile(); void open(); bool save(); bool saveAs(); void about(); void documentWasModified(); private: void createActions(); void createMenus(); void createToolBars(); void createStatusBar(); void readSettings(); void writeSettings(); bool maybeSave(); void loadFile(const QString &fileName); bool saveFile(const QString &fileName); void setCurrentFile(const QString &fileName); QString strippedName(const QString &fullFileName); QPlainTextEdit *textEdit; QString curFile; QMenu *fileMenu; QMenu *editMenu; QMenu *helpMenu; QToolBar *fileToolBar; QToolBar *editToolBar; QAction *newAct; QAction *openAct; QAction *saveAct; QAction *saveAsAct; QAction *exitAct; QAction *cutAct; QAction *copyAct; QAction *pasteAct; QAction *aboutAct; QAction *aboutQtAct; }; L'API publique se limite au constructeur. Dans la section protected, nous r�impl�mentons QWidget::closeEvent() pour d�tecter les tentatives de fermeture de la fen�tre et avertir l'utilisateur en cas de modifications non sauvegard�es. Dans la section private slots, nous d�clarons les slots correspondant aux entr�es de menu, ainsi qu'un myst�rieux slot documentWasModified(). Enfin, dans la section private de la classe, nous avons divers membres qui seront expliqu�s par la suite. Impl�mentation de la classe MainWindow#include <QtGui> #include "mainwindow.h" Nous commen�ons par inclure <QtGui>, un fichier d'en-t�te qui contient la d�finition de toutes les classes de QtCore et QtGui ; cela nous �vite d'avoir � inclure chaque classe individuellement. Nous incluons aussi mainwindow.h. Vous vous demandez peut-�tre pourquoi nous n'incluons pas simplement <QtGui> dans mainwindow.h. Nous �vitons de le faire car l'inclusion d'un fichier d'en-t�te aussi important depuis un autre fichier d'en-t�te peut rapidement d�grader les performances. Dans le cas pr�sent, cela ne poserait pas de probl�me, mais il vaut mieux, de fa�on g�n�rale, n'inclure que les fichiers d'en-t�te strictement n�cessaires dans un autre fichier d'en-t�te. MainWindow::MainWindow() { textEdit = new QPlainTextEdit; setCentralWidget(textEdit); createActions(); createMenus(); createToolBars(); createStatusBar(); readSettings(); connect(textEdit->document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); setCurrentFile(""); setUnifiedTitleAndToolBarOnMac(true); } Dans le constructeur, nous commen�ons par cr�er un widget QPlainTextEdit en tant qu'enfant de la fen�tre principale (l'objet this). Nous appelons ensuite QMainWindow::setCentralWidget() pour dire que ce widget va occuper la partie centrale de la fen�tre principale, entre les barres d'outils et la barre d'�tat. Nous appelons ensuite createActions(), createMenus(), createToolBars() et createStatusBar(), quatre fonctions priv�es de construction de l'interface utilisateur. Apr�s cela, nous appelons readSettings() pour restaurer les pr�f�rences utilisateur. Nous �tablissons une connexion signal-slot entre l'objet document QPlainTextEdit et notre slot documentWasModified(). Lorsque l'utilisateur modifie le texte dans le QPlainTextEdit, nous voulons mettre � jour la barre de titre pour montrer que le fichier a �t� modifi�. Pour finir, nous d�finissons le titre de la fen�tre en utilisant la fonction priv�e setCurrentFile(). Nous y reviendrons plus tard. void MainWindow::closeEvent(QCloseEvent *event) { if (maybeSave()) { writeSettings(); event->accept(); } else { event->ignore(); } } Lorsque l'utilisateur essaie de fermer la fen�tre, nous appelons la fonction priv�e maybeSave() pour lui donner la possibilit� de sauvegarder les changements en cours. La fonction renvoie true si l'utilisateur veut que l'application se ferme ; sinon elle renvoie false. Dans le premier cas, nous sauvegardons les pr�f�rences utilisateur sur le disque et acceptons l'�v�nement de fermeture ; dans le second cas, nous ignorons l'�v�nement de fermeture, ce qui veut dire que l'application va continuer � fonctionner comme si rien ne s'�tait pass�. void MainWindow::newFile() { if (maybeSave()) { textEdit->clear(); setCurrentFile(""); } } Le slot newFile() est invoqu� lorsque l'utilisateur s�lectionne File|New depuis le menu. Nous appelons maybeSave() pour sauvegarder les changements en cours et si l'utilisateur accepte de continuer, nous vidons le QPlainTextEdit et appelons la fonction priv�e setCurrentFile() pour mettre � jour le titre de fen�tre et d�sactiver le drapeau windowModified. void MainWindow::open() { if (maybeSave()) { QString fileName = QFileDialog::getOpenFileName(this); if (!fileName.isEmpty()) loadFile(fileName); } } Le slot open() est invoqu� lorsque l'utilisateur clique sur File|Open. Nous ouvrons une QFileDialog demandant � l'utilisateur de choisir un fichier. Si l'utilisateur choisit un fichier (c'est-�-dire que fileName n'est pas une cha�ne vide), nous appelons la fonction priv�e loadFile() pour r�ellement charger le fichier. bool MainWindow::save() { if (curFile.isEmpty()) { return saveAs(); } else { return saveFile(curFile); } } Le slot save() est invoqu� lorsque l'utilisateur clique sur File|Save. Si l'utilisateur n'a pas encore fourni de nom pour le fichier, nous appelons saveAs() ; sinon, nous appelons la fonction priv�e saveFile() pour r�ellement sauvegarder le fichier. bool MainWindow::saveAs() { QString fileName = QFileDialog::getSaveFileName(this); if (fileName.isEmpty()) return false; return saveFile(fileName); } Dans saveAs(), nous commen�ons par ouvrir une QFileDialog demandant � l'utilisateur de choisir un nom de fichier. Si l'utilisateur clique sur Cancel (annuler), le nom de fichier renvoy� est vide et nous ne faisons rien. void MainWindow::about() { QMessageBox::about(this, tr("� propos de Application"), tr("L'exemple <b>Application</b> montre comment �crire " "des applications d'interface utilisateur moderne en utilisant Qt " "avec une barre de menu, d'outils et d'�tat.")); } La fen�tre « � propos de... » de l'application est g�n�r�e avec une seule instruction, en utilisant la fonction statique QMessageBox::about(), qui permet l'insertion de code HTML. L'appel tr() autour de la cha�ne litt�rale signale que la cha�ne doit �tre traduite. Une bonne habitude est d'appeler tr() sur toutes les cha�nes visibles par l'utilisateur, au cas o� vous d�cideriez plus tard de traduire votre application dans d'autres langues. La documentation Internationalisation avec Qt d�crit tr() en d�tail. void MainWindow::documentWasModified() { setWindowModified(textEdit->document()->isModified()); } Le slot documentWasModified() est invoqu� � chaque fois que le texte dans le QPlainTextEdit change suite � des modifications par l'utilisateur. Nous appelons QWidget::setWindowModified() afin que la barre de titre indique que le fichier a �t� modifi�. La fa�on dont cette information est montr�e varie suivant les plateformes. void MainWindow::createActions() { newAct = new QAction(QIcon(":/images/new.png"), tr("&Nouveau"), this); newAct->setShortcuts(QKeySequence::New); newAct->setStatusTip(tr("Cr�e un nouveau fichier")); connect(newAct, SIGNAL(triggered()), this, SLOT(newFile())); openAct = new QAction(QIcon(":/images/open.png"), tr("&Ouvrir..."), this); openAct->setShortcuts(QKeySequence::Open); openAct->setStatusTip(tr("Ouvre un fichier existant")); connect(openAct, SIGNAL(triggered()), this, SLOT(open())); ... aboutQtAct = new QAction(tr("� propos de &Qt"), this); aboutQtAct->setStatusTip(tr("Affiche la bo�te de dialogue � propos de Qt")); connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt())); La fonction priv�e createActions(), qui est appel�e depuis le constructeur de MainWindow, cr�e des QAction. Le code est tr�s r�p�titif, donc nous ne montrons que les actions correspondant � File|New, File|Open et Help|About Qt. Une QAction est un objet repr�sentant une action utilisateur, comme une sauvegarde de fichier ou la demande d'une bo�te de dialogue. Une action peut �tre int�gr�e dans un QMenu ou une QToolBar (ou les deux) ou dans n'importe quel autre widget r�impl�mentant QWidget::actionEvent(). Une action poss�de un texte, qui est affich� dans le menu, une ic�ne, une touche de raccourci, une infobulle, une information d'�tat (montr� dans la barre d'�tat), un texte « What's This ? » (« qu'est-ce que c'est ? »), etc. Elle �met un signal triggered() � chaque fois que l'utilisateur invoque l'action (par exemple en cliquant sur l'entr�e de menu associ�e ou le bouton de la barre d'outils). Nous connectons ce signal � un slot qui va r�aliser l'action. Le code ci-dessus contient un autre idiome demandant une explication. Pour certaines actions, nous sp�cifions une ic�ne sous forme de QIcon au constructeur de QAction. Le constructeur de QIcon prend le nom de fichier d'une image qu'il essaie de charger. Ici, le nom de fichier commence par :. Ce type de nom de fichier n'est pas un nom de fichier ordinaire mais un chemin dans les ressources enregistr�es dans l'ex�cutable. Nous y reviendrons lorsque nous �tudierons le fichier application.qrc int�gr� dans le projet. cutAct->setEnabled(false); copyAct->setEnabled(false); connect(textEdit, SIGNAL(copyAvailable(bool)), cutAct, SLOT(setEnabled(bool))); connect(textEdit, SIGNAL(copyAvailable(bool)), copyAct, SLOT(setEnabled(bool))); } Les actions Edit|Cut and Edit|Copy ne doivent �tre accessibles que si le QPlainTextEdit contient un texte s�lectionn�. Nous les d�sactivons par d�faut et connectons le signal QPlainTextEdit::copyAvailable() au slot QAction::setEnabled(), ce qui permet de n'activer les actions que si l'�diteur de texte contient une s�lection. void MainWindow::createMenus() { fileMenu = menuBar()->addMenu(tr("&Fichier")); fileMenu->addAction(newAct); fileMenu->addAction(openAct); fileMenu->addAction(saveAct); fileMenu->addAction(saveAsAct); fileMenu->addSeparator(); fileMenu->addAction(exitAct); editMenu = menuBar()->addMenu(tr("&�dition")); editMenu->addAction(cutAct); editMenu->addAction(copyAct); editMenu->addAction(pasteAct); menuBar()->addSeparator(); helpMenu = menuBar()->addMenu(tr("&Aide")); helpMenu->addAction(aboutAct); helpMenu->addAction(aboutQtAct); } Cr�er des actions ne suffit pas � les rendre accessibles � l'utilisateur ; nous devons aussi les ajouter au syst�me de menu. C'est ce que fait createMenus(). Nous cr�ons un menu File (fichier), Edit (modifier) et Help (aide). QMainWindow::menuBar() nous permet d'acc�der � la barre de menu de la fen�tre. Nous n'avons pas besoin de cr�er la barre de menu nous-m�mes ; elle est cr��e la premi�re fois que nous appelons cette fonction. Juste avant de cr�er le menu Help, nous appelons QMenuBar::addSeparator(). Cela n'a pas d'effet pour la plupart des styles de widgets (par exemple les styles Windows et Mac OS X) mais pour les styles bas�s sur Motif cela a pour effet de cadrer Help � droite de la barre de menu. Essayez de lancer l'application avec diff�rents styles pour voir le r�sultat : application -style=windows application -style=motif application -style=cde �tudions maintenant les barres d'outils : void MainWindow::createToolBars() { fileToolBar = addToolBar(tr("Fichier")); fileToolBar->addAction(newAct); fileToolBar->addAction(openAct); fileToolBar->addAction(saveAct); editToolBar = addToolBar(tr("�dition")); editToolBar->addAction(cutAct); editToolBar->addAction(copyAct); editToolBar->addAction(pasteAct); } La cr�ation de barres d'outils est tr�s similaire � la cr�ation de menus. Les actions que nous associons aux menus peuvent �tre r�utilis�es dans les barres d'outils. void MainWindow::createStatusBar() { statusBar()->showMessage(tr("Pr�t")); } QMainWindow::statusBar() renvoie un pointeur sur le widget QStatusBar de la fen�tre principale. Comme pour QMainWindow::menuBar(), le widget est cr�� automatiquement la premi�re fois que la fonction est appel�e. void MainWindow::readSettings() { QSettings settings("Trolltech", "Exemple Application"); QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint(); QSize size = settings.value("size", QSize(400, 400)).toSize(); resize(size); move(pos); } La fonction readSettings() est appel�e depuis le constructeur pour charger les pr�f�rences utilisateur et les autres param�tres de l'application. La classe QSettings fournit une interface de haut niveau pour l'enregistrement permanent de param�tres sur disque. Sur Windows, elle utilise la (trop) c�l�bre base de registres Windows ; sur Mac OS X, elle utilise l'API native CFPreferences bas�e sur XML ; sur Unix/X11, elle utilise des fichiers texte. Le constructeur de QSettings prend des arguments identifiant votre organisation et le nom du produit. Cela permet aux param�tres de diff�rentes applications d'�tre conserv�s s�par�ment. Nous utilisons QSettings::value() pour extraire la valeur des param�tres pos et size. Le second argument de QSettings::value() est optionnel et sp�cifie une valeur par d�faut pour le param�tre. Cette valeur est utilis�e la premi�re fois que l'application est lanc�e. Au moment de restaurer la position et la taille d'une fen�tre, il est important d'appeler QWidget::resize() avant QWidget::move(). L'explication est donn�e dans la documentation G�om�trie de la fen�tre. void MainWindow::writeSettings() { QSettings settings("Trolltech", "Exemple Application"); settings.setValeur("pos", pos()); settings.setValeur("size", size()); } La fonction writeSettings() est appel�e depuis closeEvent(). L'�criture des param�tres est similaire � leur lecture, en plus simple. Les arguments du constructeur de QSettings sont les m�mes que pour readSettings(). bool MainWindow::maybeSave() { if (textEdit->document()->isModified()) { QMessageBox::StandardButton ret; ret = QMessageBox::warning(this, tr("Application"), tr("Le document a �t� modifi�.\n" "Voulez-vous sauvegarder vos changements ?"), QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); if (ret == QMessageBox::Save) return save(); else if (ret == QMessageBox::Cancel) return false; } return true; } La fonction maybeSave() est appel�e pour sauvegarder les changements en cours. Si des changements sont en cours, elle ouvre une QMessageBox permettant � l'utilisateur de sauvegarder le document. Les options sont QMessageBox::Yes, QMessageBox::No et QMessageBox::Cancel. Le bouton Yes est sp�cifi� comme le bouton par d�faut (le bouton invoqu� lorsque l'utilisateur presse Return) en utilisant le drapeau QMessageBox::Default ; le bouton Cancel est sp�cifi� comme le bouton d'�chappement (le bouton invoqu� lorsque l'utilisateur presse Esc) en utilisant le drapeau QMessageBox::Escape. La fonction maybeSave() renvoie true dans tous les cas, sauf quand l'utilisateur clique Cancel. L'appelant doit v�rifier la valeur de retour et arr�ter le traitement en cours si la valeur de retour est false. void MainWindow::loadFile(const QString &fileName) { QFile file(fileName); if (!file.open(QFile::ReadOnly | QFile::Text)) { QMessageBox::warning(this, tr("Application"), tr("Impossible de lire le fichier %1:\n%2.") .arg(fileName) .arg(file.errorString())); return; } QTextStream in(&file); #ifndef QT_NO_CURSOR QApplication::setOverrideCursor(Qt::WaitCursor); #endif textEdit->setPlainText(in.readAll()); #ifndef QT_NO_CURSOR QApplication::restoreOverrideCursor(); #endif setCurrentFile(fileName); statusBar()->showMessage(tr("Fichier charg�"), 2000); } Dans loadFile(), nous utilisons QFile et QTextStream pour lire les donn�es. L'objet QFile donne acc�s aux octets stock�s dans le fichier. Nous commen�ons par ouvrir le fichier en mode lecture seule. Le drapeau QFile::Text indique que le fichier est de type texte et pas un fichier binaire. Sur Unix et Mac OS X, cela ne fait pas de diff�rence, mais sur Windows, cela permet la transformation des s�quences de fin de ligne « \r\n » en « \n » � la lecture. Si nous r�ussissons � ouvrir le fichier, nous utilisons un objet QTextStream pour lire les donn�es. QTextStream convertit automatiquement les donn�es 8 bits en QString Unicode et g�re divers encodages. Si aucun encodage n'est sp�cifi�, QTextStream suppose que le fichier est �crit dans l'encodage 8 bits par d�faut du syst�me (par exemple, Latin-1 ; voir QTextCodec::codecForLocale() pour les d�tails). �tant donn� que l'appel � QTextStream::readAll() peut �tre long, nous d�finissons le pointeur Qt::WaitCursor comme pointeur de l'application enti�re pour la dur�e de l'op�ration. Enfin, nous appelons la fonction priv�e setCurrentFile(), que nous allons expliquer dans la suite, et nous affichons la cha�ne « File loaded » (« Fichier charg� ») dans la barre d'�tat pendant 2 secondes (2000 millisecondes). bool MainWindow::saveFile(const QString &fileName) { QFile file(fileName); if (!file.open(QFile::WriteOnly | QFile::Text)) { QMessageBox::warning(this, tr("Application"), tr("Impossible d'�crire dans le fichier %1:\n%2.") .arg(fileName) .arg(file.errorString())); return false; } QTextStream out(&file); #ifndef QT_NO_CURSOR QApplication::setOverrideCursor(Qt::WaitCursor); #endif out << textEdit->toPlainText(); #ifndef QT_NO_CURSOR QApplication::restoreOverrideCursor(); #endif setCurrentFile(fileName); statusBar()->showMessage(tr("Fichier sauvegard�"), 2000); return true; } L'enregistrement d'un fichier est tr�s similaire � son chargement. Ici, le drapeau QFile::Text permet la conversion sur Windows du « \n » en « \r\n » pour se conformer � la convention du syst�me. void MainWindow::setCurrentFile(const QString &fileName) { curFile = fileName; textEdit->document()->setModified(false); setWindowModified(false); QString shownName = curFile; if (curFile.isEmpty()) shownName = "untitled.txt"; setWindowFilePath(shownName); } La fonction setCurrentFile() est appel�e pour r�initialiser l'�tat de quelques variables lorsqu'un fichier est charg� ou enregistr� ou lorsque l'utilisateur commence � �diter un nouveau fichier (dans ce dernier cas fileName est vide). Nous mettons � jour la variable curFile, d�sactivons le drapeau QTextDocument::modified et le drapeau associ� QWidget:windowModified et mettons � jour le titre de la fen�tre avec le nouveau nom de fichier (ou untitled.txt). L'appel � la fonction strippedName() autour de curFile dans l'appel QWidget::setWindowTitle() raccourcit le nom de fichier en excluant le chemin. Voici la fonction : QString MainWindow::strippedName(const QString &fullFileName) { return QFileInfo(fullFileName).fileName(); } La fonction main()de cette application est typique des applications qui contiennent une fen�tre principale :#include <QApplication> #include "mainwindow.h" int main(int argc, char *argv[]) { Q_INIT_RESOURCE(application); QApplication app(argc, argv); app.setOrganizationName("Trolltech"); app.setApplicationName("Exemple Application"); MainWindow mainWin; mainWin.show(); return app.exec(); } Le fichier de ressourcesVous vous souvenez probablement que pour certaines actions, nous avons sp�cifi� des ic�nes avec des noms de fichiers commen�ant par : et mentionn� que ces noms de fichiers ne sont pas des noms de fichiers ordinaires mais des chemins dans les ressources enregistr�es de l'ex�cutable. Ces ressources sont compil�es. Les ressources associ�es � une application sont sp�cifi�es dans un fichier .qrc, un format de fichier bas� sur XML qui liste des fichiers pr�sents sur le disque. Voici le fichier application.qrc utilis� par notre exemple Application : <!DOCTYPE RCC><RCC version="1.0"> <qresource> <file>images/copy.png</file> <file>images/cut.png</file> <file>images/new.png</file> <file>images/open.png</file> <file>images/paste.png</file> <file>images/save.png</file> </qresource> </RCC> Les fichiers .png list�s dans le fichier application.qrc sont des fichiers pr�sents dans l'arborescence des sources de l'exemple Application. Les chemins sont relatifs au r�pertoire o� se trouve le fichier application.qrc (le r�pertoire mainwindows/application). Le fichier de ressources doit �tre mentionn� dans le fichier application.pro pour que qmake le prenne en compte : RESOURCES = application.qrc qmake produira des r�gles de g�n�ration d'un fichier qrc_application.cpp qui sera compil� dans l'application. Ce fichier contient les donn�es des images et des autres ressources sous forme de tableaux C++ statiques contenant des donn�es binaires compress�es. Voir Le syst�me de ressources de Qt pour plus d'informations sur les ressources. RemerciementsMerci � <!idiallo!> pour la traduction et � <!johnlamericain!>, <!ClaudeLELOUP!> et <!jacques_jean!> pour leur relecture ! |
Cette page est une traduction d'une page de la documentation de Qt, �crite par Nokia Corporation and/or its subsidiary(-ies). Les �ventuels probl�mes r�sultant d'une mauvaise traduction ne sont pas imputables � Nokia. | Qt 4.7 | |
Copyright © 2025 Developpez LLC. Tous droits r�serv�s Developpez LLC. Aucune reproduction, m�me partielle, ne peut �tre faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon, vous encourez selon la loi jusqu'� 3 ans de prison et jusqu'� 300 000 E de dommages et int�r�ts. Cette page est d�pos�e � la SACD. | ||
Vous avez d�nich� une erreur ? Un bug ? Une redirection cass�e ? Ou tout autre probl�me, quel qu'il soit ? Ou bien vous d�sirez participer � ce projet de traduction ? N'h�sitez pas � nous contacter ou par MP ! |