Accueil
Accueil Le Club Delphi Kylix C C++ Java J2EE DotNET & C# Visual Basic Access Pascal Dev Web PHP ASP XML UML SQLSGBD Windows Linux Autres
logo

precedent    sommaire    suivant   


Un new sans delete ?
auteur : Matthieu Brucher
Dans un code Qt4, on verra souvent un new sans delete associé.

En fait, si une nouvelle instance de QObject est crée et qu'on lui spécifie un parent - le premier argument du constructeur -, c'est ce parent qui sera chargé de la destruction du fils.

La majorité des classes de Qt4 hérite plus ou moins directement de QObject, mais attention, ce n'est pas le cas de toutes. L'indicateur est la possiblité de passer un objet parent au constructeur.

lien : en La classe QObject

Les signaux et autres slots
auteur : Matthieu Brucher
Les signaux et slots sont l'implémentation par Trolltech du pattern observer. Ce pattern permet de prévenir les classes voulant observer un évènement.

Pour utiliser ce système, il faut hériter de QObject, soit directement, soit à l'aide d'un des objets dérivés de QObject. Ensuite, il faut définir la macro Q_OBJECT qui servira à qmake puis à moc pour générer le code nécessaire à l'utilisation de ces fonctions.

Pour déclarer des signaux, il suffit d'indiquer :

    signal:
     void monSignal();
pour que moc génère le code qui va bien et pour que le signal puisse être utilisé. On appelera un signal par :

   emit monSignal();
Ces signaux peuvent être connectés à d'autres signaux ou à des slots. Ces slots sont des fonctions du programmeur qui seront appelées dès que possible.

   public slots:
     void monSlot();
