Forum Programmation.c++ QT4 et slots perso

Posté par  .
Étiquettes : aucune
0
10
jan.
2006
Bonjour,

Je cherchais un toolkit graphique pour developper des IHM... Apres quelques essais et test, j'ai finalement opté pour QT en C++. J'ai essayé python avec QT3 mais je voulais faire du QT4 directement, or au moment ou j'ai commencé mes tests pyQT n'était dispo que pour QT3. Bref.... nous allons discuter des slots perso.

Tout d'abord pour vous faire une idée, vous pourrez constater ici ce que donne mon interface pour l'instant (ce n'est pas fini hein :p).
http://julthomas.free.fr/plop.png

En gros, j'ai un QGridLayout qui divise ma fenetre en 2 (gauche et droite). Chaque partie (gauche et droite) est sur un QVBoxLayout. A gauche haut, j'ai un SearchWidget perso. A gauche bas, j'ai un QTableWidget. A droite au j'ai un autre widget perso que j'ai appellé InfosWidget. Et a droite bas j'ai pour l'instant un simple bouton histoire de mettre qquechose.

Mon test de slot perso se situe au niveau du InfosWidget. Si on regarde le screenshot, on voit un QLineEdit et juste a côté un QSlider. Je cherche à faire en sorte que bouger le QSlider mette à jour le QLineEdit. Facile :) Oui mais... Voici ma classe InfosWidget :


#ifndef __INFOSWIDGET_H__
#define __INFOSWIDGET_H__

#include <QtGui>

class InfosWidget : public QWidget
{
Q_OBJECT

private:
QGridLayout *mainLay;
QLabel *titleLab;
QLabel *commentLab;
QLabel *scoreLab;
QLineEdit *scoreValEdit;
QLineEdit *titleEdit;
QTextEdit *commentEdit;
QSlider *scoreSlide;
QPushButton *updateBut;

public:
InfosWidget();
~InfosWidget();

public slots:
void updateScoreValEdit(int val);
};

#endif /* __INFOSWIDGET_H__ */


Voici comment est connecté mon slot dans InfosWidget.cpp :


connect(scoreSlide, SIGNAL(valueChanged(int)), this, SLOT(updateScoreValEdit(int)));


Et voici le code du slot updateScoreValEdit(int) :


void InfosWidget::updateScoreValEdit(int val)
{
QString str;

str.setNum(val);
cout << str.toStdString() << endl;
//scoreValEdit->setText(str);
}


Tel quel, lorsque je bouge mon slide, je vois bien s'afficher la valeur dans ma console. Lorsque je décommente la ligne qui met à jour le QLineEdit, paf segfault au premier mouvement du slide. Au début j'avais essayé avec un QLabel au lieu d'un QLineEdit, pareil, même chose...

Je ne maîtrise pas les autotools, je n'utilise pas KDeveloppe. Je fais tout ca sous Emacs... Le but est faire une applis de gestion de mes divx, qui scanne les fichiers médias de mes disques durs et met le tout dans une base SQLite. J'ai déja developpé toute cette partie, et j'en suis à l'interface.

Pour compiler l'interface, j'ai donc fait mon Makefile perso en regardant les commandes que lançait qmake-qt4 car je voulais me passait des outils trolltech. Or, après avoir lu quelques docs, je m'apperçois que QT utilise un truc dont je doit absolument me servir pour faire des slots perso : moc. Je n'aime pas beaucoup ca mais bon, du coup pour l'instant je compile mon interface avec :


qmake-qt4 -project
qmake
make


A cause de ce moc, j'ai dû rajouter :
#include <QtGui>
dans mon .hpp, ce que j'ai trouvé très crado. Mais bon, apparement pas le choix.

Bref, en utilisant les outils QT (qmake, moc), en ayant inclus les header des objets QT et ayant mis la directive Q_OBJECT dans mon .hpp, tout devrait être réunit pour me slot perso fonctionne !! Mais non.

Ma question est donc, quelqu'un pourrait-il me donner une piste pour éviter ce segfault ? De plus, suis-je obligé d'utiliser les outils QT, ce moc me donne des boutons :) J'aime bien me compliquer et lancer à la main mes lignes de commandes appelant g++.

A ce que je sache, les projets utilisant QT que j'ai déjà pu compiler n'utilise pas qmake. Un ./configure && make fonctionne très bien et je suppose que le make n'appelle pas qmake.

Merci d'avance,
Julien.
  • # Emacs

    Posté par  . Évalué à 0.

    Je ne maîtrise pas les autotools, je n'utilise pas KDeveloppe. Je fais tout ca sous Emacs...

    Déjà un bon point :-)

    paf segfault au premier mouvement du slide

    Rajoute gdb à ta boîte à outil et débuggue!
    Tu devras probablement rajouter des -ggdb et autres "debug" dans ta config.

    ce moc me donne des boutons

    Apparamment ils utilisent pas les templates, enfin ils utilisent leur propre macro-ifieur
    :-(
    • [^] # Re: Emacs

      Posté par  . Évalué à 2.

      Bah même pas besoin de gdb (mais absolument indispensable à tout codeur).

      Ton en-tête est cool, tu définit bien le bidule dans InfosWidget.h :
      QLineEdit *scoreValEdit;


      Mais après dans InfosWidget.cpp (pourquoi pas .cc ???), tu redéfinit une nouvelle variablle InfosWidget, tu aurais du écrire :
      scoreValEdit = new QLineEdit("00");

      plutôt que
      QLineEdit *scoreValEdit = new QLineEdit("00");
      .

      --
      Emacs ça déchire (C-x 4-a pour rajouter une entréee dans le ChangeLog)
      • [^] # Re: Emacs

        Posté par  . Évalué à 1.

        Ah oui effectivement.... C'est le copié/collé apres avoir ait le .hpp ça :) Tu crois que le segfault sur le slot pourrait venir de ça ? Je testerai ce soir, j'ai partiel dans 2 heure et je doit réviser encore :)

        Sinon .cpp me parait plus "standard" que .cc, mais à vrai dire j'en sais strictement rien. Pareil pour .hpp au lieu de .hh... J'ai regardé dans des sources de projets et il me semble que c'était les extentions qui revenaient.

        Mais effectivement les divers avis m'interessent.
  • # moc OUI

    Posté par  . Évalué à 2.

    Oui, l'appel au moc est indispensable.

    Les slots ne sont pas du C++ pur. Il faut donc que moc passe par là pour remplacer ton code qui à trait aux slots/signaux par du code "standards C++". Donc tu n'as pas le choix. C'est une sorte de "préprocesseur" supplémentaire.

    La plus propre façon de faire ça est bien d'utiliser qmake pour générer ton makefile. Les autotools ayant l'air de qqch de compliqué à gérer même si il doit surement être possible de faire au moins aussi bien.

    Par contre pour le segfault, j'ai pas d'idée comme cela. T'as essayé de remplacer par
    scoreValEdit->setText("10");
    pour voir ?
    • [^] # Re: moc OUI

      Posté par  . Évalué à 1.

      Même chose, j'avais essayé aussi.

      Tout ce que je fais sur mon object à partir du slot entraine une segfault. Je ne comprend vraiment pas. Si je le fait en dehors du slot (à la fin du constructeur par exmeple), ok no problemo. Ca doit etre un truc à la con mais je ne vois vraiment pas.

      Pour qmake ok, soit :)
      Je pense que je vais essayer de voir ce que peut me dire gdb comme le suggère Neil Dökkalfar mais ca sera surement pour ce week end, je suis un peuspeed avec mes partiels cette semaine (toujours au dernier moment, comme d'hab. :p).
      • [^] # Re: moc OUI

        Posté par  . Évalué à 2.

        Tu pourrais tapper tout ton fichier .h et .cpp ? Ce sera plus facile à voir.
        • [^] # Re: moc OUI

          Posté par  . Évalué à 1.

          Ok je met pas le code directement ici mais voila un lien vers des fichiers html avec colorisation (fait avec webcpp en passant, http://webcpp.sf.net).
          http://julthomas.free.fr/qt/InfosWidget.hpp.html
          http://julthomas.free.fr/qt/InfosWidget.cpp.html

          Et ici voilà un tar.gz avec tout le reste du code (dont la classe qui fait appel à InfosWidget) :
          http://julthomas.free.fr/qt/qtiface.tar.gz

          Je préviens, c'est aps forcement propre partout. C'est même certain. Mais bon, vu qu'il n'y a presque rien dans les classes ça reste très lisible (je pense).
          • [^] # Re: moc OUI

            Posté par  . Évalué à 3.

            Trouvé !

            En fait tu définies deux fois la variables scoreValEdit. Une fois dans le .h:
            QLineEdit *scoreValEdit;

            et une deuxième fois dans le .cpp :
            QLineEdit *scoreValEdit = new QLineEdit("00");


            Donc la deuxième fois c'est une variable locale. C'est elle qui est initialisée et pas la variable global. Ta variable global scoreValEdit auquel tu accèdes dans ta fonction updateScoreValEdit(int val) n'est pas initialisée. Pour que ça marche tu dois remplacer ton code dans to .cpp par :

            mainLay = new QGridLayout();
            titleLab = new QLabel("Title:");
            commentLab = new QLabel("Comment:");
            scoreLab = new QLabel("Score:");
            scoreValEdit = new QLineEdit("00");
            titleEdit = new QLineEdit;
            commentEdit = new QTextEdit();
            scoreSlide = new QSlider(Qt::Horizontal);
            updateBut = new QPushButton("Update");
            • [^] # Re: moc OUI

              Posté par  . Évalué à 1.

              Grrrr alors c'est bien ça !!?! Ok tsss... que j'suis bête.
              Bah merci beaucoup à vous deux en tout cas. Je teste ça ce soir.
              • [^] # Re: moc OUI

                Posté par  . Évalué à 2.

                Moi je conseillerais de préfixer tous les noms de données membres par un m_ (ou toute autre convention):

                QLabel *titleLab;

                devient:

                QLabel *m_titleLab;


                De cette manière, et lorsque le taille du code sera plus importante, il sera bien plus aisé de repérer les variables locales de celles qui appartiennent à l'instance de la classe.

                La lisibilité du code ça permet d'éviter bon nombre de bogues.

                Mes 2 centimes...
  • # Résolu :)

    Posté par  . Évalué à 1.

    Je confirme que c'est bien ça !
    Nikel merci beacoup.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.