1

yop,

J'ai un QTableWidget qui contient un tab. Su ce tab (classe FormLadder), j'ai un bouton close, censé fermer son propre tab : http://www.mirari.fr/Wu33[img][/img]

Un clic sur ce bouton appelle une méthode de FormLadder :void FormLadder::on_buttonLadderClose_clicked() { controler->closeLadder(this); }

MAIS !!!

Le controller appelé voudrait, entre autres, détruire ce FormLadder! Normal, yen a plus besoin. Mais si mon FormLadder est édtruit, comment la méthode on_buttonLadderClose_clicked() va-t-elle retourner fiablement ? Ca sera une méthode d'un objet devenu inexistant ><

Question : quelle est la bonne façon de s'y prendre ? Si je détruisais ce tab "de l'extérieur", ça poserait pas de problème, mais comment auto-détruire un objet et les données qui lui sont associées ?

Merci d'avance. smile

2

Alors, la méthode elle-même n'est pas un problème, elle ne fait plus qu'un return (implicit) après l'appel à closeLadder, donc elle n'a plus besoin de l'objet détruit. Mais, attention attention, il est très dangereux d'effacer un QObject dans un slot, parce qu'il peut y avoir d'autres évènements en attente. Pour ça, QObject propose une méthode deleteLater, qui efface l'objet quand les évènements en cours ont été traîtés.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

3

Parfait merci ! C'est exactement ça que je cherchais : The object will be deleted when control returns to the event loop. Je regardais hier s'il était possible de dériver QAplication pour surcharger, s'il était possible, l'event loop, et y insérer la destruction de ce foutu tab. En fait, le mécanisme existe déjà love

4

Si cette question vous a ultra-choqué ("comment il s'y prend comme une merde pour arriver à une problématique de ce genre ?!?!?"), n'hésitez pas à le dire. Bien que la fonction proposée par Kevin, que je subodorais et cherchais à implémenter, me satisfasse à 100%, je suis tout à fair preneur d'une solution avec un autre angle d'attaque. smile

5

Ce type de bogue "use after free" est très courant dans les applications Qt, et la solution est toujours la même: remplacer delete par deleteLater. C'est exactement pour ça que cette méthode existe.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

6

Qu'existe-t-il pour sérialiser ? Je ne voudrais sauver que des données de type de base C++, et des données Qt simples, du genre QString.

=> Bon, je crois que j'ai ma réponse : http://doc.qt.io/qt-5/qvariant.html

7

Euh non, QVariant est pour le typage faible, pas pour la sérialisation. Tu peux aussi sérialiser un QVariant, mais il n'est normalement ni nécessaire, ni utile de passer par ça si tu connais le type des données à sérialiser.

La sérialisation se fait à travers QDataStream. Pour la plupart des classes Qt, la sérialisation est déjà implémentée, si tu veux sérialiser une classe que QDataStream ne connaît pas, tu peux implémenter ton propre surchargement des opérateurs << et >> (cf. "Reading and Writing Other Qt Classes" dans la documentation).
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

8

Ok, merci beaucoup. Je vais zyeuter tout ça. smile

9

Mdr, il suffit de définir operator<< pour les classes perso, terminé c'est fini, c'est absolument génial cette classe, en 10 minutes j'ai implémenté la sérialisationde deux classes de données complexes grin

