La syntaxe recommandée (pour des raisons d'efficacité) est celle des listes d'initialisation:
Code : Sélectionner tout - Visualiser dans une fenêtre à part AbstractInterface(Automate * automate):m_automate(automate){}
La syntaxe recommandée (pour des raisons d'efficacité) est celle des listes d'initialisation:
Code : Sélectionner tout - Visualiser dans une fenêtre à part AbstractInterface(Automate * automate):m_automate(automate){}
ok donc maintenant, j'ai une classe abstraite (si je bien compris ce que j'ai lu, elle est abstraite parce qu'elle a au moins une de ces méthodes qui est virtual).
Avec cette classe abstraite, je passe en paramètre mon automate donc ma classe abstraite connait l'automate donc toutes ces classes filles devraient connaître elles aussi l'automate.
Dans ma classe automate, j'ai remplacer setInterface(Mainwindow* interface) par setInterface(AstractInterface* interface)
mais du coup comment je dit "l'interface que j'utilise pour le moment est mainwindow" ???
Après comme tu fais tourner les 2 en même temps, il te restera à gérer la concurrence d'accès...voilà pourquoi à la base je te poussais vers 2 exe...dans l'idée que tu n'en ferais tourner qu'un à la fois.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 MainWindow window(automate); automate.setInterface(&window);
ok par contre trois questions
1- dans mon constructeur de abstractInterface, je passe en paramètre l'automate donc les classes filles de abstractInterface devraient connaitre l'automate. Actuellement mon constructeur de mainwindow est:
Est-ce que je dois garder "l'initalisation" de l'automate ici ou pas ? (je pense que oui mais je préfère en être sur
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 MainWindow::MainWindow(Automate* automateParam, QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow), automate(automateParam) { ui->setupUi(this); }
2-actuellement, lorsque j'essaie de compiler j'ai une erreur assez bizarre dans mon constructeur de mainwindow
je ne comprend pas pour il me parle ici de AbstractInterface au lieu de mainwindow (est ce que cela viendrait du fait que je passe un paramètre dans le constructeur de abstractInterface et 2 dans le constructeur de mainwindow ???)erreur : no matching function for call to 'AbstractInterface::AbstractInterface()'
MainWindow::MainWindow(Automate* automateParam, QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow), automate(automateParam)
3-
Me pousser a faire 2 exe: est-ce que dans ce cas je pourrais pas faire un copier/coller de mon projet avec d'un côté l'IHM Qt et de l'autre l'IHM web ???Après comme tu fais tourner les 2 en même temps, il te restera à gérer la concurrence d'accès...voilà pourquoi à la base je te poussais vers 2 exe...dans l'idée que tu n'en ferais tourner qu'un à la fois.
Sois tu remontes la gestion de ce pointeur au niveau de la classe abstraite (à priori une classe d'interface qui n'aurait pas connaissance de l'automate ne servirait pas à grand chose) avec gestion de l'accès des classes filles concrètes à ce pointeur.
Sois tu laisses faire chaque classe concrète (la duplication de code n'est pas très grande, et cela sera peut-être plus simple à comprendre pour toi).
En aucun cas tu ne fais un mix des deux. Même si ça marche, ça compliquera les choses pour tes successeurs (ou même pour toi dans quelques temps), et de plus comme en réalité seul un des deux pointeurs servira, ça va favoriser des erreurs si tu te plantes de pointeur en écrivant du code.
Quand tu construis ta classe dérivée MainWindow, il y a appel de constructeur pour chaque classe mère. Par défaut le compilateur génère automatiquement un appel au constructeur par défaut (celui qui n'a pas d'argument), or ici il n'existe pas, donc il faut que dans ta liste d'initialisation tu appelles explicitement le constructeur défini, qui prend un pointeur sur automate en argument. (ou alors tu oublies la gestion du pointeur au niveau de la classe abstraite). C'est une des bases de la création de classes, donc révision urgente à ce niveau!Envoyé par clairetj
Surtout pas malheureux! Avoir deux copies du même code complique beaucoup la maintenance du code. Il faut penser à reporter chaque modif (évolution ou bugfix) deux côtés, et tu peux être sûr qu'il y aura des oublis!Envoyé par clairetj
Sois tu prends l'option économique du projet qui crée deux exe, sois tu prends l'option "luxe" des 3 projets, mais il ne faut pas dupliquer de code.
Sur ce point uniquement (sur les autres, je n’ai rien à ajouter à tout ce que tu as déjà répondu), perso, je pencherai plus pour faire une interface « composée », c’est à dire, une classe qui reporte elle les évènements dans les deux interfaces instanciées. Mais de toute façon, on n’en est pas encore là.
Sinon, puisque la question a été posée : l’initialisation de l’automate va plutôt être pilotée par le main, plutôt que par l’interface : forcément : même si tu instancies plusieurs interfaces, tu ne veux initialiser l’automate qu’une seule fois.
Enfin, concernant l’organisation du projet : à mon sens, tu as suffisamment peu de code pour l’instant pour ne pas justifier une séparation en plusieurs librairies/exécutables/cibles. Certes, c’est mieux, mais tu pourras toujours le faire après et autant éviter de te rajouter des difficultés là où ce n’est pas strictement nécessaire.
donc comme ça:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 MainWindow::MainWindow(Automate* automateParam, QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow), AbstractInterface(automateParam), automate(automateParam) { ui->setupUi(this); }
Je sais pas si ça peut aider à répondre à la question, mais je récupérer un code (que je n'utiliser pas actuellement) qui me permet de n'avoir d'ouvrir qu'une seule fois mon programme.
Donc par exemple lorsque je compile/exécute une première fois, j'ai mon interface qui s'ouvre normalement mais si je lance une deuxième compilation/exécution (et je n'ai pas fermer la première) rien ne s'ouvre et j'ai un petit message grâce à un qDebug qui me dit "votre programme est déjà lancé"
est-ce que cela peut aidé ???
C’est cool mais ça ne changera rien à l’initialisation de l’automate si tu instancies les deux interfaces (l’interface qt et l’interface web) dans le même programme .
Non, pas comme ça.
Comme te l’a dit therwald, tu as deux solutions :
- soit l’automate est un membre de la classe de base, et dans ce cas, tu n’as pas de membre automate dans MainWindow --> tu utilises celui de la classe de base
- soit l’automate est un membre de MainWindow, et dans ce cas, tu te contentes d’appele AbstractInterface() sans paramètre.
Comme tu as commencé par la première solution, continuons avec.
Si tu veux que la classe MainWindow ait accès au membre m_automate de AbstractInterface, il faut que tu changes sa visibilité :
Dans MainWindow.h, tu supprimes le membre automate.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 protected: // à la place de private: Automate* m_automate;
Et dans MainWindow.cpp, partout où tu utilisais automate, tu utilises m_automate. Cela utilisera le membre m_automate… de AbstractInterface, grâce à l’héritage.
Ton constructeur va être simplement :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 MainWindow::MainWindow(Automate* automateParam, QWidget *parent) : QMainWindow(parent), AbstractInterface(automateParam), ui(new Ui::MainWindow) { ui->setupUi(this); }
Donc là maintenant, ma partie interface est complétement indépendant de ma partie automate ???
Sans le code, ça va être difficile de le confirmer .
Mais néanmoins, tu dois pouvoir le voir toi-même : tant que ajouterAction et ajouterMenu utiliseront des QAction / QMenu, ça ne sera pas indépendant : il va te falloir modifier cela pour que ajouterAction prenne, non pas directement une QAction, mais en réalité les informations suffisantes pour qu’elle puisse construire elle-même le QAction (et idem pour ajouterMenu).
J'utilise actuellement ajouterAction et ajouterMenu ici:
Pour moi, de ce que je comprends, ce qui est vraiment utile à l'automate c'est juste cette ligne:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 void Automate::detectionPortCOM() { int i = 0; ports = QextSerialEnumerator::getPorts(); //recuperation de l'ensemble des ports COM dans une liste qDebug("Detection des Ports COM fait"); if(ports.isEmpty()) { m_interface->ajouterMenu(new QMenu("Pas De Port Disponible")); qDebug("Pas de Port Disponible"); } else { qDebug("Port trouvé, création de la liste en cours"); foreach(QextPortInfo port, ports) // création d'un lien entre chaque port et une action dans le menu { QAction *action = new QAction(port.portName, this); action->setCheckable(true); m_interface->ajouterAction(action); signalMapper->setMapping(action, port.portName); connect(action, SIGNAL(triggered()), signalMapper, SLOT(map())); actions.append(action); i++; nombreTotPortCOM = i; } } qDebug("Affichage dans l'IHM Okay"); connect(signalMapper, SIGNAL(mapped(QString)), this, SLOT(selectPort(QString))); //sélection du port COM } void Automate::selectPort(QString name) { if(!actions.isEmpty()) // lors d'un clic sur un choix de port, celui-ci est marqué par un tick { foreach (QAction *act, actions) { act->setChecked(false); if(act->text() == name) { portCOMName = name; act->setChecked(true); } } } }
après le traitement, je pense qu'il doit être possible de l'effectuer dans la partie interface, pareil pour la selection du port et il faudrait juste renvoyer à l'envoyer le port choisi.
Code : Sélectionner tout - Visualiser dans une fenêtre à part ports = QextSerialEnumerator::getPorts(); //recuperation de l'ensemble des ports COM dans une liste
ma variable ports est de ce type (défini dans le .h en private):
J'avais donc pensé (et j'ai essayé de le faire sans que cela fonctionne) à faire:
Code : Sélectionner tout - Visualiser dans une fenêtre à part QList<QextPortInfo> ports;
du coup, si je déclarais ma variables ports en public et en faisant cela:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 QList<QextPortInfo> Automate::detectionPortCOM() { ports = QextSerialEnumerator::getPorts(); //recuperation de l'ensemble des ports COM dans une liste qDebug("Detection des Ports COM fait"); return(ports);
ne pourrais-je pas faire le traitement dans mon mainwindow ???
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 void Automate::detectionPortCOM() { ports = QextSerialEnumerator::getPorts(); //recuperation de l'ensemble des ports COM dans une liste qDebug("Detection des Ports COM fait");
Il se passe plusieurs chose dans « detectionPortCom ».
En vrac :
- on récupère la liste des ports
- ensuite, pour chaque port
- on crée une action (spécifique à l’interface, donc)
- on ajoute cette action dans le signalMapper
- on connecte le signal triggered de cette action au slot map du signal mapper afin de pouvoir ajouter un paramètre
- on ajoute l’action dans le membre actions
- enfin, on connecte le signal mapped du signal mapper vers le slot selectPort, ce qui permet de sélectionner le port avec le bon argument grâce au signal mapper.
Plusieurs remarques :
- le signalMapper sert seulement à rajouter un paramètre à l’appel. Il est logiquement utilisé par la partie interface, certainement pas par l’automate. Sa place n’est donc pas dans l’automate, mais plutôt dans l’interface
- garder la liste des actions créées dans l’automate n’a pas de sens : c’est à l’interface graphique de gérer ça
- créer l’object QAction dans l’automate n’a pas non plus de sens : c’est une classe qui clairement fait partie de l’interface graphique.
Du coup, je verrai plutôt les choses comme ça :
Tu remarqueras que j’ai renommé les méthodes ajouterMenu et ajouterAction : en effet, leur nom doit correspondre à ce qu’elles sont censé faire et pas forcément ce qu’elles font effectivement*: ajouterPort ajoute un port dans l’interface, le fait qu’il le fasse via une action est un détail d’implémentation.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 void Automate::detectionPortCOM() { int i = 0; m_interface->resetPorts(); // réinitialiser tous les ports, on reconstruit la liste ports = QextSerialEnumerator::getPorts(); //recuperation de l'ensemble des ports COM dans une liste qDebug("Detection des Ports COM fait"); if(ports.isEmpty()) { m_interface->noPortsAvailable(); // signifier à linterface quil ny a aucun port de disponible qDebug("Pas de Port Disponible"); } else { qDebug("Port trouvé, création de la liste en cours"); foreach(QextPortInfo port, ports) // création d'un port dans linterface : elle se débrouille pour lafficher comme elle veut { m_interface->ajouterPort(port.portName); // ajouter le port dans linterface i++; nombreTotPortCOM = i; } } qDebug("Affichage dans l'IHM Okay"); } void Automate::selectPort(QString name) { portCOMName = name; // TODO : vérifier que le nom est valide }
Et dans la partie « interface », tu vas devoir :
- créer tes QAction / QMenu (pas grand chose qui change).
- utiliser le signalMapper pour ajouter le paramètre portName à l’appel (là non plus, pas grand chose qui change)
- connecter le signal mapped() du signalMapper à la méthode selectPort de ton automate.
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager