[QT] thread et GUI

thread et GUI [QT] - C++ - Programmation

Marsh Posté le 11-06-2012 à 17:39:01    

Salut tout le monde,
 
Voila j'ai plusieurs questions, je galére sur un truc. JE débute sous QT et je transforme un serveur de fichier que j'ai codé en c en serveur ( pareil donc ) mais avec interface graphique.
 
Est-ce possible avec Qt de greffer un fichier .ui sur un thread et aussi est-ce possible de lancer un thread à partir d'un autre thread?
 
Je vais avoir besoin d'un sacré coup de main.
Si besoin je poste mon code.
 
Merci les amis!

Reply

Marsh Posté le 11-06-2012 à 17:39:01   

Reply

Marsh Posté le 11-06-2012 à 18:28:25    

l'interface graphique DOIT être mise à jour par le thread principal. Aucune autre solution et pas moyen de contourner le problème.
C'est la partie en dessous que tu peux threader.

Reply

Marsh Posté le 11-06-2012 à 18:54:28    

Je suis parfaitement d'accord mais la je ne souhaite pas mettre à jour mais bien lancer une nouvelle fenêtre, avec un autre .ui.
 
Ce n'est pas possible non plus?

Reply

Marsh Posté le 11-06-2012 à 19:15:09    

link953 a écrit :

Je suis parfaitement d'accord mais la je ne souhaite pas mettre à jour mais bien lancer une nouvelle fenêtre, avec un autre .ui.
 
Ce n'est pas possible non plus?


 
le .ui c'est juste un fichier xml qui décrit tes widgets, qui sont alors écrits en c++
Si si, tu peux ouvrir toutes les fenetres que tu veux, mais dans le thread principal

Reply

Marsh Posté le 11-06-2012 à 19:47:59    

ok merci beaucoup

Reply

Marsh Posté le 12-06-2012 à 08:33:09    

Autre petite question,
 
Qt propose donc de la programmation événementiel. Une while(1) ( bien pratique en C), n'est donc plus de mise je pense non comment la remplacer "proprement", avec le système de SLOT et CONNECT?
 
Et est-ce pour cela que j'ai une beau : QThread: Destroyed while thread is still running en quittant mon programme?
 voici le code du thread:
 

