tu peut mais je ne trouve pas ca trés objet et trés propre. QThread n'est pas une clas GUI et faire un héritage multiple avecun QThread et un QWidget.... bof bof bof
Pourquoi vouloir faire ca?
Version imprimable
c'est clair, j'essaie de trouver une bonne approche, pour clarifier un peu la mise en place des mutexs si besoin est.Citation:
je ne trouve pas ca trés objet et trés propre
Et surtout pour minimaliser et trouver mon erreur.
Enfin bref, du coup au lieu de créer une QThread "Media", j'ai tout passé dans ma classe principale. Ca évite les public, etc.
Je gagne en nombre de méthode, variable qui se répétait, etc...
et ca ne change pas grand chose en conception.
Disons que la gestion media passe dans la GUI même.
Et pour celle là paradoxalement je n'ai pas besoin de QThread.
Je mets en place la QThread uniquement pour le timer.
Et je verrai ce que ca donne.
Ca va se résumer à un run qui contient un emit.
Ca devrait finir par fonctionner... :triste:
:nono:Citation:
faire un héritage multiple avecun QThread et un QWidget
En effet, j'oublie tout de suite l'idée.
Non, tu ne peux pas mettre la GUI dans un autre thread. Et tout mettre dans la classe principale, c'est plus que déconseillé. Se retrouver avec une grosse classe monolithique sans le moindre rôle exact est une horreur à retoucher (je l'ai fait aussi par le passé et je te recommande vivement de réfléchir à une conception plus propre du style 1 classe <=> 1 responsabilité).
La conception "type" dans ce genre de situation est comme l'a dit IrmatDen de confier à une classe une responsabilité.
Plus tu divises en morceaux la fonction principale de ton programme, plus facile ce sera de rajouter des fonctionnalités, modifier ce qui existe, etc...
Ici, tu dois séparer tout ce qui concerne ton thread du GUI, et les relier grâce au fabuleux système de signal-slot de Qt. Ils ne doivent rien partager d'autre.
????Code:
1
2
3
4
5
6
7
8 void SoundSystem::run() { this->play(5000); emit renderPosition(7); }
ou est la boucle ????????
quand tu fera start, un thread sera créé, puis ces deux ligne seront appélé puis ta thread sera fini!!!!!
faut au moins une boucle
Et si tu veut utiliser l'eventloop tu doit la lancerCode:
1
2
3
4
5
6
7 void SoundSystem::run() { while(aze) { ... } }
Code:
1
2
3
4
5
6 void SoundSystem::run() { ... exec(); }
Attends, avec ou sans boucle meme résultat : que dalle.Citation:
????
ou est la boucle ????????
quand tu fera start, un thread sera créé, puis ces deux ligne seront appélé puis ta thread sera fini!!!!!
La loop est prévu au programme final...
C'est quoi concrètement la différence entre eventloop et thread lancé par le run ? Le run lance un thread qui lance une eventloop qui effectue le contenu du run ?Citation:
Et si tu veut utiliser l'eventloop tu doit la lancer
C'est sûr.Citation:
La conception "type" dans ce genre de situation est comme l'a dit IrmatDen de confier à une classe une responsabilité.
Je ne comprends pas pourquoi vous vous échiner à vouloir mettre une boucle d'événement dans le thread? Quels événements de Qt as-tu à gérer dans le thread? J'ai cru comprendre que c'était un thread pour utiliser FModEx et émettre des infos. C'est tout ou y'a autre chose?
(Note: je n'étais pas là pdt quelques jours, et je suis arrivé avec déjà 3 pages de posts, donc j'ai peut-être raté quelque chose)
Ok, bon résultat, je reviens à mon truc, une GUI, un Sound System, qui contient un run magnifique,
dans ce run un while, et dans ce while un emit, et dans cet emit une variable, fixée à const int 10 pour les besoins du test
Le emit ne fait pas frétiller le SLOT de la GUI d'un poil
et d'ailleurs, aux derniers tests, c'est le SLOT qui est mauvais...
Pourtant, ... il est bien déclaré dans les private slots,
il prend bien les mêmes arguments.
Il est même du même type.
:aie::aie::aie::marteau:
Y a t il une différence de déclaration notable pour les CONNECT, entre un signal émis depuis une QThread et un signal émi depuis son THREAD ?
:?:
Peux-tu coller ici la déclaration + implémentation du thread, la déclaration de la classe contenant le slot, son implé, ainsi que la fonction/classe où le connect est fait?
Ton archive faisant 8MB avec un débit de 50kB, ce sera plus pratique de n'avoir que l'essentiel ;)
Pour ta question, c'est pas vraiment clair. As-tu lu ceci: Signals and Slots Across Threads ?
Oui je l'ai lu, je suis en queued connection, et dans le même cas de figure que l'exemple Mandelbrot.Citation:
Pour ta question, c'est pas vraiment clair. As-tu lu ceci: Signals and Slots Across Threads ?
Citation:
Peux-tu coller ici la déclaration + implémentation du thread,
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 #ifndef SOUNDSYSTEM_H #define SOUNDSYSTEM_H #include <QMutex> #include <QSize> #include <QThread> #include <QWaitCondition> class SoundSystem : public QThread { Q_OBJECT public: SoundSystem(QObject *parent = 0); ~SoundSystem(); protected: void run(); private: bool timecount; signals: void renderPosition(unsigned int position); }; #endif
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 #include "SoundSystem.h" #include <QtGui> #include <fstream> #include <iostream> #include <QKeyEvent> using namespace std; SoundSystem::SoundSystem(QObject *parent) : QThread(parent) { timecount=true; }; SoundSystem::~SoundSystem(){ }; void SoundSystem::run() { while(timecount){ emit renderPosition(7); sleep(1); } }
Citation:
la déclaration de la classe contenant le slot
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 #include "ui_GUI.h" #include "SoundSystem.h" using namespace std; class GUI : public QMainWindow { Q_OBJECT public: GUI(QWidget *parent = 0); ~GUI(); private slots: void rPosition(unsigned int position); private: Ui_GUI interface; SoundSystem *audioThread; signals: void renderPosition(unsigned int position); };
Citation:
son implé
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 #include "GUI.h" #include <stdio.h> #include <QtGui> #include <QtCore> #include <time.h> #include <string> #include <fstream> #include <iostream> using namespace std; GUI::GUI(QWidget *parent) : QMainWindow(parent) { this->interface.setupUi(this); audioThread = new SoundSystem(this); Connect(audioThread, SIGNAL(renderPosition(unsigned int position)), this, SLOT(rPosition(unsigned int position))); }; GUI::~GUI(){ }; void GUI::rPosition(unsigned int position){ this->interface.transportSlider->setValue(77); this->interface.timeLabel->setText(QString("544")); };
Citation:
, , ainsi que la fonction/classe où le connect est fait?
Code:
1
2
3
4 void GUI::rPosition(unsigned int position){ this->interface.transportSlider->setValue(77); this->interface.timeLabel->setText(QString("544")); };
Ah, ben voilou :)
1. connect s'écrit en minusculeCode:Connect(audioThread, SIGNAL(renderPosition(unsigned int position)), this, SLOT(rPosition(unsigned int position)));
2. les signaux/slots ne doivent comporter que les signatures, pas les noms de paramètres
Et pour finir, tu ne démarres pas ton thread dans le snippet posté (à vérifier avec le reste de ton code bien sûr)
PS: pas besoin de ; après l'implémentation des fonctions (ça ne fait rien de mal, mais c'est inutile)
erreur de frappe ici, c est en minuscule dans mon prog,Citation:
connect s'écrit en minuscule
j'ai donc passé :
et ca marche... :wow:Code:
1
2 connect(audioThread, SIGNAL(renderPosition(unsigned int)), this, SLOT(rPosition(unsigned int)));
c'est psychologique, quand je commence à tourner en rond, je met du verni "le point virgule"...Citation:
PS: pas besoin de ; après l'implémentation des fonctions (ça ne fait rien de mal, mais c'est inutile)
merci
Ce n'etait pas une volonté. J'ai essayer de lui expliquer deux façon d'utiliser les thread avec Qt pour lui permettre de choisir celle qui lui correspond.
Puis au bout d'un moment on mélange tout :cry: maintenant avec son code c'est plus claire;)
Donc au final tu va y faire quoi dans le run??
donc au final... j'y lance la lecture, et le compteur.
en fait je vais devoir créer une QThread pour le compteur, instanciée dans la QThread pour la lecture, instanciée dans la GUI
Un truc bizarre pour le son, avec FMODex, ses méthodes ne sont plus asynchrones, une fois "play" lancée, la bande son est jouée... et on peut intervenir sur les canaux, le volume et tout.
DANS LE MAIN THREAD
Là j'ai calé "play", puis mon compteur, dans le run : le compteur marche mais play est zappé. Comme si il était asynchrone.
Bref, je vais faire 2 threads.
Le probleme que j'ai d'emblée, c'est le besoin de passer à mon run des variables venant de la classe d'audessus... puisque je vais dire à mon compteur : récupère la position de la tête de lecture à chaque pas...
Hors la tête de lecture, elle est gérée par ma QThread qui "start" le compteur
j'add de suite, j'avais ca dans mon .proCode:CONFIG += console
Pour cela, crée une classe qui hérite de QThread avec comme paramètres au constructeur les paramètres dont tu parles.
Ensuite, tu n'as qu'à stocker une instance de cette classe dans ta classe de fenêtre principale, et connecter le run du thread au signal que tu veux (appui sur play, ...). Et dans le constructeur de ta classe fenêtre principale, ou dans une autre méthode, tu construis ton instance de thread dérivé en donnant les paramètres que tu désires au constructeur.
exact, merci ;)
En y réfléchissant...
pourquoi veut tu utiliser une thread???
pour pas que l compteur freeze mon appli.
J'ai vérifié, il la freeze bien.
Je n'ai plus accès à la GUI en éxcécution.
:koi:
as tu essayé un QTimer qui à temps régulier va regardé la position de lecture?
http://qt.developpez.com/doc/latest/qtimer.html#details
voici un exemple d'utilisation d'un QTimer.
En je voulais m'en servir pour te faire un exemple avec QThread et c'est la ou je ne comprenais plus pourquoi tu avait besoin d'un thread...
Ici tu as un objet qui à temp régulier va émettre une position et une QImage. Une IHM affichera tout cela.
Dsl j'ai pas eu le courage de faire des commentaire.
Mais si tu as des question pas de problème.
Pour ton problème, en gros tu va regarder la position de lecture à temps régulier
[edit]
nouveau code car oublié de mettre un fond avec painter :aie:
[/edit]
merci mec, je regarderai ca demain (tiens on est déja demain lol...)
décidemment Qt en tous cas.
PS : d'ailleurs avec mon thread-compteur, ca freezait si je ne faisais pas un petit sleep(1), c'est pour lui laisser le temps de repasser la main ou c'est juste anormal ?
Parfait, le QTimer marche parfaitement.
Le seul truc c'est que mon QTimer active le slot de positionnement de la tete de lecture, et qu'a la main via la GUI on peut bouger soi meme la tete de lecture pour se déplacer à différents points du track.
Résultat : si la fréquence du timer est trop forte, il empeche de bouger a la main la tete de lecture.
Ca ne freeze pas, donc pas besoin de thread, mais du coup j'ai fixé une pulse de 1sec pour le timer, en dessous ca n'est pas gérable.
Je pourrai également affiner la tete de lecture en changeant la résolution du slider via QtDesigner, et profiter d'une pulse de 10ms, graphiquement ce serait plus fluide et plus esthétique, mais je serais bloqué pour l'exploration.
En fait il empeche pas, mais il l'acquisition ne se fait pas forcément...
Je vois si c'est pas une question de bon choix du SIGNAL sur le slider...
En fait c'est tout bête, le timer repositionne la tete de lecture toutes les X ms,Citation:
Citation:
Envoyé par ttone Voir le message
Résultat : si la fréquence du timer est trop forte, il empêche de bouger à la main la tête de lecture.
pourquoi?
si je le pulse à 10 ms, je n'ai pas le temps de déplacer la tete que le timer s'est déjà chargé de l'actualiser...
ce que je vais faire:
* placer ce timer dans un thread->run()
* jouer du mutex
voici un autre exemple avec un QObject qui possède une valeur qui avance(peut representer la lecture d'un fichier) et une interaction avec un slider
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 #include <QtGui> class myPosition:public QObject { Q_OBJECT public: myPosition():QObject(),m_position(0) { connect(&m_timer,SIGNAL(timeout()),this,SLOT(avancer())); m_timer.start(100); } QTimer m_timer; int m_position; signals : void position(int); public slots: void setPosition(int pos) { m_position = pos ; } void pause() { m_timer.stop(); } void play() { m_timer.start(100); } void avancer() { m_position++; if (m_position>100 ) m_position =100; emit position(m_position); } }; #include "main.moc" int main(int argc,char ** argv) { QApplication app(argc,argv); QSlider slider; myPosition position; QObject::connect(&slider,SIGNAL(sliderPressed ()),&position,SLOT(pause())); QObject::connect(&slider,SIGNAL(sliderMoved (int)),&position,SLOT(setPosition(int))); QObject::connect(&slider,SIGNAL(sliderReleased ()),&position,SLOT(play())); QObject::connect(&position,SIGNAL(position(int)),&slider,SLOT(setValue(int))); slider.show(); return app.exec(); }
Cool ce code, je suis en train de le regarder, apparemment dans celui ci déjà tu n'as pas de probleme d'interaction avec le slider...Citation:
Fichiers attachés
Type de fichier : rar testTHread.rar (1,5 Ko, 3 affichages)
c'est ca que je dois mettre en place.Citation:
l'avancement est stoppé pendant le drag
Sinon je dois faire un mauvais truc en mettant une pulse lente au QTimer.
Dans mon cas, ca c'est inhérent. Je ne récupère le signal que si l'utilisateur a "released" le slider... le probleme c'est qu'il n'a pas le temps de le relacher que deja le slider s'est repositionné.Citation:
le slider envoie un signal que lorsque tu le bouge avec la souris
J'ai testté d'autres signaux dérivant de QAbstractbutton notamment, comme clicked, mais ca ne marche pas bien, voir pas du tout, bien que la doc Trolltech les mentionne pour un QSlider.
sert toi du dernier code alors ;)
c'est sliderMoved qui freeze automatiquement les autres signaux ?