Salut,
Quelqu'un a-t-il déjà utilisé l'api QT Jambi pour java (QT c'est l'API graphique utilisée par KDE)?
Juste pour avoir quelques retours d'expérience...
Merci d'avance.
Salut,
Quelqu'un a-t-il déjà utilisé l'api QT Jambi pour java (QT c'est l'API graphique utilisée par KDE)?
Juste pour avoir quelques retours d'expérience...
Merci d'avance.
C'est du stable et bien foutu (QT inside oblige).
Ensuite je n'ai que peu joué avec QT et jamais avec Jambi, mais je ne pense pas qu'il y ait de peur à avoit, les Trolls font du très beau boulot (quand tu vois ce qui est en train de se préparer pour KDE4)...
Bref il n'y a pas de peur à avoir.
OK, je ne connais pas du tout au niveau de la programmation. Comparé à Swing, quels sont les avantages / inconvénient?
Pas de grosse différence. Le système des événements et un peu différent et je me souviens que QT était plus chiant à customiser que Swing mais sinon... Je ne sais pas pour Jambi, mais la version C++ obligeait aussi à utiliser les classes URL, String, etc. de QT. C'était pratique en C++ mais si en Java il faut faire pareil ça peut être agaçant.
Arf, j'ai trouvé ceci dans leurs exemples:
Gros problème de conception
Code : Sélectionner tout - Visualiser dans une fenêtre à part textEdit.document().contentsChanged.connect(this, "documentWasModified()");(on ne fait pas de l'introspection pour ça, on utilise le pattern command)
En quoi c'est un problème de conception ? C'est chiant pour le refactoring mais à part ça... le système de slots et signaux de QT est assez sympa globalement, et moins lourd à gérer que des pelletés de listeners.
Bah oui, le refactoring, le non "compile-checked". Et c'est beaucoup plus lent au runtime (ça ce n'est qu'un détail).Envoyé par Gfx
En Java, les pointeurs de fonctions se font par le design pattern "commande" (si c'est bien le nom "commande" si je ne me trompe pas, mais bon je sais que tu vois de quoi je parle ^^).
Non, ce n'est pas beaucoup plus lent au runtime. Toutes les animations que j'écris utilisent le TimingFramework et donc la reflection et l'introspection et on obtient quelque chose d'extrêmement fluide à 60 fps sans aucun problème. Cela fait très longtemps que les performances de reflection sont excellentes.
Et tes arguments n'expliquent pas en quoi c'est une mauvaise conception. Le compile-time checking par exemple est certes très utile, mais pour un cas comme celui-ci, en rien vital.
Arf, j'avais pas envie d'écrire le test, mais bon tant pis...Envoyé par Gfx
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 package reflex; interface MonInterface { void method(); } public class TestReflex implements MonInterface { public void call(String method) throws Exception { getClass().getMethod(method).invoke(this); } public void method() {} public static void main(String... args) throws Exception { TestReflex reflex = new TestReflex(); long t = System.nanoTime(); for(int i = 0; i < 100000; i++) { reflex.call("method"); } long t1 = System.nanoTime() - t; System.out.println(t1); MonInterface interf = reflex; t = System.nanoTime(); for(int i = 0; i < 100000; i++) { interf.method(); } long t2 = System.nanoTime() - t; System.out.println(t2); System.out.println((double)t1/t2); } }Sur un simple test, l'appel par le design pattern command est 85x plus rapide que par réflexivité... Sans compter que la pour la reflexivité je ne parse pas la String pour récupérer les types des arguments etc.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 299386919 3469155 86.29966634526275
Mais bon, peu importe, la vitesse d'exécution n'était qu'un argument secondaire.
Je ne suis pas d'accord. Si on va dans ce sens, on n'a qu'à écrire tout le code de la fonction dans une String, et on la passe en argument...Envoyé par Gfx
C'est pour moi une simple erreur de "mapping" direct entre C++ et Java...
Code : Sélectionner tout - Visualiser dans une fenêtre à part machin.connect(this, "monTextField.setEnabled(false); System.out.println(\"bonjour\");");
En C++ quand on fait un pointeur de fonction, on a réellement un pointeur de fonction, pas une String indiquant comment le récupérer...
Pour faire la même chose en Java et avoir directement le pointeur, il faut utiliser une interface...
Donc ce qui est utilisé ici est un "mapping" de syntaxe (pour que la syntaxe java ressemble à la syntaxe C++), mais en rien un "mapping" de ce qui se passe à l'exécution, ni de concepts...
Oui la reflection c'est plus lent, forcément. Mais 80x plus lent ne signifie pas grand chose sans la mesure d'un appel à une interface. La seule chose importante est que même 80x plus lent, c'est assez rapide pour faire des animations complexes et fluides. Si cela ne suffit pas pour gérer un clic sur un bouton...
En modifiant ton test on peut voir qu'invoquer une méthode par reflection prend environ 300 nanosecondes. Loin certes des 4 nanosecondes pour un appel à une méthode d'interface mais amplement suffisant. C'est typiquement une optimisation inutile dans la plupart des cas.
Ce n'est pas ce que j'ai dit. J'ai dit que pour connecter un signal à son slot, une String n'était pas gênante. Je n'ai jamais prétendu qu'écrire le corps du handler dans la String serait une bonne idée. Ce n'est pas un argument que de modifer le mien.Je ne suis pas d'accord. Si on va dans ce sens, on n'a qu'à écrire tout le code de la fonction dans une String, et on la passe en argument...
Pour moi l'équivalent du pointeur sur fonction C/C++ est justement un objet Method obtenu par reflection. Ce n'est certes pas ainsi que l'on programme en Java mais QT est une API C++ et le mécanisme des slots/signals fonctionne de cette manière. Introduire des interfaces comme en Swing aurait un impact immense sur l'API QT pour un gain qui n'est pas du tout évident DANS LE CADRE de QT.
Note également que les slots/signaux sont bien plus flexibles que des interfaces. Grâce à eux tu peux connecter un signal generate(QRect, QImage) à une méthode addImage(QRect, QImage). Rien n'impose le nombre et le type d'arguments que tu peux utiliser.
Ah, ça j'étais sûr que tu allais répondre ça (que le test était foireux)...Envoyé par Gfx
C'est justement parce que je ne le mets pas en cache qu'il n'est pas foireux...
Le but était de comparer la vitesse d'exécution de 2 bouts de codes, appelés 1 fois chacun... Pour qu'on puisse observer des différences, bien sûr l'appeler 1 seule fois ne sert à rien, on ne voit rien. Donc je l'ai appelé 100000 fois... Il faut bien sûr que les 100000 appels soit indépendants...
Si tu introduis des optimisations en ne faisant un des traitement qu'une seule fois pour les 100000 appels, là ton test est foireux
EDIT: tu viens de modifier ton post...
On accepte de perdre du temps (aussi important soit-il) sur l'appel d'une méthode lorsque cela apporte un avantage par ailleurs. Ici je ne vois que des inconvénients... Le seul avantage que l'on peut voir est d'avoir une syntaxe proche de celle de C++... Moi personnellement ça ne me suffit pas...Envoyé par Gfx
FIN EDIT
C'est par ce que tu te limites à la syntaxe... Car c'est bien différent...Envoyé par Gfx
C'est ce que je dis... c'est simplement pour syntaxiquement faire "comme C++".Envoyé par Gfx
Évidemment, tout ce qui n'est pas vérifié est plus flexible... Mais n'est-ce pas là la force des langages "fortement" typés (où le fortement reste à définir) de ne pas être flexible là où il ne faut pas l'être?Envoyé par Gfx
Ah non ! Tu compares l'invocation d'une méthode d'une interface à l'introspection d'une méthode PLUS son invocation. Tu fais DEUX choses. Pour être totalement partial ton code devrait être le suivant :Le but était de comparer la vitesse d'exécution de 2 bouts de codes, appelés 1 fois chacun... Pour qu'on puisse observer des différences, bien sûr l'appeler 1 seule fois ne sert à rien, on ne voit rien. Donc je l'ai appelé 100000 fois... Il faut bien sûr que les 100000 appels soit indépendants...
Si tu introduis des optimisations en ne faisant un des traitement qu'une seule fois pour les 100000 appels, là ton test est foireux
Là on teste bien le coût de l'invocation. Pas de la recherche ET de l'invocation.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 private Method m; public void init(String method) throws Exception { m = getClass().getMethod(method); } public void call() { m.invoke(this); }
Bien sûr que c'est différent, mais c'est la fonctionnalité qui en est la plus proche en Java.C'est par ce que tu te limites à la syntaxe... Car c'est bien différent...
Ça, c'est un vieux débat... va donc en parler aux admirateurs de RubyMais n'est-ce pas là la force des langages "fortement" typés (où le fortement reste à définir) de ne pas être flexible là où il ne faut pas l'être?) Plus sérieusement, c'est une fonctionnalité, pas une force. Pas dans tous les cas. Cela dépend de tes besoins. Pour une simple gestion d'événements il est loin d'être évident que cette contrainte soit un véritable bénéfice. (Et tu veux sans doute parler de typage statique plutôt que de typage fort dans ce cas.)
Tout à fait. En fait je voulais comparer "l'ajout" (par la méthode connect) + "l'appel" lors d'un évènement.Envoyé par Gfx
Mais pour cela il faut mettre le interf = reflex dans la boucle également (qui correspond au passage de paramètre de l'objet).
Ce qui donne:
83 fois plus rapide...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 305388379 3660380 83.43078560149493
Mais bon après tu peux comparer séparément l'ajout et l'appel, tu obtiendras sans doute pour l'ajout un résultat bien plus rapide pour le design pattern Command (simple affectation) pour le passage de paramètre, et un peu moins rapide (que 80x plus rapide) pour l'invocation...
Mais bon, on ne va pas continuer les benchmark, ni savoir si gagner 80x en rapidité est important, la vitesse n'était pas un argument essentiel... le reste est d'après moi plus grave encore ;-)
Mais QT ne va pas faire la recherche de la méthode à chaque fois qu'un événement est généré, seulement lors du connect(). C'est cela qui rend ton test complètement caduc. Et puis je n'avais même pas vu, mais tu fausses encore plus le test en passant d'abord dans la méthode call(). Tu ajoutes donc à l'invocation de Method le coût d'appel à call() (même si selon la JVM ce code pourra être inliné ou pas). Bref.Tout à fait. En fait je voulais comparer "l'ajout" (par la méthode connect) + "l'appel" lors d'un évènement.
Mais pour cela il faut mettre le interf = reflex dans la boucle également (qui correspond au passage de paramètre de l'objet).
Tu n'as toujours pas d'exemple concret qui montrerait en quoi cette API est dangereuse/mal conçue/ce que tu veux.... le reste est d'après moi plus grave encore ;-)
Essaye d'utiliser QT sans vouloir le faire à la sauce Swing et tu découvriras une excellente API.
Au niveau "pratique" déjà, le refactoring, qu'on peut quasiment totalement oublier si on développe un programme en utilisant QT Jambi. Au niveau temps de développement, je pense que les erreurs de runtime demandent un plus long débuggage que les erreurs de compilation.Envoyé par Gfx
(et un problème qui n'est pas lié à la reflexivité, mais c'est dommage de ne pouvoir ajouter qu'un seul listener -si c'est le cas, je n'ai pas fouillé l'api-)
Je pense qu'en C++ c'est très bien, en Java j'ai des doutes au vu des exemples...Essaye d'utiliser QT sans vouloir le faire à la sauce Swing et tu découvriras une excellente API.
Mais tu as raison, je n'ai pas testé (encore?).
En tout cas j'aime bien le rendu sur certains screenshots (peut-être parce que c'est le même que sur mon bureau, qui est en KDE).
Disons que QT est très intéressant en C++ pour ses classes "annexes" comme les strings, etc. Il y a quelques années le rendu sous Windows était encore trop différent des applications natives mais les dernières versions sont excellentes. Leur API de dessin est également super sympa.
Pour les erreurs de compilation... certes. Mais tu fais si souvent des fautes de frappe dans le nom des méthodes pour que cela soit un vrai gain **dans ce cas très particulier et très limité** ? D'autant plus qu'il y a la completion pour ça (et oui même dans une String).
Hello!
Ouais, j'ai été très surpris de voir qu'il existait une version JAVA de QT
ça me semble bien jusqu'à date
Mais c'est vrai que si on nous force a utiliser les types de base à la sauce QT, c'est moins sympa oui comme disait.. je sais plus qui tout à coup![]()
Partager