Code :
  1. int csock; //pointeur valeur de retour de la socket passé en argument au thread plus tard
  2. int connexion = 0;
  3. ThreadAccept::ThreadAccept(QObject *parent)
  4. : QThread(parent)
  5. {
  6. }
  7. ThreadAccept::~ThreadAccept()
  8. {
  9.     ThreadAccept::terminate();
  10. }
  11. void ThreadAccept::run()
  12. {
  13.     /* Declaration des variables de la socket, hsock valeur de retour de la fonction accept, p_int pointeur de retour du maloc*/
  14.         struct sockaddr_in my_addr;
  15.         int hsock;
  16.         int * p_int ;
  17.         socklen_t addr_size = 0;
  18.         //int csock; //pointeur valeur de retour de la socket passé en argument au thread plus tard
  19.         struct sockaddr_in sadr;
  20.        /*création de la socket*/
  21.         hsock = socket(AF_INET, SOCK_STREAM, 0);
  22.         if(hsock == -1)
  23.         {
  24.         ThreadAccept::terminate();
  25.         }
  26.         p_int = (int*)malloc(sizeof(int)); //cast et malloc pour le pointeur i
  27.         *p_int = 1;
  28.         //paramettrage de la socket
  29.         if( (setsockopt(hsock, SOL_SOCKET, SO_REUSEADDR, (char*)p_int, sizeof(int)) == -1 )||(setsockopt(hsock, SOL_SOCKET, SO_KEEPALIVE, (char*)p_int, sizeof(int)) == -1 ) )
  30.             {
  31.                 free(p_int);
  32.                 ThreadAccept::terminate();
  33.             }
  34.         free(p_int);
  35.          /* Configuration */
  36.         my_addr.sin_family = AF_INET ; /* Protocole familial (IP) */
  37.         my_addr.sin_port = htons(port);/* Listage du port */
  38.         memset(&(my_addr.sin_zero), 0, 8);
  39.         my_addr.sin_addr.s_addr = INADDR_ANY ; /* Adresse IP automatique */
  40.         /* bind de la socket */
  41.         if( bind( hsock, (struct sockaddr*)&my_addr, sizeof(my_addr)) == -1 )
  42.         {
  43.             ThreadAccept::terminate();
  44.         }
  45.         /* Démarrage du listage (mode server) */
  46.         if(listen( hsock, 10) == -1 )
  47.         {
  48.             ThreadAccept::terminate();
  49.         }
  50.          addr_size = sizeof(struct sockaddr_in);
  51.         /*corps du programme, allocation dynamique pour la socket acceptation d'un connexion et demarrage d'un nouveau thread*/
  52.         while(1)
  53.         {
  54.             //csock = malloc(sizeof(int));
  55.             if((csock = accept( hsock, (struct sockaddr*)&sadr, &addr_size))!= -1)
  56.             {
  57.                 //lancement deuxieme thread
  58.                threadfichier = new ThreadFichier(csock);
  59.                threadfichier->start();
  60.                 qDebug() << threadfichier->getStartWidget() << endl;
  61.                 // On met a 1 notre variable qui signifie
  62.                 threadfichier->demarrer();
  63.                 if(threadfichier->getStartWidget() == 1)
  64.                 {
  65.                     emit started();
  66.                    qDebug() << "ok" << threadfichier->getStartWidget() << endl;
  67.                 }
  68.             }
  69.             else
  70.             {
  71.                 ThreadAccept::terminate();
  72.             }
  73.         }
  74.         qDebug() << "test2" << endl;
  75.     exec();
  76. }
  77. void ThreadAccept::setPort(int portsocket)
  78. {
  79.     port = portsocket;
  80. }
  81. void ThreadAccept::setCsock()
  82. {
  83. }


Merci


Message édité par link953 le 12-06-2012 à 08:49:45
Reply

Marsh Posté le 12-06-2012 à 10:42:00    

Tu as bien instancié une QApplication dans ton main? si tu ne le fais pas, tu as ce message.
Sinon le terminate() ils disent bien qu'il faut éviter


Message édité par antiseptiqueincolore le 12-06-2012 à 10:42:56
Reply

Marsh Posté le 12-06-2012 à 10:44:06    

Oui le terminate est mauvais. j'ai chercher de mon coté, et j'ai remplacer ma while(1) par une while avec une variable boolean mais même erreur.
 
Qu'entends-tu par le QApplication?

Code :
  1. int main(int argc, char *argv[])
  2. {
  3.     QApplication a(argc, argv);
  4.     QCoreApplication::setApplicationVersion("1.0.5" );
  5.     QCoreApplication::setOrganizationName("Iris Team" );
  6.     QString locale = QLocale::system().name();
  7.     QTranslator translator;
  8.     translator.load(QString("qt_" ) + locale, QLibraryInfo::location(QLibraryInfo::TranslationsPath));
  9.     a.installTranslator(&translator);
  10.     MainWindow w;
  11.     w.show();
  12.     return a.exec();
  13. }


 
Tu parles de ça?


Message édité par link953 le 12-06-2012 à 10:45:54
Reply

Marsh Posté le 12-06-2012 à 10:51:20    

ouais je pensais à ça.
C'est ton mainwindow qui instancie le ThreadAccept?
 
Si tu fais

Code :
  1. int main(int argc, char *argv[])
  2. {
  3.   QApplication app(argc, argv);
  4.   ThreadAccept test;
  5.   test.start();
  6.   return app.exec();
  7. }


 
ça le fait aussi?


Message édité par antiseptiqueincolore le 12-06-2012 à 10:54:22
Reply

Marsh Posté le 12-06-2012 à 11:31:52    

Oui c'est mainwindow.
Je n'ia pas reussi avec ce que tu m'a dis.
Peut être si je poste mon code sa te sera plus clair?

Reply

Marsh Posté le 12-06-2012 à 11:31:52   

Reply

Marsh Posté le 12-06-2012 à 11:40:04    

ouais, un ensemble qui compile? Je promets rien, mais je peux jouer avec

Reply

Marsh Posté le 12-06-2012 à 11:47:22    

Oui sa compile, mais je te préviens il est loin d'être optimisé, ( ni même élégant).
C'est une adaptation d'un programme qui fonction avec une interface graphique mais c'est un projet perso alors bon.. bref voila le code.
 
http://www.toofiles.com/fr/oip/doc [...] chive.html

Reply

Marsh Posté le 12-06-2012 à 11:56:15    

l'ideal serait de greffer le fichier ThreadFichier.ui sur le thread écrit dans ThreadFichier.cpp

Reply

Marsh Posté le 12-06-2012 à 12:28:34    

pardon
vire le exec() du run() si tu n'as pas besoin de la gestion des events, ou ajoute un thread->quit() dans le destructeur de ton mainwindow (ou plutot dans la partie qui arrete le serveur, que tu peux appeler si besoin dans le destructeur de ton mainwindow)


Message édité par antiseptiqueincolore le 12-06-2012 à 12:32:00
Reply

Marsh Posté le 12-06-2012 à 14:01:43    

T'es mon sauveur, j'ai enlevé exec(); et j'ai plus d'érreur. Penses-tu que c'est la meilleurs solution?

Reply

Marsh Posté le 12-06-2012 à 14:50:50    

link953 a écrit :

T'es mon sauveur, j'ai enlevé exec(); et j'ai plus d'érreur. Penses-tu que c'est la meilleurs solution?


 
J'en sais rien...
Regarde du coté du module QtNetwork aussi. Il y a tout ce qu'il te faut.

Reply

Marsh Posté le 12-06-2012 à 15:53:49    

oui je sais mais pour l'instant je préfére me debrouillé avec les thread, c'est déjà du mal...

Reply

Marsh Posté le 13-06-2012 à 16:55:51    

Salut! Dernière question apres je t'embête plus.
 
J'ai deux .ui, le premier est mis directement lors du lancement du projet, le deuxième vient d'être créer mais je ne sais pas comment le lancé.

Reply

Marsh Posté le 13-06-2012 à 17:15:42    

link953 a écrit :

Salut! Dernière question apres je t'embête plus.
 
J'ai deux .ui, le premier est mis directement lors du lancement du projet, le deuxième vient d'être créer mais je ne sais pas comment le lancé.


En fait l'idée de base c'est de créer ton ui, et de créer la classe qui en dérive et que tu utilises.
 
Dans ton .pro, tu rajoutes
FORMS +=   monUi.ui
 
Après tu crées deux fichiers, et tu les ajoutes dans ton .pro
SOURCES += uiDerivee.cpp
HEADERS += uiDerivee.h
 
 
et tu codes ta classe
 
class uiDerivee : public Ui::monUi
{
Q_OBJECT
et tout ce que tu veux dedans
}
 
et quand tu en as besoin, tu instancies ta classe et tu appelles show() dessus
 
edit. la méthode que tu as utilisée, doit marcher aussi. Mais j'ai appris à faire comme ça.Mais ça devait pas être ça ton problème


Message édité par antiseptiqueincolore le 13-06-2012 à 17:22:31
Reply

Marsh Posté le 13-06-2012 à 21:00:30    

Pourtant j'ai essayé ça et pas de resultat concluant...

Reply

Marsh Posté le 13-06-2012 à 21:32:07    

link953 a écrit :

Pourtant j'ai essayé ça et pas de resultat concluant...


quoi donc?
 

Code :
  1. uiDerivee *test = new uiDerivee;
  2. test->show()


ne fait rien?
 
dans le constructeur de ta class uiDerivee, tu as bien un  

Code :
  1. setupUi(this);


?
 
également, je crois qu'il faut que ta classe uiDerivee dérive de QWidget
class uiDerivee : public QWidget, public Ui::monUi  
{
...
};


Message édité par antiseptiqueincolore le 13-06-2012 à 21:34:08
Reply

Marsh Posté le 13-06-2012 à 22:00:05    

Yep j'ai essayer tout ça, c'est donc que j'ai du merder quelque part je vais chercher dans mon code je te tiens au courant demain je pense.
 
En tout cas merci infiniment de ton aide!

Reply

Marsh Posté le 14-06-2012 à 17:39:10    

Bon j'ai essayer tout un tas de chose je m'en sort pas. J'ai réussi niveau fonction a faire ce que je veux mais pas niveau graphique.
Est ce que tu pourrais me filer un coup de main?

Reply

Marsh Posté le 14-06-2012 à 18:14:33    

oui si tu veux
C'est là où je comprends pas, parce dans le code que tu avais posté, ton "a propos de l'application" et "a propos de qt" fonctionnent.
Qu'est-ce que tu veux que je fasse?
 
attends bouge pas je vais te faire un truc avec deux ui. Je te poste ça ce soir


Message édité par antiseptiqueincolore le 14-06-2012 à 18:39:13
Reply

Marsh Posté le 14-06-2012 à 19:41:57    

Bon j'ai repris ton zip.
Dans ton mainwindow j'ai rajouté un bouton "pouet" qui t'ouvre une fenetre modale en cliquant dessus. J'ai pas changé ton ancien code
http://www.toofiles.com/fr/oip/doc [...] modif.html

Reply

Marsh Posté le 14-06-2012 à 20:43:27    

Ok je regarde sa desuite!

Reply

Marsh Posté le 14-06-2012 à 20:49:31    

Ok super. T'es un chef merci infiniment. Je vais bosser ça. Je ne ferme pas le topic au cas ou :D...

Reply

Marsh Posté le 16-06-2012 à 00:13:45    

Je dois vraiment être nul, j'ai compris comment lancer la nouvelle fenêtre mais je n'arrive pas à modifier les labels ou la progresse par que j'ai mis dedans.

Reply

Marsh Posté le 16-06-2012 à 07:15:23    

Dans l'exemple que je t'ai fait, je n'ai pas procédé par aggrégation (comme toi avec tes Ui::MainWindow *ui; et Ui::MainWindow *up;), mais par dérivation de la classe mère, donc tout est accessible directement:
myLabel->setText("hello" );
myProgressBar->setValue(10);


Message édité par antiseptiqueincolore le 16-06-2012 à 07:16:05
Reply

Marsh Posté le 16-06-2012 à 11:35:21    

Je confirme je suis vraiment nul, j'ai vraiment du mal avec le c++. Encore une fois merci à toi.

Reply

Marsh Posté le 17-06-2012 à 15:17:44    

Alors j'ai un dernier petit souci. J'essai d'envoyer un signal depuis mon thread ThreadFichier et de le recevoir dans monFichier.cpp (qui gére l'interface graphique)
 
Je pense que sa vient d'un problèmes de parent.
 
Mon probleme c'est que j'emet un signal que je tente de récuperer dans un slot mais rien ne se passe. Même quand je met qAPP et le slot qui(); rien ne se passe.

Reply

Marsh Posté le 17-06-2012 à 15:48:29    

Je vois hmmmmmm
 [:michaeldell]  
rien
 
A l'exécution, il te dit même pas que ton slot existe pas?
T'as connecté comment? où?

Reply

Marsh Posté le 17-06-2012 à 16:05:04    

La compil' et l'execution RAS. j'ai connecté un signal émit dans le thread qui gére la reception du fichier a un slot dans la classe que tu avais faite myPouet.

Reply

Marsh Posté le 17-06-2012 à 16:09:57    

link953 a écrit :

La compil' et l'execution RAS. j'ai connecté un signal émit dans le thread qui gére la reception du fichier a un slot dans la classe que tu avais faite myPouet.


 
comment t'as écrit le code? A quel endroit? Si je pense à ce que je pense, les pointeurs que tu passes à connect sont-ils non nuls?
quelle version de Qt?

Message cité 1 fois
Message édité par antiseptiqueincolore le 17-06-2012 à 16:29:23
Reply

Marsh Posté le 17-06-2012 à 17:59:46    

antiseptiqueincolore a écrit :


 
comment t'as écrit le code? A quel endroit? Si je pense à ce que je pense, les pointeurs que tu passes à connect sont-ils non nuls?
quelle version de Qt?


 
Alors voci les codes:
 
ThreadFichier.hpp

Code :
  1. #ifndef THREADFICHIER_HPP
  2. #define THREADFICHIER_HPP
  3. #include <QtGui>
  4. #include <QMainWindow>
  5. #include <fcntl.h>
  6. #include <string.h>
  7. #include <stdlib.h>
  8. #include <errno.h>
  9. #include <stdio.h>
  10. #include <netinet/in.h>
  11. #include <resolv.h>
  12. #include <sys/socket.h>
  13. #include <sys/types.h>
  14. #include <arpa/inet.h>
  15. #include <unistd.h>
  16. #include <netinet/in.h>
  17. #include <signal.h>
  18. #include <QApplication>
  19. #include <QWidget>
  20. namespace Up {
  21. class ThreadFichier;
  22. }
  23. class ThreadFichier : public QThread
  24. {
  25. Q_OBJECT
  26. public:
  27.     int getStartWidget();
  28.     ThreadFichier(int& _csock);
  29.     ~ThreadFichier();
  30.     void run();
  31.     void demarrer();
  32. private:
  33.     int csock;
  34.     int startWidget;
  35. signals:
  36.     void setmaximum(int maximum);
  37. };
  38. #endif // THREADFICHIER_HPP


 
Le .cpp

Code :
  1. #include "ThreadFichier.hpp"
  2. #include <string>
  3. ThreadFichier::ThreadFichier(int& _csock)
  4. : QThread()
  5. {
  6.      csock = _csock;
  7. }
  8. ThreadFichier::~ThreadFichier()
  9. {
  10.         close(csock);
  11.         QThread::setTerminationEnabled();
  12. }
  13. void ThreadFichier::run()
  14. {
  15.             int recu = 0;
  16.             int bytecount = 0;
  17.             int taille_buffer = 0;
  18.             char *buffer_md5= 0;
  19.             char *buffer= 0;
  20.             char *buffer_fichier[512];
  21.             /*Reception nom du fichier*/
  22.             if((bytecount = read(csock, &recu, sizeof(recu)))== -1) //Premier recv qui permet de récuperer la taille de la chaine
  23.             {
  24.                 qDebug() << "Erreur reception nom du fichier" << ntohl(recu) << endl;
  25.                 emit setmaximum(ntohl(recu));
  26.             }
  27.             qDebug() << "Taille recu du nom du fichier" << ntohl(recu) << endl;
  28.             taille_buffer = ntohl(recu); /*preparation de la taille du buffer avec le int recu et convertion du reseau vers la machine host*/
  29.             buffer= (char *)malloc((taille_buffer)+1); /* Attribution de la taille buffer en fonction de ce que l'on va recevoir*/
  30.             buffer[taille_buffer]=0;
  31.             if((bytecount = recv(csock, buffer, taille_buffer, 0))== -1) //Deuxieme recv permettant de récuperer dans un buffer adequat la chaine de caractére
  32.             {
  33.                 qDebug() << "Probleme de reception du nom de fichier" << endl;
  34.             }
  35.             qDebug() << "Nom du fichier recu" << buffer << endl;
  36.             if((bytecount = recv(csock, &recu, sizeof(recu), MSG_WAITALL))== -1)
  37.             {
  38.                 qDebug() << "Taille de la chaine de caractere corrompu" << endl;
  39.             }
  40.             qDebug() << "Taille recu " << ntohl(recu) << endl;
  41.             taille_buffer = ntohl(recu);
  42.             buffer_md5=(char *)malloc(taille_buffer);
  43.             buffer_md5[taille_buffer]=0;
  44.             if((bytecount = recv(csock, buffer_md5, taille_buffer, 0))== -1) //Deuxieme recv permettant de récuperer dans un buffer adequat la chaine de caractére
  45.             {
  46.                 qDebug() << "Buffer non recus" << endl;
  47.             }
  48.             qDebug() << "empreinte md5 tablette  " << buffer_md5 << endl;
  49.             //Reception taille du fichier
  50.             if((bytecount = recv(csock, &recu, sizeof(recu), MSG_WAITALL))== -1)
  51.             {
  52.                 qDebug() << "Probleme de reception du fichier" << endl;
  53.             }
  54.             // Taille du fichier
  55.             qDebug() << "Taille recu: " << ntohl(recu) << endl;    //et en bytes %d \n", ntohl(recu),bytecount);
  56.             char path[50] = "/Users/benjaminaubry/Desktop/";
  57.             strcat(path, buffer);
  58.             FILE * fd=fopen(path,"wb" );
  59.             // Reception du fichier par bloc de 512
  60.             while((bytecount = read(csock, buffer_fichier,1))>0)
  61.             {
  62.                 fwrite(buffer_fichier,1,1,fd);
  63.             }
  64.             // On ferme le fichier
  65.             fclose(fd);
  66.             qDebug() << "Fin du thread\n";
  67. }
  68. void ThreadFichier::demarrer()
  69. {
  70.     startWidget = 1;
  71. }
  72. int ThreadFichier::getStartWidget()
  73. {
  74.     return startWidget;
  75. }


 