(bon par contre, j'ai trouvé commenté générer automagiquement les getters/setters qu'après avoir fini ça, donc j'aurais probablement pu mettre 3 minutes au lieu de 10 trigic)

10

Tu vas aussi avoir besoin de operator>> si tu veux récupérer les données que tu as écrites. smile
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

11

Oui tout à fait, je l'ai pas encore écrit mais ça me semble tout aussi simple.

12

Effectivement.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

13

J'ai des soucis récurrents avec QTableWidget.

Entre autres, les labels horizontaux (les titres de colonnes) qui doivent hériter de la classe Shrödinger.
Voici mon code :LadderUi::LadderUi(QWidget* parent) : QWidget(parent), ui(new Ui::LadderUi) { ui->setupUi(this); // Create and set the columns titles labels << "Name" << "Race" << "Score" << "Victories" << "Defeats"; ui->tableLadder->setHorizontalHeaderLabels(labels); }
Rien de sorcier. Tout le reste est paramétré dans Designer, sauf les titres des colonnes, car dans le constructeur ça les fait apparaitre de temps en temps.

Un screen de Designer puisqu'on en parle : sZyO

Et le résultat sur l'appli : lwtn

On voit une ligne de données rentrée dans le tableau, mais nulle trace des colonnes.

Il s'agit d'un "fork" d'un de mes projets, ce code-là n'a pas changé, et "avant ça marchait". Je ne sais plus ce que j'avais fait pour que ça marche d'ailleurs, j'avais ramé, mais j'avais fini par y arriver.

Que faire ?

14

Un test case minimaliste qui reproduit le problème : http://www.mirari.fr/M5rn
Windows 7, Qt 5.4.1, MinGW 32 bits bundlé avec Creator.

Meme résultat sous Debian testing (Jessie), Qt 5.3.2.

Ca doit etre moi qui rate un truc sad

15

Dans ton fichier ladderui.ui, je vois:
       <attribute name="horizontalHeaderVisible">
        <bool>false</bool>
       </attribute>
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

16

Oui, j'ai fini par voir ça. Et c'est bien là que ça déconne, comme le montrent mes screens, parce qu'après avoir joué avec les checkboxs de Designer, j'ai réussi à faire réapparaitre les labels.

J'en conclus que :
- Designer est buggué sur ce point
- la doc est trompeuse, car elle laisse penser que définir les labels les fait apparaitre : The simplest way to create the headers is to supply a list of strings to the setHorizontalHeaderLabels() and setVerticalHeaderLabels() functions.

Et je n'ai pas trouvé de méthode setVisible() pour les labels, alors que c'est paramétrable (théoriquement) dans Designer : Header::horizontalHeaderVisible: No documentation available.

Enfin c'est pas très grave, mais je sais pas trop où reporter.
Par contre, si tu veux le faire, je suis sûr qu'on écoute plus un mainteneur de KDE de longue date qu'un inconnu au bataillon cheeky

17

@Kevin -> suite à ta réponse, un objet défini comme ça :class Ladder: public QObject { public: Ladder(QString name); ~Ladder(); ... private: Q_DISABLE_COPY(Ladder) ... };
alloué sur le heap, sans autre héritage, et qui utilise deleteLater(), c'est pas un problème ?

Sinon, après la problématique à laquelle répond deleteLater(), on se retrouve avec une autre : comment faire pour détruire sans souci quelque chose qui contient un QWidget ?

J'espère que comme ça, ça marche.

18

Folco (./17) :
@Kevin -> suite à ta réponse, un objet défini comme ça :
class Ladder: public QObject
…
alloué sur le heap, sans autre héritage, et qui utilise deleteLater(), c'est pas un problème ?

Je ne vois aucun problème là.
Sinon, après la problématique à laquelle répond deleteLater(), on se retrouve avec une autre : comment faire pour détruire sans souci quelque chose qui contient un QWidget ?

Un objet ne doit jamais contenir un QWidget, mais seulement un pointeur QWidget *. Comme ça, si ton QWidget est une fenêtre (donc n'a pas de parent), tu peux utiliser deleteLater sur le QWidget * dans ton destructeur, sinon le mieux est de ne pas y toucher (il sera détruit automatiquement quand le widget parent le sera).
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

19

Ok, merci.

Bug reporté ici : https://bugreports.qt.io/browse/QTCREATORBUG-14189
On va mesurer le temps de réaction/correction. cheeky

20

J'ai cherché sans succès une méthode de Q(Core)Application qui permette de broadcaster un event à tous les QObject créés par l'application.
Ca permettrait aux objets qui le souhaitent de s'enregistrer élégamment les uns auprès des autres, sans variable globale. Ca existe ?

21

Émettre un signal auquel les objets intéressés peuvent se connecter (avec un slot), ça ne te suffit pas?
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

22

Ca demande que l'émetteur connaisse l'adresse des destinataires. Idéalement, j'aurais aimé éviter. Je vais totu simplement procéder autrement, merci.

23

Dans mon idée, c'est aux destinataires de se connecter au signal de l'émetteur. (C'est comme ça que fonctionnent les signaux et slots Qt normalement.) Ainsi, l'émetteur "connaît" les destinataires dans le sens où il y a une liste des connections quelque part dans les membres privés de QObject, mais c'est géré à l'intérieur de Qt, ton code ne doit pas s'en occuper.

Mais peut-être qu'avec un exemple, je verrais mieux ce que tu veux faire?
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

24

Bon, je m'y suis pris complètement autrement, d'une façon certainement plus Qt-compliant. J'essaye de me plier à la philosophie du truc.

pwic, j'ai un souci avec QCloseEvent, ou la manière dont on ferme une fenêtre. J'ai lu (et reeeelu) le tutorial d'une simple application, je ne vois pas ce qui cloche, et pourtant...
// Post a close event, which will cause MainWindow::closeEvent() to be called later void MainWindow::on_buttonQuit_clicked() { // The event loop takes the ownership of the event and frees it qApp->postEvent(this, new QCloseEvent; }

Donc dans ma MainWindow, j'ai un bonton "quit" qui est censé quitter, en postant un QCloseEvent. Ca a l'air tellement simplissime que je ne vois pas ce qui cloche.
Je ne trifouille pas les flags de la mainwindow, je ne redirige rien vers ci ou ça, donc je ne sais pas vers où chercher ><

Une idée stp ?

25

Normalement, on utilise QCoreApplication::quit() pour quitter l'application.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

26

Ok, mais je ne vois pas ce qui ne marche pas ><
Et je ne veux pas fermer comme ça, vu que je veux intercepter le close event :void MainWindow::closeEvent(QCloseEvent* event) { if (!controller->closeAll()) { event->ignore(); } }

Même quand je vire le bloc if(), et que je fait un event->accept(), ça ne fait rien. Je dois faire un close() pour que ça fonctionne. Pourtant, l'exemple d'ici montre une surdéfinition de closeEvent qui n'en fait pas plus :void MainWindow::closeEvent(QCloseEvent *event) { if (maybeSave()) { writeSettings(); event->accept(); } else { event->ignore(); } }
Et j'ai tracé l'exécution, l'event est bien envoyé quand je clique sur mon bouton.

27

Il faut appeler close() et ce sera Qt qui activera ton closeEvent et réagira en conséquence. Poster directement le QCloseEvent ne sert à rien, c'est seulement le mécanisme pour accepter ou rejeter la fermeture, mais la réception de l'évènement ne ferme rien, la logique est dans la méthode close.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

28

Ok, je comprends le mécanisme alors. Donc mon bouton doit juste appeler close(), et mon closeEvent() custom acceptera ou rejetera l'event.

Mais alors, quel intéret de pouvoir générer un poster un event s'il est "inactif" ? C'est dommage, parce que je trouve ça très élégant de générer des events dans un programme basé sur l'évènementiel...

Merci en tout cas, tu me débloques sur ce point. smile

29

Bon ben non seulement j'ai compris, mais en plus ça marche du tonerre maintenant, eventClose() permet d'intercepter la fermeture de l'application par le WM, et de l'annuler au besoin, c'est absolument parfait love. Comme les vrais, quoi tripo
Merci encore happy

30

Folco (./28) :
Mais alors, quel intéret de pouvoir générer un poster un event s'il est "inactif" ? C'est dommage, parce que je trouve ça très élégant de générer des events dans un programme basé sur l'évènementiel...

L'évènementiel de Qt passe principalement par les signaux et les slots. Le système des events sert essentiellement pour les évènements issus du système, et postEvent n'est utile que très rarement (pour simuler par exemple un appui d'une touche).
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité