60

Kevin Kofler (./59) :
mais il le saura faire bientôt

Très jolie forme de l'ancien français pour il saura le faire bientôt cheeky

Sinon merci. Tant mieux, que quelqu'un bosse dessus. Je dois dire que je suis assez surpris, parce que ça me semble être des fonctionnalités assez basiques pour un tel programme, ça accroit la productivité, et ça réduit les risque d'erreur.

61

Un italianisme. 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é

62

ok ^^

Sinon, question, quand je réimplémente ce genre de chose : void changeEvent(QEvent* event);
Dois-je le mettre dans la section public de ma classe, ou dans une section protected slots ?
Je sais pas trop comment déterminer ça. C'est la doc de Qt qui dicte la visibilité d'une part, et l'emploi du mot slots d'autre part ? Je sais pas trop bien quelle règle suivre.

(en l'occurence, je veux utiliser cet event pour une classe qui dérive de QMainWindow. J'essaye de réécrire mon projet sans utiliser Qt Creator/Designer pour bien comprendre tous les mécanismes. C'est super intéressant)

63

C'est à mettre dans une section protected. changeEvent n'a pas besoin d'être un slot, ça ne passe pas par le système de signaux et slots, mais par l'appel d'une méthode virtuelle (principalement pour des raisons de performance).
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é

64

Merci !

Ah, et est-ce que, si je dérive une classe dérivant de QWidget et que j'intercepte changeEvent, je dois appeler le handler d'origine, comme ça ?
void MainWindow::changeEvent(QEvent* event)
{
    QWidget::changeEvent(event);
    if (event->type() == QEvent::LanguageChange)
        translate();
}

Comme tu vois, j'intercepte l'event pour traduire les chaines de ma classe, mais je dois aussi retransmettre l'event, non ?

65

Oui, il faut effectivement appeler QWidget::changeEvent.
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é

66

oh yeah ! deviendrais-je bon ? grin
Bon, grand merci en tout cas, en 3 jours j'ai appris à faire un CMakeLists.txt rudimentaire, à coder le squelette d'une appli Qt sans Creator, et à faire mes premièes UI sans Designer. Je suis content, ça m'apporte beaucoup top

Sinon, j'ai lu la doc de CMake à propos des variables standard et des variables en cache. Si je comprends bien l'utilité de ce cache, il sert à recevoir les variables qu'un premier run de CMake fera sur un projet, c'est ça ?
Et comment je sais quelles variables CMake va être capable de renseigner tout seul ?
Et quelles sont les variables que je vais devoir redéfinir moi-même ?

67

Dans le cas idéal, les valeurs par défaut sont bonnes. smile Les valeurs modifiables sont normalement documentées quelque part, par exemple, il y a une liste des répertoires de destination configurables de CMake dans la page man de CMake, et celles rajoutées par Extra CMake Modules (ECM) sont aussi documentées quelque part. Si tu définis tes propres variables CACHE, tu devrais aussi les documenter. (La définition de la variable te permet de mettre une description en une ligne qui apparaîtra dans le dialogue de KDevelop et dans le CMake GUI. Si ça ne suffit pas, un fichier INSTALL(.txt) ou semblable est un bon endroit pour documenter les options de compilation.) Il y a par exemple des projets (surtout des bibliothèques) qui sont compilables pour Qt 4 ou Qt 5 au choix, il y a généralement un flag de type QT4_BUILD ou QT5_BUILD (booléen) ou encore QT_VERSION (entier).
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é

68

Ok, merci bien. Je commencerais à être presque à l'aise avec tout ça, ça devient un vrau plaisir. J'en ai surement pas une utilisation très avancée cependant, je débute, mais plus facilement que j'aurais pensé. smile

Maintenant, j'entrevois la puissance des signaux et des slots. Ca évite notamment bien du travail, car si je veux qu'un objet distant me transmette une donnée, j'ai juste à lui faire émettre un signal vers un de mes slots, pas besoin de dériver l'objet distant pour lui apprendre à causer à un objet de mon type.
C'est juste génial love

Par contre, une question de parentalité : pourquoi les parents des QWidgets sont-ils des QWidgets, et non des QObjects ? C'est pas grave, mais c'est juste pour comprendre, j'ai lu la doc sur la hiérarchie des objets dans un programme, donc je comprends pas trop pourquoi dans une application, on passe de l'un à l'autre.

Sinon voici une petite classe, qui étend QPushButton pour lui associer une action. Je poste le code en PNG, parce que la coloration syntaxique de KDevelop déchire sa race de sa grand-mère embarrassed
TPushButton.hpp
PIZQ
TPushButton.cpp
lKyk

Question :
- est-ce qu'il vaut mieux utiliser les macros SIGNAL/SLOT, ou la forme &classe::méthode des connections ? Ou est-ce qu'on s'en fout ? En fait, je ne sais pas pourquoi la méthode est surchargée, il y a des cas où on ne peut pas faire sans l'un ou l'autre ?
- la méthode se surcharge avec un "functor", c'est une simple fonction comme en C, ça ?
- j'appelle le slot "trigger" quand on clique sur le bouton, est-ce que ça pourrait etre un problème d'appeler directement le signal "triggered" de l'action ? ou est-ce que c'est strictement identique ?
- est-ce qu'un destructeur d'objet qui a établi des connexions doit les détruire manuellement dans le destructeur, ou est-ce automatique ?

Merci d'avance hehe

69

Folco (./68) :
Par contre, une question de parentalité : pourquoi les parents des QWidgets sont-ils des QWidgets, et non des QObjects ? C'est pas grave, mais c'est juste pour comprendre, j'ai lu la doc sur la hiérarchie des objets dans un programme, donc je comprends pas trop pourquoi dans une application, on passe de l'un à l'autre.

Parce que la notion d'appartenance pour les QWidgets est particulière: En plus de l'appartenance de QObject, elle signifie aussi que le widget est contenu graphiquement dans son parent. (En particulier, une fenêtre n'a pas de parent.) Un widget ne peut pas être contenu dans un objet non graphique.

Si tu veux absolument insérer une fenêtre dans une hiérarchie de QObject, quelque chose comme ça devrait fonctionner:
class WidgetWrapper : public QObject, public QScopedPointer<QWidget> {
  Q_OBJECT

  public:
    WidgetWrapper(QWidget *wrapped, QObject *parent = nullptr) : QObject(parent), QScopedPointer<QWidget>(wrapped) {}
    virtual ~WidgetWrapper() {}

  private:
    Q_DISABLE_COPY(WidgetWrapper)
}

et ensuite là où tu voudrais écrire new MyWidget(parent), tu écris new WidgetWrapper(new MyWidget(), parent) à la place.
- est-ce qu'il vaut mieux utiliser les macros SIGNAL/SLOT, ou la forme &classe::méthode des connections ? Ou est-ce qu'on s'en fout ? En fait, je ne sais pas pourquoi la méthode est surchargée, il y a des cas où on ne peut pas faire sans l'un ou l'autre ?

Les macros SIGNAL/SLOT étaient la seule forme jusqu'à Qt 4, et a été gardée surtout pour des raisons de compatibilité. La nouvelle forme est la version C++11 (enfin, elle est aussi permise en C++98 si le slot n'a pas plus de 6 arguments, le C++11 rajoute les templates variadiques, ce qui permet un nombre arbitraire d'arguments). L'avantage de la nouvelle forme est qu'elle permet de vérifier les types en temps de compilation au lieu de travailler avec des chaînes de caractéres (les macros SIGNAL et SLOT stringifient (!) leur contenu, toutes les vérifications de type sont faites lors de l'appel) et est donc aussi plus rapide. Le désavantage est qu'il faut préciser le nom de la classe. De plus, (avantage) tant qu'il y a une seule surcharge de la méthode, on n'a pas besoin de préciser les arguments, mais (désavantage) quand il y en a plusieurs, choisir la bonne méthode devient compliqué (et on ne peut pas utiliser les arguments optionnels avec une valeur par défaut).

Cf. http://wiki.qt.io/New_Signal_Slot_Syntax.
- la méthode se surcharge avec un "functor", c'est une simple fonction comme en C, ça ?

Un foncteur est un objet qui implémente operator(). Ça peut être un simple pointeur de fonction (mais en général, dans ce cas, il vaut mieux utiliser une méthode avec la syntaxe précédente), mais aussi une expression lambda C++11 (c'est surtout pour ça que cette syntaxe existe), un objet tr1::bind ou n'importe quel objet qui implémente un operator() avec les bons arguments.
- j'appelle le slot "trigger" quand on clique sur le bouton, est-ce que ça pourrait etre un problème d'appeler directement le signal "triggered" de l'action ? ou est-ce que c'est strictement identique ?

Connecter un signal directement à un autre est possible en théorie, mais tu es censé faire ça uniquement pour connecter un signal d'une autre classe directement à un signal de ta classe, pas l'inverse! Tu n'es pas censé appeler directement un signal d'une autre classe. Rien ne te dit que le slot trigger ne fasse pas plus qu'émettre le signal triggered. Donc la seule solution conforme á l'interface voulue est de connecter le signal reçu au slot trigger de l'action.
- est-ce qu'un destructeur d'objet qui a établi des connexions doit les détruire manuellement dans le destructeur, ou est-ce automatique ?

C'est automatique.
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é

70

Ok, merci pour ces clarifications, c'est vraiment excellent tout ça love
Sinon j'ai raté la page sur la New Signal Slot Syntax, elle doit pas être très bien référencée dans la doc (j'utilise Assistant et ma doc locale), parce que j'ai du^lire tout le reste qui concerne les signaux et les slots.
Merci encore et vivement ce soir ! tongue

71

Ok, j'ai trouvé ça dans la page que tu m'as linkée :
It is possible to connect to any member function of QObject, not only slots.
Ca veut dire qu'on a plus besoin de "private slots", les trois sections habituelles de visibilité des méthodes sont suffisantes pour un slot ?

Il y a ce bout de code en exemple :
QTcpSocket '''socket = new QTcpSocket;
Ca veut dire quoi cette triple apostrophe, je crois bien que c'est pas la première fois que je croise ça, mais je comprends pas ce que ça signifie ^^

72

Folco (./71) :
Ok, j'ai trouvé ça dans la page que tu m'as linkée :
It is possible to connect to any member function of QObject, not only slots. Ca veut dire qu'on a plus besoin de "private slots", les trois sections habituelles de visibilité des méthodes sont suffisantes pour un slot ?

Avec la nouvelle syntaxe, oui.
Il y a ce bout de code en exemple :
QTcpSocket '''socket = new QTcpSocket;Ca veut dire quoi cette triple apostrophe, je crois bien que c'est pas la première fois que je croise ça, mais je comprends pas ce que ça signifie ^^

C'est une erreur de conversion de wiki. C'est censé être une étoile (pointeur). Certains wikis utilisent *foo* pour le gras, d'autres '''foo''', et apparemment la conversion a été faite bêtement. grin
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é

73

Ah ok, un mystère de résolu grin

74

Puisqu'il ne peut y avoir qu'une QMainWindow par application, est-ce qu'il y a une macro pour la récupérer, comme qApp par exemple ?
Sinon, ça veut dire qu'il faut se ballader un pointeur un peu partout, ou en définir un global ?

Non parce que des solutions comme ça ou encore comme ça, si elles sont rigoureusement justes, je veux meme pas en entendre parler sick

75

Folco (./74) :
Puisqu'il ne peut y avoir qu'une QMainWindow par application

Dit qui? Dans KTIGCC, je crée plusieurs QMainWindow (la vraie fenêtre principale et chaque fenêtre source (les sources ouvertes hors projet)) et ce n'est aucun problème, ni avec Qt 3, ni avec Qt 4. Je n'ai pas encore essayé avec Qt 5, mais la documentation ne l'interdit nulle part, donc je ne vois pas pourquoi ça ne fonctionnerait plus.

Et pour trouver la fenêtre principale, je passe un pointeur vers la fenêtre principale à chaque fenêtre source dans le constructeur de SourceFileWindow.
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é

76

Ah, ben tu vois j'étais dans l'erreur. Ce sont les Q[Core|Gui]Application qui sont uniques.
Donc ok, pour les mainwindows.
Ok, t'as choisi le passage d'un pointeur, j'imagine que la fenêtre racine a une "parent window" à nullptr, tout simplement.
Pour le moment, j'ai mis une var globale, ça permet d'éviter de multiplier les accesseurs, et ça devrait etre la seule var globale, donc ça me va comme ça vue tout ce que ça simplifie.

Merci bien. smile

77

Folco (./76) :
Ok, t'as choisi le passage d'un pointeur, j'imagine que la fenêtre racine a une "parent window" à nullptr, tout simplement.

Dans KTIGCC, elle est d'une classe différente, parce que j'ai une seule fenêtre projet (la vraie fenêtre principale) et n (0, 1 ou plusieurs) fenêtres source (qui ont aussi un menu, une barre d'outils et une barre d'état, d'où l'utilisation de QMainWindow).
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é

78

Ah ok.

79

Kevin Kofler (./69) :
De plus, (avantage) tant qu'il y a une seule surcharge de la méthode, on n'a pas besoin de préciser les arguments, mais (désavantage) quand il y en a plusieurs, choisir la bonne méthode devient compliqué (et on ne peut pas utiliser les arguments optionnels avec une valeur par défaut).

Tiens, je viens d'être confronté à ça, j'ai pas trouvé la solution dans la doc.
J'avais void méthode() et void méthode(int i), et ça compilait pas à cause des appels à la méthode sans paramètres.
J'ai pas su comment écrire la connexion, du coup j'ai renommé la méthode. Il y a une vraie solution à ça ?

80

Essaie (void (MaClasse::*)(int))&MaClasse::méthode. Ou alors utilise l'ancienne syntaxe.
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é

81

Ah bien vu, ça marche, merci top

82

La parentalité des QObject/QWidget, c'est la mort des delete/destructeurs.

83

Question : Comment obtenir ce genre de log valgrind avec Qt ?
==9795== LEAK SUMMARY:
==9795== definitely lost: 7,510 bytes in 61 blocks
==9795== indirectly lost: 184,690 bytes in 2,680 blocks
==9795== possibly lost: 4,676 bytes in 83 blocks
==9795== still reachable: 148,659 bytes in 500 blocks
==9795== suppressed: 0 bytes in 0 blocks

Réponse : afficher 3 widgets à l'écran
cheeky

84

Bof, même pas 300 ko en tout... c'est petit joueur, moi je dis hehe
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

85

quoi sérieux ? mais c'est dégueulasse ! grin

86

non mais c'est clairement pas normal, je veux juste dire que j'ai déjà vu bien pire grin
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

87

pouet,

J'utilise une QComboBox. Dedans, on ajoute des QString, ok. Mais les indexes, j'aime pas ça. Je crée donc les éléments avec cette méthode.
Comme UserData, je mets un QVariant::fromValue de l'objet référencé par l'item ajouté.

J'aimerais, connaissant l'item courant de mon QComboBox, pouvoir récupérer le pointeur, et le caster vers mon objet de départ. C'est à dire, obtenir une correspondance item <-> objet, sans index, donc indépendamment de la manière dont est triée la liste du Combo.

Comment faire ? Est-ce qu'un static_cast<Objet_de_depart*>(combo->itemAt(i).currentData) ferait l'affaire ? Est-ce safe, est-ce la méthode prévue ?
Ou dois-je maintenir une QList<le_type_d'objets_ayant_une_entree_dans_le QComboBox>, en parallèle du Combo, pour obtenir le pointeur kivabien quand je reçois le signal "l'item X est le nouvel item courant" ?


ps -> les seuls pointeurs que QVariant connaisse, c'est const char*, même pas void* sad

88

Folco (./87) :
Comment faire ? Est-ce qu'un static_cast<Objet_de_depart*>(combo->itemAt(i).currentData) ferait l'affaire ? Est-ce safe, est-ce la méthode prévue ?

Presque. La syntaxe correcte est:
combo->currentData().value<le_type_de_depart>()
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é

89

Ah super, merci, je suis débloqué ! boing

90

Autre chose, je suis dérouté parce que ça m'a l'air très bête...
J'ai ce code, dans le constructeur de ma MainWindow (template Creator) : connect(MainWindow::ui->projectList, &QComboBox::currentIndexChanged, this, &MainWindow::changeCurrentProject);
L'erreur de compilation est : no matching function for call to 'MainWindow::connect(QComboBox*&, <unresolved overloaded function type>, MainWindow*, void (MainWindow::*)(int))'
Pourtant, projectList est bien un QComboBox, il dispose bien du signal currentIndexChanged, donc je vois pas ce qui cloche...

J'ai bien inclus le header de QComboBox, et euh... ben justement, ça me semble tellement con que je sais pas par où chercher confus


Ca compile avec la version ancienne des signaux/slots : connect(ui->projectList, SIGNAL(currentIndexChanged(int)), this, SLOT(changeCurrentProject(int)));
Mais je vois pas ce qui déconne dans ce que j'ai écrit, meme si je pense que c'est dû à cet argument que j'arrive pas à passer ><