monFichier.h:

Code :
  1. #ifndef MONFICHIER_H
  2. #define MONFICHIER_H
  3. #include <ui_fichier.h>
  4. #include <QWidget>
  5. #include <ThreadFichier.hpp>
  6. class myPouet: public QWidget, public Ui_monfichier
  7. {
  8.       Q_OBJECT
  9.   public:
  10.    explicit myPouet();
  11.     ThreadFichier *threadfichier;
  12. public slots:
  13.   void maximum(int maximum);
  14. };
  15. #endif // MONFICHIER_H


 

Code :
  1. #include <monFichier.h>
  2. int max;
  3. extern int csock;
  4. myPouet::myPouet()
  5. {
  6.   setupUi(this);
  7.   threadfichier = new ThreadFichier(csock);
  8.   QObject::connect(pushButton, SIGNAL(clicked()), this, SLOT(close()));
  9.   QObject::connect(threadfichier, SIGNAL(setmaximum(int)), this, SLOT(maximum(int)));
  10.   progressBar->setValue(0);
  11.   //pushButton->setEnabled(false);
  12. }
  13. void myPouet::maximum(int maximum)
  14. {
  15.     progressBar->setMaximum(maximum);
  16.     qDebug() << "bonjour" << endl;
  17. }


 
J'essai de d'envoyer depuis le Threadfichier la taille max que je recois de ma socket vers MonFichier pour initialiser une progresse bar avec Qt 4.7.4

Reply

Marsh Posté le 17-06-2012 à 18:01:10    

J'ai tester avec un qDebug pour voir si j'arrivais correctement dans le slot mais non rien ne s'affiche.

Reply

Marsh Posté le 17-06-2012 à 18:57:49    

Tu passes pas dans run() donc ton signal n'est pas émis

Reply

Marsh Posté le 17-06-2012 à 19:08:55    

Pourtant si, je fais appel à ce thread dans une autre classe. La dessus aucun doute il est executer puisque je revois bien mon fichier.


Message édité par link953 le 17-06-2012 à 19:09:05
Reply

Marsh Posté le 17-06-2012 à 19:26:35    

alors bytecount ne vaut pas -1 alors


Message édité par antiseptiqueincolore le 17-06-2012 à 19:28:08
Reply

Marsh Posté le 17-06-2012 à 19:47:21    

nop.
 
Je peux placer le emit n'importe ou rien ne part.

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed