PenguinPenguin

Programmer avec Qt


Valid HTML 4.0! Valid CSS! étiqueté grâce à l'ICRA

Ma page LinuxTout mon site

Ceci n'est pas le guide de programmation sous Qt, mais juste un rappel de ce que je suis arrivé à comprendre afin de pouvoir recommencer à faire la même chose une autre fois. Pour le moment, ce fichier est une version complètement non achevée qui ne réclame que vos remarques pour s'améliorer!

J'ai utilisé Kdevelop et Qt designer. pour ceux qui compte faire sans, je suis sur que cette page ne leur sera pas suffisante.



  1. Le français, pas l'anglais!

    Etant anglophobe, je me suis débrouillé avec mes propres moyens, sans trop parcourir de documentations en anglais. J'explique donc mes astuces. J'ai tout de même trouvé des sites ou des pages en français, je vais donc vous les donner en vrac.

  2. Utilisation de Kdevelop
    1. Présentation

      Pour commencer, je me suis inspiré du site de Jean-Marie LAFON. Même s'il n'est pas prévu pour Qt3, il convient tout à fait pour cette version plus réscente.

    2. Ouverture de KDevelop

      Si on commence un projet, il faut suivre le point précédent. Par contre, pour réouvrir un projet déjà commencer, il faut aller chercher son projet dans le menu Projet->Open recent Project si on a réscemment travaillé dessus. Sinon, il faut aller dans Projet->Open ce qui est équivalent à l'icône projet.

    3. Mon utilisation

      Je n'utilise KDevelop que pour gérer mon projet :

      • Ajout d'un nouveau document :
      • Compilation
      • Débogage

      Pour l'édition j'ai pris l'habitude de kwrite que j'utilise pour écrire ce texte en html. J'aime bien entre autre l'affichage du numéro de ligne (faire F11).

  3. Utilisation de QT Designer
    1. Présentation

      Pour les débuts tout est encore commenté dans le site de Jean-Marie LAFON.

      Par contre, pour ouvrir par la suite Qt Designer à partir de KDevelop, il y a un bouton dans la barre du haut qui represente le signe de Qt : qt, cliquez dessus puis sélectionnez votre interface d'utilisateur Qt (avant il faudra souvent sélectionner le bon dossier) : c'est un fichier .ui.

    2. Bloquer la taille de la fenêtre

      Par la fenêtre Object Explorer, onglet Objects, sélectionnez la base du projet (l'item le plus haut). Ceci affichera dans la fenêtre Property Editor/Signal Handlers, onglet Properties, les propriétés de votre fenêtre. Vous y trouverez la propriété minimunSize (taille minimum) minimumSize, cliquez sur le '+' devant minimumSize et vous pouvez modifier la taille en modifiant l'un après l'autre la largeur (width) et la hauteur (height). Recommencez la même manipulation avec maximumSize (taille maximum), si les paramètres sont les mêmes alors la taille de votre fenêtre sera fixée, l'utilisateur ne pourra pas la faire varier.

  4. Les includes
    1. Lequel mettre?

      Si avec Qt Designer, vous mettez un nouveau objet, tant que vous n'intervenez pas dessus avec votre programme, il n'y a rien à faire. Par contre, s'il devient interactif, il faudra mettre un include qui définit l'objet et ses méthodes.

      Lors de la compilation un message signalant qu'il n'a pas su quoi faire avec l'objet et/ou sa méthode vous préviendra qu'il faut mettre dans le programme l'include qui va avec. Les includes se trouvent dans /usr/lib/qt3/include/ :

      [troumad@mon_pc][~/Troumad/Linux]$ ls /usr/lib/qt3/include/
      jri.h               qconfig-small.h   qftp.h                qlist.h                  qpngio.h           qsize.h               qt.h
      jri_md.h            qconnect.h        qgarray.h             qlistview.h              qpntarry.h         qsizepolicy.h         qthread.h
      ...
      ... Il y en a beaucoup ...
      ...
      qconfig-medium.h    qfontmetrics.h    qlineedit.h           qplatinumstyle.h         qsimplerichtext.h  qtextstream.h
      qconfig-minimal.h   qframe.h          qlistbox.h            qpmcache.h               qsizegrip.h        qtextview.h
      

      Dans cet exemple, je supose que vous utilisez un objet du type : QFileDialog. Voici comment le trouver :

      [troumad@mon_pc][~/Troumad/Linux]$ cd /usr/lib/qt3/include
      [troumad@mon_pc][/usr/lib/qt3/include]$ find . -type f -print |xargs grep QFileDialog
      ./qfeatures.h:// QFileDialog
      ./qfiledialog.h:** Definition of QFileDialog class
      ./qfiledialog.h:class QFileDialog;
      ./qfiledialog.h:class QFileDialogPrivate;
      ./qfiledialog.h:class QFileDialogQFileListView;
      ./qfiledialog.h:class Q_EXPORT QFileDialog : public QDialog
      ./qfiledialog.h:    QFileDialog( const QString& dirName, const QString& filter = QString::null,
      ./qfiledialog.h:    QFileDialog( QWidget* parent=0, const char* name=0, bool modal = FALSE );
      ./qfiledialog.h:    ~QFileDialog();
      ./qfiledialog.h:    friend class QFileDialogQFileListView;
      ./qfiledialog.h:    QFileDialogPrivate *d;
      ./qfiledialog.h:    QFileDialogQFileListView  *files;
      ./qfiledialog.h:    QFileDialog( const QFileDialog & );
      ./qfiledialog.h:    QFileDialog &operator=( const QFileDialog & );
      

      Votre objet se trouve donc dans qfiledialog.h. Il faut donc mettre :

      #include <qfiledialog.h>
    2. Que peut-on faire avec cet objet ?

      Toutes les fonctions utilisables avec cet objet se trouvent décrite (arguments d'entrée et de sortie) dans l'include que vous venez de rajouter. Il vous suffit de le regarder.

      [troumad@mon_pc][~/Troumad/Linux]$cat /usr/lib/qt3/include/qfiledlg.h
      /****************************************************************************
      ** $Id: qt/qfiledlg.h   3.1.2   edited Nov 8 14:35 $
      **
      ** Compatibility file - should only be included by legacy code.
      ** It #includes the file which obsoletes this one.
      trop long : description des droits et autres
      #endif
      [troumad@mon_pc][/~/Troumad/Linux]$cat /usr/lib/qt3/include/qfiledialog.h
      /****************************************************************************
      trop long : description des droits
      **********************************************************************/
      
      #ifndef QFILEDIALOG_H
      trop long : mise en place des données utiles
      #endif // QT_H
      
      #ifndef QT_NO_FILEDIALOG
      
      class Q_EXPORT QFileIconProvider : public QObject
      {
      trop long : définition de QFileIconProvider, ce n'est pas ce qu'on cherche
      };
      
      class Q_EXPORT QFileDialog : public QDialog
      {
      Comment les définir
      
          Q_OBJECT
          Q_ENUMS( Mode ViewMode PreviewMode )
          // ##### Why are this read-only properties ?
          Q_PROPERTY( QString selectedFile READ selectedFile )
          Q_PROPERTY( QString selectedFilter READ selectedFilter )
          Q_PROPERTY( QStringList selectedFiles READ selectedFiles )
          // #### Should not we be able to set the path ?
          Q_PROPERTY( QString dirPath READ dirPath )
          Q_PROPERTY( bool showHiddenFiles READ showHiddenFiles WRITE setShowHiddenFiles )
          Q_PROPERTY( Mode mode READ mode WRITE setMode )
          Q_PROPERTY( ViewMode viewMode READ viewMode WRITE setViewMode )
          Q_PROPERTY( PreviewMode previewMode READ previewMode WRITE setPreviewMode )
          Q_PROPERTY( bool infoPreview READ isInfoPreviewEnabled WRITE setInfoPreviewEnabled )
          Q_PROPERTY( bool contentsPreview READ isContentsPreviewEnabled WRITE setContentsPreviewEnabled )
      
      public:  C'est là que je vais trouver ce que je cherche
          QFileDialog( const QString& dirName, const QString& filter = QString::null,
                       QWidget* parent=0, const char* name=0, bool modal = FALSE );
          QFileDialog( QWidget* parent=0, const char* name=0, bool modal = FALSE );
          ~QFileDialog();
      
          // recommended static functions Recommendé ?
          static QString getOpenFileName( const QString &initially = QString::null,
                                          const QString &filter = QString::null,
                                          QWidget *parent = 0, const char* name = 0,
                                          const QString &caption = QString::null,
                                          QString *selectedFilter = 0,
                                          bool resolveSymlinks = TRUE);
          static QString getSaveFileName( const QString &initially = QString::null,
                                          const QString &filter = QString::null,
                                          QWidget *parent = 0, const char* name = 0,
                                          const QString &caption = QString::null,
                                          QString *selectedFilter = 0,
                                          bool resolveSymlinks = TRUE);
          static QString getExistingDirectory( const QString &dir = QString::null,
                                               QWidget *parent = 0,
                                               const char* name = 0,
                                               const QString &caption = QString::null,
                                               bool dirOnly = TRUE,
                                               bool resolveSymlinks = TRUE);
          static QStringList getOpenFileNames( const QString &filter= QString::null,
                                               const QString &dir = QString::null,
                                               QWidget *parent = 0,
                                               const char* name = 0,
                                               const QString &caption = QString::null,
                                               QString *selectedFilter = 0,
                                               bool resolveSymlinks = TRUE);
      Ceci permet d'appelé la boite de dialogue pour aller chercher dans l'arboscence respectiveemnt, un fichier à ouvirir (doit exister), un fichier pour sauver les données (ne doit pas forcément exister?), un répertoire (doit exister ?) ou une liste de fichiers (doivent exister ?). Voir plus loin.
          // other static functionsplein de fonctions : nous en regarderons peu!
      ...
          QString selectedFile() const;
      Voici la première : renvoie le nom du fichier sélectionné :
      ...
          virtual void setSelectedFilter( const QString& );
      La dernière : impose une selection
      ...
      
      public slots:
      Ils sont fournis par Qt Designer quand on fait des connections
      ...
      
      protected:
      ...
      signals:
      Ils sont fournis par Qt Designer quand on fait des connections
      ...
      
      private slots:
      ...
      
      private:
      ...
      };
      
      #endif
      
      #endif // QFILEDIALOG_H
      

      Comme vous le voyez, certains includes ne font que renvoyer à un autre include. C'est pour des versions de compatibilité et ils sont obsoletes : évitez donc d'utiliser ceux là! Il vous faudra parcourir les nouveaux includes pour savoir comment travailler avec votre objet.

    3. Ouverture de différentes fenêtres
      1. Ouvertures succéssives de fenêtres principales

        Je suis arrivé à faire ouvrir 2 fenêtres consécutivement dans le corps du programme, voici un extrait de mon fichier main.cpp :

        int main(int argc, char *argv[])
        {
         ...
         KApplication a;           // on ne peut définir qu'une seule KApplication
         QFileDialog * d_chemin = new QFileDialog();
         a.setMainWidget(d_chemin);// définition de la première KApplication
         Qs = d_chemin->getOpenFileName( acces,QString::null,0,0,QString::null,0,TRUE);
                                   // affichage et exécution de la première KApplication
         if (Qs.isEmpty())         // Si on a appuyé sur 'Cancel' ou la croix en haut à droite : rien dans Qs
         {
          alerte("Fin","

        Vous venez d'annuler.
        Le programme s'arrête donc.


        http://troumad.free.fr

        "); return 0; // Return implique la fin du programme } else { strcpy(acces,Qs); // J'ai besoin d'une chaîne de caractère, pas d'une QString que je ne sais pas encore utiliser.. if (acces!=NULL) xf_entree=fopen(acces,"r"); } ... QFileDialog * d_chemin = new QFileDialog(); // je définis d_chemin comme étant un QFileDialog Qs = d_chemin->getOpenFileName( acces,QString::null,0,0,QString::null,0,TRUE); // Je fais exécuter d_chemin qui me renvera l'adresse d'un fichier existant strcpy(acces,Qs); // J'ai besoin d'une chaîne de caractère, pas d'une QString que je ne sais pas encore utiliser.. printf("%s\n",acces); xf_entree=fopen(acces,"r"); ... Mon_essai *mon_essai = new Mon_essai(); a.setMainWidget(mon_essai);// définition de la troisième KApplication mon_essai->show(); // affichage de la troisième KApplication return a.exec(); // fin du programme car il y a return }

        Si vous définissez deux KApplication, vous générez lors de l'exécution un plantage du programme, KDE vous signale que l'application s'est terminée anormalement et a généré le signal 11 (SIGSEGV). Ceci dit, j'aimerai savoir exactement ce qu'est une KApplication : ma seconde fenêtre est sans KApplication et si je ferme ma fenêtre sans faire OK, je plante le programme. Le premier cas, lui permet de vérifier comment on est sorti de la fenêtre QDialog.

        Tant qu'il n'y a pas de return, on peut afficher les unes après les autres autant de KApplication (fenêtre de dialogues) que l'on souhaite.

      2. Ouverture de sous fenêtres à partir d'une autre fenêtre

        Il faut tout simplement ouvrir une fenêtre sans dire que c'est une KApplication. Voici un exemple qui était dans mon essai avec XF86Config-4 :

        Dialogue_Xinerama * averti_xinerama = new Dialogue_Xinerama();
        averti_xinerama->show();
        

        Dialogue_Xinerama() était défini par un ensemble de fichiers générés par Qt Designer. Comme je suis arrivé à faire des fenêtres contenant plusieurs objets, j'ai donc éliminé cette fonction. Vous verez celà au point suivant.

        Maintenant, il faut que je trouve une astuce pour "endormir" la fenêtre mère le temps de l'ouverture de cette fenêtre.

      3. Ouverture de fenêtres avec plusieurs objets

        Voici une procédure qui fait afficher une fenêtre avec un message et un bouton pour fermer la fenêtre lorsqu'on l'appelle :

        void alerte(char * titre,char * message)// titre : nom de la fenêtre, message : message à afficher
        {
         QWidget * app =new QWidget(0,titre,0); // Mon expérience dit que ça marche mieux avec des pointeurs
         QLabel * label = new QLabel(app,0);    // Premier objet de ma fenêtre : un label
         label->setText(message);               // Message du label
         label->setAutoResize( TRUE );          // Pour mettre la fenre à la taille du texte, sinon, elle est trop petite!
         label->setAlignment( 3 );              // Alignement du texte
         QPushButton * mes = new QPushButton("Ok",app); // Second objet = un bouton
         mes->move((label->width()-mes->width())/2,4+label->height());
                                                // Mettre le bouton ailleurs que sur le texte qui est en (0,0)
         mes->connect (mes, SIGNAL(clicked()),app, SLOT(close()));
                                                // Dire que la fenêtre se ferme quand on clique sur le bouton
         app->resize(max(label->width(),mes->width()),4+label->height()+mes->height());
                                                // mMttre la fenêtre à la bonne taille
         app->show();                           // afficher la fenêtre
        }
        
    4. Astuces de programmations

      J'essaie ici de mettre soit la résolution d'erreurs courantes lors de la compilation, soit de vraie astuces. Je remplis cette rubrique avec vos questions et les réponses à y apporter et les choses dont je suis fier.

      1. invalid use of `this' in non-member function

        Pour les fonctions qui ne sont définies void Nom_du_Widjet::Nom_de_la_fonction(), il faut recupéré le widjet par un paramètre qu'on passe avec la fonction, ou avec un paramètre global.

      2. syntax error before `->' token

        C'est peut-être que vous avez votre structure, directement une classe, une structure ou un widjet au lieu d'un pointeur sur cet objet. Dans ce cas, il faut remplacer le -> par un point.

    Télécharger l'image de fond en plus grand et moins clair (51,3 Ko) contre 27ko pour celle du fond.

    Ma page LinuxTout mon site