Une fois les slots définis, il suffit de connecter les signaux et les slots entre eux. Comme il s'agit de connexion directe, il n'est pas possible de connecter un signal sans paramètre à un slot avec un paramètre. Pour cela, il faut utiliser entre-temps QSignalMapper.

   connect(this, SIGNAL(monSignal(), somethingElse, SLOT(monSlot()));;
On constatera aussi que signaux et slots ne peuvent pas retourner de valeur, pour l'instant.

lien : en Les signaux et slots
lien : fr Tutoriel sur les signaux et slots de Qt 4

Comment s'interfacent les signaux et les slots?
auteur : Nykoo
Dans la question "Les signaux et autres slots" nous avons vu comment s'interface une connexion entre signaux et slots simples, c'est à dire sans transmission de valeur.
Or, les signaux et slots ont la capacité de se transmettre des données par le biais de leurs arguments.

Prenons l'exemple de la classe QLineEdit de Qt.
Son signal textChanged(const QString&) permet de récupérer le texte présent dans le QLineEdit au moment de l'émission du signal.
De même, son slot setText(const QString&) permet de redéfinir le texte contenu dans le QLineEdit à l'aide d'un objet QString.

Rappel: Il est possible de connecter un signal avec un slot, mais on peut également connecter un signal à un autre signal. Pour créer une connexion signal/slot (ou signal/signal) qui permette la transmission de valeurs, il suffit d'écrire la signature complète de chaque signal/slot dans la fonction connect().
Autrement dit, il faut indiquer le nom des signaux/slots en question, ainsi que les types des arguments qu'ils prennent en paramètre :
Exemple de signature complète


monSignal(QString,int) //signature d'un signal
monSlot(QString,int) //signature d'un slot
connect(objet1,SIGNAL(monSignal(QString,int)),objet2,SLOT(monSlot(QString,int)))
	
       
Attention, car il faut prendre certaines précautions. Dans une fonction connect(), les types des arguments des deux fonctions doivent être compatibles et placés dans le même ordre. Des arguments sont compatibles si le même objet est en jeux. Ex: const QString& est compatible avec QString. Par contre QString* et QString& ne le sont pas. Voici un exemple de connexion avec 2 types compatibles.

connect(this,SIGNAL(monSignal(QString,int)),somethingElse,SLOT(monSlot(const QString&,int)));	
		
Cependant, le signal ou le slot qui est situé dans la partie droite de la fonction connect() peut avoir un nombre d'arguments inférieur ou égal à celui du signal situé à gauche. Par exemple la connexion suivante:

connect(this,SIGNAL(monSignal(QString,int)),somethingElse,SLOT(monSlot(QString)))	
		
est valide. L'argument int sera simplement ignoré.


Comment créer ses propres signaux et slots avec transmission de valeurs?
auteur : Nykoo
Cette question nécessite d'avoir compris la création de signaux/slots simples (sans arguments) décrite dans la question "Les signaux et autres slots"

Pour créer un signal ou un slot avec des arguments il suffit d'ajouter les noms des types dans le prototype:


class myClass : public xxx
{
Q_OBJECT
...
signals:
	void monSignal(type1,type2)
public slots:
	void monSlot(type1,type2);
...
}

		
Ainsi, pour émettre son signal il suffit d'utiliser le mot clef emit.
emmision du signal void monSignal(nom_type)


void fonction()
{
	nom_type t;
	emit monSignal(t);
}

		
La connexion se fera avec un signal ou un slot qui prend un argument de type nom_type.


Comment utiliser les auto-connexions?
auteur : mac&cheese
Sous Qt, les connexions entre les signaux et slots peuvent être mis en place soit manuellement, soit automatiquement, en utilisant la capacité qu'a QMetaObject d'établir des liens entre ces derniers.

Cette partie ne concerne pas les connexions manuelles (traitées à cette adresse), en revanche elle traite de la méthode automatique.

Bien qu'il soit plutôt aisé d'implémenter un slot et de le connecter dans le constructeur, nous pouvons tout aussi bien utiliser l'outil d'auto-connexion de QMetaObject pour connecter le signal clicked() de myButton à un slot dans notre classe.

Bien qu'il soit plutôt aisé d'implémenter un slot et de le connecter dans le constructeur, nous pouvons tout aussi bien utiliser l'outil d'auto-connexion de QMetaObject pour connecter les signals et les slot clicked() :

QMetaObject::connectSlotsByName(QObject *object);
		
Cette fonction du QMetaObject de Qt connecte automatiquement tous slots qui respectent la convention on_Nomobjet_Nomsignal() au signal Nomsignal() correspondant de l'object Nomobjet. Deux conditions sont à remplir:

  • L'objet NomObject doit être un enfant de l'objet passé en paramètre à la méthode connectSlotByName().
  • Les objets (parents et enfants) doivent être nommés avec la fonction setObjectName(const QString& name).
exemple


class MainWindows : public QWidget
{
Q_OBJECT
public :
  MainWindows(QWidget * parent = 0);
 
public slots :
//slot qui sera connecté au signal clicked de l'objet myButton
//par l'autoconnect
  void on_myButton_clicked();
 
};

MainWindows::MainWindows(QWidget * parent):QWidget(parent)
{
 ...
    QPushButton * pButton = new QPushButton("essai auto connect");
    //nom du bouton pour être retrouvé par l'autoconnect
    pButton->setObjectName("myButton");
...
  //auto connection des signaux/slots
  QMetaObject::connectSlotsByName(this);
}
	
Attention: supposons, cette fois-ci, que nous créons notre fenêtre via le Qt Designer et non plus en ligne de code; nous possédons alors un fichier supplémentaire, à savoir, mainwindows.ui. Lors de la compilation, l'outil uic de Qt, se charge de générer le code de la fonction setupUi() de notre fenêtre (mainwindows.ui). Le code généré utilise alors de la même façon :

  • setObjectName(const QString& name) : pour nommer les objets defini dans le *.ui
  • QMetaObject::connectSlotsByName(QObject *object) : pour autoconnecter les objets définis dans le *.ui pendant l'appel à setupUi.
Il est donc possible d'utiliser de la meme façon, les auto-connexions sur une GUI codée à la main que sur une GUI créée à l'aide de Qt Designer (comment utiliser les *.ui)

REMARQUE: Si deux enfants ont le même nom, l'auto-connect ne se fera que sur le premier enfant trouvé.

REMARQUE2: Si QMetaObject::connectSlotsByName est appelé plusieurs fois, les connections générées seront multiples. Lors de l'utilisation d'un *.ui, ne pas oublier que la fonction setupUi appel l'autoconnection

Voici deux exemples à télécharger :


Erreur d'édition des liens underfined reference to 'vtable for xxx'
auteur : Matthieu Brucher
Cette erreur se produit lorsque la partie QObject d'une classe n'a pas été ajoutée à l'édition des liens.

Lors de l'utilisation de la macro Q_OBJECT, on définit un certain nombre de méthodes et de variables statiques. Ces méthodes et ces variables sont implémentées dans un fichier généré automatiquement par qmake à l'aide de l'outil moc. Vous pouvez naturellement créer ce fichier manuellement et l'ajouter pour compilation et édition des liens.

lien : en La classe QObject
lien : en Les signaux et slots

Comment ouvrir une application à partir de Qt ?
auteur : Yan Verdavaine
Qt fournit la classz QProcess. Cette classz permet de contrôler l'exécution d'une application dans un nouveau process. Il est ainsi possible de contrôler :

  • les variables d'environnements par la methode setEnvironement()
  • le répertoire d'exécution par setWorkingDirectory()
  • de lancer l'application par la fonction start
La fonction start qui crée un process enfant (sera fermé si le process parent est fermé) avec pour paramètres :

  • path de l'exécutable
  • liste des paramètres d'entrée de l'exe
  • un mode d'ouverture pour interagir avec l'application par le biais des entréeé/sorties standard
Cette classe possède d'autres fonctions pour lancer une application :

  • QProcess::execute : équivalent à start. Bloquante jusqu'à la fin de l'exécution de l'application lancée
  • QProcess::startDetached : permet de lancer une application dans un process indépendant. Peut donner le pid du process créé
Il est bon de remarquer que ces fonctions:

  • ont des paramètres similaires à ceux de start :
    • path de l'exécutable
    • liste des paramètres d'entrée de l'exe
  • ne donne pas de moyen pour interagir avec le process par le biais des entrées/sorties standard
  • ces deux fonctions sont des fonctions static et peuvent être appelées sans création d'un QProcess. Dans ce cas les variables d'environnement et le répertoire d'exécution sera le même que ceux de l'application courante.
Exemple utilisant QProcess::startDetached


#include <QtGui>

class MyQPushButton : public QPushButton
{
    public :
    //createur.
    //text : text du bouton
    //exe  : commande à exécuter lors de l'appui.
    MyQPushButton(const QString & text,const QString & exe, QWidget * parent = 0):QPushButton (text,parent),m_exe(exe){resize(75, 30);setFont(QFont("Times", 18, QFont::Bold));};
    virtual void mouseReleaseEvent ( QMouseEvent * event )
        {
        //lance la commande dans un process indépendant
        QProcess::startDetached (m_exe);
        }

    private :
    QString m_exe;

};
int main(int argc, char* argv[])
{
    QApplication app(argc, argv);
    QWidget w;
    QVBoxLayout vl(&w);
    //boutton : ouvre grâce au CMD la page vers DVP/Qt
    MyQPushButton bouton1("Ouvrir DVP / Qt","cmd /c start http://qt.developpez.com/",&w);

    //boutton : lance notepad
    MyQPushButton bouton2("Ouvrir notepad","notepad",&w);

     //boutton : lance invite de commande
    MyQPushButton bouton3("Ouvrir invite de commande","cmd" ,&w);
    vl.addWidget(&bouton1);
    vl.addWidget(&bouton2);
    vl.addWidget(&bouton3);
    w.show();
    return app.exec();
}
				
			

Comment interagir avec une application lancée par un QProcess?
auteur : Yan Verdavaine
QProcess permet de lancer des applications externes (voir ici). Elle permet surtout d'interagir avec l'application à la manière d'un pipe au travers des entrées/sorties standard de l'application. Ainsi le troisième paramètre de la fonction start permet de spécifier quel type d'interaction on veut utiliser (par défaut, les deux types sont activés) :

  • mode read : récupération de la sortie standard (stdout) et d'erreur(stderr)
  • mode write : écriture sur l'entrée standard de l'application (stdin)
QProcess utilise les méthodes définies par QIODevice pour faire ces interactions. Pour la récuperation des sorties, il faut faire attention au channel que l'on est en train de lire :

  • pour la sortie standard il faut utiliser : setReadChannel ( QProcess::StandardOutput )
  • pour la sortie d'erreur il faut utiliser : setReadChannel ( QProcess::StandardError)
De plus Qprocess fournit deux signaux intéressants, qui indiquent si des données venant d'une des sortie sont arrivées :

  • readyReadStandardOutput () : des données provenant de la sortie standards sont prêtes à être traitées
  • readyReadStandardError () : des données provenant de la sortie d'erreur sont prêtes à être traitées
Il est aussi possible de faire ces interaction à l'aide de fichiers :

  • setStandardErrorFile : fichier où l'on récupère la sortie d'erreur de l'application lancée
  • setStandardOutput : fichier ou l'on récupère la sortie standard de l'application lancée
  • setStandardInputFile : fichier contenant les donné à envoyer sur l'entrée standard de l'application lancée
voici un example à telecharger : TestQProcess_zip


Comment interagir avec les applications associées par défaut ?
auteurs : Yan Verdavaine, IrmatDen
Qt fournit la classe QDesktopServices et en particulier la fonction static QDesktopServices::openUrl, qui permet d'interagir avec les applications associées par défaut. Elle peut être étendue si nécessaire pour ajouter ses propres handlers pour un schéma donné.


#include <QtGui>

class MyQPushButton : public QPushButton
{
public :
    //createur.
    //text : texte du boutton
    //exe  : commande à executer lors de l'appui.
    MyQPushButton(const QString & text,const QString & url, QWidget * parent = 0):QPushButton (text,parent),m_url(url){resize(75, 30);setFont(QFont("Times", 18, QFont::Bold));};
    virtual void mouseReleaseEvent ( QMouseEvent * event )
        {
        QDesktopServices::openUrl(m_url);
        }

private :
    QString m_url;

};

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);
    QWidget w;
   
    //Action : ouvre l'url ver DVP /Qt
    MyQPushButton bouton1(" Ouvrir DVP / Qt","http://qt.developpez.com",&w);
    //Action : ouvre le fichier texte. /!\ ce fichier doit exister
    MyQPushButton bouton2("Ouvrir fichier txt","c:/test.txt",&w);
    //Action : ouvre l'edition d'un mail avec l'adresse et le sujet remplis
    MyQPushButton bouton3("Envoyer mail","mailto:qt@dvp.com?subject=test envoie mail" ,&w);
   
    QVBoxLayout vl(&w);
    vl.addWidget(&bouton1);
    vl.addWidget(&bouton2);
    vl.addWidget(&bouton3);
    w.show();
    return app.exec();
}

				
			

Comment charger et utiliser dynamiquement une .dll, .so avec Qt ?
auteur : IrmatDen
Qt fournit la classe QLibrary permettant de charger de façon multi-plateformes une bibliothèque dynamique, ainsi que d'en récupérer des pointeurs vers les fonctions exportées.

Après avoir créé un objet de ce type, il faut spécifier le nom de la bibliothèque dynamique à associer sans préciser l'extension (ce n'est plus multi-plateformes sinon ). Il suffit ensuite d'appeler resolve() en fournissant le nom du symbole à trouver. Il est retourné en tant que void*, donc un cast sera bien évidemment nécessaire. Sont aussi fournies des fonctions statiques évitant l'instanciation dans le cas où l'on ne voudrait récupérer qu'un symbole.

Par exemple, admettons qu'une fonction d'une bibliothèque permette de compter le nombre de lettres dans un mot :


typedef int (*StringLength)(char*); // définition du type de fonction
QLibrary lib("string_util"); // création d'un objet QLibrary lié à string_util (.dll, .so ou autre)
StringLength strLength = (StringLength)lib.resolve("strlen"); // récupération d'un pointeur sur notre fonction partagée
if(strLength)
    strLength("QLibrary"); // devrait renvoyer 9... si tout va bien ;)

				
			

precedent    sommaire    suivant   

Consultez les autres F.A.Q's


Les sources présentés sur cette pages sont libre de droits, et vous pouvez les utiliser à votre convenance. Par contre cette page de présentation de ces sources constitue une oeuvre intellectuelle protégée par les droits d'auteurs. Copyright ©2006  Developpez LLC. Tout 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érets. Cette page est déposée à la SACD.

Vos questions techniques : forum d'entraide Accueil - Publiez vos articles, tutoriels, cours et rejoignez-nous dans l'équipe de rédaction du club d'entraide des développeurs francophones. Nous contacter - Copyright 2000..2005 www.developpez.com