Java et les JFileChooser
Java des fois, tu me fais ch*** !
Je bosse actuellement sur un logiciel de traitement d'image en Java ( coming soon
) ... et j'ai besoin de manipuler des JFileChooser (pour sélectionner des fichiers et des dossiers). Avant de pester contre ce foutu Swing d'énoncer mon soucis, je vais dire deux mots sur Swing, pour ceux qui ne connaîtraient pas.
Swing est une bibliothèque graphique pour Java. Elle permet donc de créer des interfaces graphiques. Ce qui est pratique, c'est que ça fonctionne sur n'importe quel système d'exploitation, donc pas mal pour du développement multiplateforme. (petit troll : et c'est beaucoup plus confortable à utiliser que C et GTK ... bien que je préfère largement le C à Java).
Revenons à nos moutons. Qu'est-ce qui me fait actuellement ch*** avec JFileChooser ? Et bien la réponse est simple : son implémentation moisie ! C'est un composant très peu personnalisable. Par exemple, si on veut garder uniquement la fenêtre de navigation sans les boutons, le sélectionneur de type de fichiers et toussa, on s'amuse avec la méthode remove(getComponent(index)) à chercher quel est le bon composant à virer. Ou aussi ce qui est à l'origine de ce post : comment choisir le mode d'affichage par défaut (liste ou détails). Je m'attendais à devoir faire un simple setViewMode(JFileChooser.DETAILS), comme en Qt quoi ... mais non faut faire un hack dégueulasse pour arriver à ses fins ! (Rhaaaaaa)
Après quelques énervements, j'ai trouvé un topic sur un forum qui m'a bien aidé :
La solution consiste à utiliser SwingUtils, téléchargeable sur le site : http://tips4java.wordpress.com/2008/11/13/swing-utils/
Il suffit ensuite de mettre le code trouvé sur le topic mentionné précédemment :
JFileChooser fileChooser = new JFileChooser();
AbstractButton button = SwingUtils.getDescendantOfType(AbstractButton.class,
fileChooser, "Icon", UIManager.getIcon("FileChooser.detailsViewIcon"));
button.doClick();
Et le tour est joué ! Mais je trouve ça vraiment dégueulasse personnellement ...
De manière plus générale, je trouve leur JFileChooser vraiment très pauvre. En plus de ne pas être très confortable à l'utilisation, il n'est pas personnalisable ... c'est vraiment dommage. Il va peut-être falloir que j'en code un moi-même quand j'en aurai le temps ... à suivre ...
Edit : Cette solution foire sur Mac OS (ça ne compile pas ...) . De plus, la façon avec laquelle j'ai encore modifié le JFileChooser (avec la méthode remove) fait foirer l'affichage sous Mac OS ...
Edit 2 : J'ai entamé (et déjà bien avancé) le codage de mon propre FileChooser et pour l'instant ça fonctionne bien
Modulo : la suite
Pour donner suite à mon post précédent : Une histoire de modulo ...
je me suis amusé à tester -5 % 26 dans 17 langages de programmations afin faire une liste des langages qui utilise la première définition et une liste de ceux qui utilisent la seconde.
Pour rappel, voici les deux définitions :
- x mod y = x - y * floor(x / y)
- x % y = x - y * iPart(x / y)
La définition 1 est cyclique. Ainsi -5 % 26 = 21. La définition 2 donne -5 % 26 = -5
Trève de bavardages, voici donc les deux listes :
| Définition 1 | Définition 2 |
|---|---|
| Ruby | C |
| Python | C++ |
| Lua | Java |
| Octave | PHP |
| MATLAB | OCAML |
| Perl | Pascal |
| Racket (anc. Scheme) | Ada |
| Prolog | Javascript |
| Go | |
| C# |
Une histoire de modulo …
Tout développeur connait le fameux (le seul, l'unique) : modulo
Comme je suis d'humeur narrative aujourd'hui, je vais quand même expliquer de quoi il s'agit
Cours du jour, bonjour
Bon, ouvrez bien vos oreilles yeux, on commence.
Tout le monde se souvient de sa tendre enfance, à l'école, en train d'assister à son premier cours de maths sur les divisions. Plutôt que de s'amuser à calculer le résultat réel (au sens mathématique du terme), on ne s'intéressait qu'à la partie entière et au reste.
Petits exemples :
12 / 5 = 2 et Reste = 2
6 / 2 = 3 et Reste = 0
9 / 2 = 4 et Reste = 1
9 / 3 = 3 et Reste = 0
En somme (notez le jeu de mot
), une division entière.
Et bien le modulo calcule le reste. C'est un nom bien barbare, qui au final, n'est rien de plus qu'un calcul enfantin
Donc si on reprend l'exemple ci-dessus, mais en version informatique cette fois, on a :
(dans beaucoup de langage, l'opérateur du modulo est le %)
12 % 5 = 2
6 % 2 = 0
9 % 2 = 1
9 % 3 = 0
Modulo = reste de la division entière.
On utilise vraiment ça ? A quoi ça peut bien servir une telle chose ??
Et bien, c'est très souvent utilisé lorsqu'on programme. On l'utilise, entre autres nombreuses choses, pour déterminer si un nombre est
pair. Il suffit de faire nombre % 2 Si le résultat est null, donc qu'il n'y a pas de reste, alors le nombre est pair. Sinon il est impair.
Maintenant que tout le monde c'est ce qu'est le modulo, on va pouvoir poursuivre sur le sujet de ce post.
Revenons aux choses serieuses
Faisons un petit exercice. Quel est le résultat de :
-5 % 26 = ?
(bien que nous ne soyons pas directement dans post concernant le domaine de la cryptographie, je vais utiliser les deux fameux protagonistes Bob et Alice, parce que je suis tombé sur cette étrangeté pendant un Travail Pratique de cryptographie)
- Bob : Pff facile, c'est 21 !
- Alice : Mais, non pas du tout c'est -5 !
- Bob : Tu n'as rien compris, un modulo c'est cyclique, ça ne peut pas être être négatif !
- Alice : Rien du tout. Tu es HS coco !
Mais qui a raison ? Et bien, ils ont tous les deux raisons. Avant d'en venir aux explications, regardons ce qu'en disent les langages de programmation.
Ruby :
$> ruby -e "puts -5 % 26" 21 $>
Python
$> python -c "print(-5 % 26)" 21 $>
Octave (et MATLAB)
$>octave --eval "mod(-5, 26)" GNU Octave, version 3.4.2 Copyright (C) 2011 John W. Eaton and others. This is free software; see the source code for copying conditions. There is ABSOLUTELY NO WARRANTY; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, type `warranty'. Octave was configured for "x86_64-unknown-linux-gnu". Additional information about Octave is available at http://www.octave.org. Please contribute if you find this software useful. For more information, visit http://www.octave.org/help-wanted.html Read http://www.octave.org/bugs.html to learn how to submit bug reports. For information about changes from previous versions, type `news'. ans = 21 $>
(On peut voir Bob trépigner
)
Java
class Main {
public static void main(String[] argv) {
System.out.println("-5 % 26 = " + (-5 % 26));
}
}
$> javac Main.java $> java Main -5 % 26 = -5 $>
PHP
$> php -r 'print((-5 % 26) . "n");' -5 $>
Agné ?! (le sourire de Bob se fane ... Alice est intriguée, comme on peut s'en douter)
Java et PHP ne sont pas les seuls. C, C++ (et d'autres) retournent -5.
Mais pourquoi ?
Et bien, en réalité, il y a deux définitions du modulo !
Regardons un peu ce qu'en dit notre vieil ami Wikipedia : http://fr.wikipedia.org/wiki/Modulo_(informatique)
Dans l'article, on a les deux définitions :
- x mod y =
x - y * floor(x / y) x % y = x - y * iPart(x / y)
La première définition donne un modulo cyclique, càd compris entre 0 et le diviseur. Je ne connaissais que la première définission et c'est à cause de ça que je me suis énnervé sur mon Travail Pratique de cryptographie (en Java). Pour résumer, je voulais faire un décalage sur chaque caractère d'une String. Bien entendu, je veux que quand on décale, par exemple, a de -4, on ait w. J'ai donc utilisé un modulo. Et comme j'utilisais le résultat comme indice d'un tableau, j'avais un joli OutOfBoundsExceptions à cause d'un indice négatif. Après quelques tests, j'ai enfin trouvé d'où venait le problème.
C'est donc bon à savoir pour tout développeur
Moralité de l'histoire : Vérifier l'évaluation du modulo du langage utilisé afin de ne pas se faire avoir bêtement (comme moi quoi
)
Edit : j'ai mis une liste des langages trié en fonctione de la définition utilisée là : http://blog.gilliek.ch/programmation/modulo-la-suite
Quel fou !
Waow ! Complètement taré : Fabrice Bellard a programmé un émulateur de PC en JavaScript qui boot sur Linux ! Vraiment bien fait
Il y a même l'éditeur vi, un compilateur pour compiler le programme hello.c présent dans votre home ainsi qu'une partie des commandes (ls, cd, chmod, du, etc.). Et les commandes gèrent même une partie des options (ex. ls -l).
ça se passe par ici : http://bellard.org/jslinux/ (à tester avec Chrome/Chromium ou Firefox 4 ou plus).
Pour les notes techniques, c'est par là : http://bellard.org/jslinux/tech.html
Les regles d’or du developpeur debutant
En lisant cet article de Developpez.com ça me donne envie de réagir ... et je vais donc réagir !
Pour résumer l'article, c'est le développeur Paul Vick qui énonce les 7 règles d'or du programmeur débutant.
Prenons ces règles une par une :
Règle numéro 1, le programmeur débutant ne doit pas écrire de longues procédures. Une procédure ne devrait pas avoir plus de dix ou douze lignes de code.
Déjà, je pense que ça dépend du langage. On ne peut pas espérer des procédures de même taille en Ruby qu'en C. En C, je dirai que ça tourne plus autour de 24 lignes (cf. Style Coding du Kernel Linux). Mais après, ça dépend de la situation ... D'autant plus si on applique une gestion d'erreurs rigoureuse ...
Deux, chaque procédure doit avoir un objectif clair. Un bon programme doit avoir des procédures claires, sans cumul.
Je suis d'accord là-dessus.
Trois, les programmeurs débutants ne doivent pas utiliser les fonctions fantaisistes du langage. Pour Paul Vick, il est mal pour un débutant d'utiliser autre chose que des déclarations de variables, les appels de procédures, des opérateurs (arithmétiques, comparaisons, etc.) et les fonctions de contrôle de flux. Selon lui, l'utilisation des fonctions simples oblige à réfléchir à ce que l'on écrit.
Je pense au contraire qu'un développeur débutant doit "s'amuser" à utiliser les fonctions du langage. Bien entendu, au début de son apprentissage, il doit veiller à bien connaître et manipuler les structures conditionnelles, les boucles, les types, ... toussa quoi. Mais il faut bien qu'un jour il apprenne à utiliser les fonctions "fantaisistes" du langage ... quoi de mieux que la pratique pour apprendre ?
Règle numéro quatre, ne jamais utiliser les fonctionnalités du langage dont vous n'êtes pas sûr(e) du résultat ou du rôle. Une règle d'or indépassable pour Paul Vick, qui estime que si elle n'est pas respectée par un débutant, il devrait purement et simplement changer de métier
Là encore : il faut tester. Pas sûr du résultat ? Alors hop un petit programme de test pour y voir plus clair ! C'est pas en tournant le dos à tous ce qu'on ne comprend pas qu'on deviendra un "bon" développeur ...
Règle numéro cinq, les débutants doivent à tout prix éviter le copier/coller. Sauf, évidemment, s'ils veulent copier le code d'un programme qu'ils ont écrit.
Je suis assez d'accord. Mais en revanche je pense qu'il est très instructif pour un débutant de s'inspirer de code existants. En effet, voir un code fait par un développeur avancé peut être instructif. Concernant le copier/coller, je serai un peu pus stricte en évitant de copier/coller son propre code (sauf dans un cas trivial et redondant). A force de tout taper, la syntaxe du langage rentrera plus facilement.
Six, le débutant doit éviter l'abstrait, et toujours opter pour le concret.
Je suis tout à fait d'accord là-dessus. Si le débutant reste trop dans l'abstrait, il va vite se sentir perdu ... et ça devient très décourageant pour lui ...
Et enfin la règle numéro sept : applique les six règles ci-dessus chaque jour pendant au moins six mois.
Alors ça c'est de la règle !
ça ressemble plus à une conclusion qu'à une règle à part entière. En plus, je pense que le temps d'apprentissage d'un langage dépend de la personne. Personnellement, je n'ai jamais eu besoin de 6 mois pour apprendre les bases d'un langage ... (et même pour les mécanismes avancés de ce langage d'ailleurs ...).
Comme c'est présenté, ça fait un peu recette miracle, mais au final, selon moi, suivre ces règles ne fera pas d'un débutant autre chose qu'un ... débutant. Faire des if/for et print "Hello, World" pendant 6 mois est complètement inutile ! C'est en explorant les "profondeurs" d'un langages qu'on apprend vraiment. Et puis, pour bien apprendre, il me semble important que la période d'apprentissage soit intéressant, attractive. Si on fait la même chose pendant 6 mois, on sera vite dégoûté.
L'article de Developpez.com se conclut comme suit : "Et pourrait même permettre, conclut-il avec humour, de se débarrasser des mauvaises habitudes acquises à l'Université. "
Sur ce point je suis d'accord. Dans les Universités (je ne veux pas généraliser hein
, mais je parle selon mon expérience), on apprend pas les bonnes pratiques de programmation ou si on les apprend, ce n'est que trop tard. C'est fort regrettable. D'un autre côté, avec le nombre impressionnant de de ressources sur Internet et dans les livres (électronique ou papier), l'étudiant peut (et devrait selon moi) apprendre par lui-même et profiter de la mine de savoir auquel on accès de nos jours.
Je rajouterai pour finir, que Paul Vick a omis un élément très important : la documentation du code. Il faut prendre l'habitude de bien documenter son code dès le début. Par exemple, faire de bons commentaires, c'est-à-dire ne pas paraphraser le code mais expliquer ce qu'il fait. Ca évite bien des problèmes de maintenabilité ...
Tetris 3D en HTML5
HTML5 prmet d'offrir d'énormes possibilités. Plus j'en apprends, plus je suis impressioné ! Voici un Tétris en 3D fait en HTML 5 : Torus
J'espère qu'un jour les jeux en Flash, seront remplacés par des jeux en HTML 5. Pareil pour les vidéo. Je commence à envoir vraiment mare de flash :
- Optimisation nul (pauvre CPU !)
- Failles de sécurité importantes
- Technologie propriétaire
- Lourd
- ...
J'attends avec impatience la fin des spécifications de HTML5.
PS: Et ne venez pas me parler de Silverlight !
Clang vs GCC
Mon ami Rolinh a déjà posté un billet sur une bizarrerie entre Clang et GCC. Eh bien hier soir, je suis tombé sur une autre assez spéciale.
Pour la petite histoire, j'aidais quelqu'un sur un forum et j'ai compilé son code avec Clang et avec Gcc et le résultat obtenue était différent.
Note : Ici, on ne s'intéresse pas à la qualité du code.
Voici le code :
int triplePointeur(int *pointeurSurNombre);
int main()
{
int nombre = 5;
triplePointeur(&nombre);
printf("%d %dnn", nombre, triplePointeur(&nombre));
return 0;
}
int triplePointeur(int *pointeurSurNombre)
{
int a = 4;
int b = 2;
*pointeurSurNombre *= 3;
return a + b;
}
Avec GCC ça donne :
$ gcc -Wall -o test test.c $ ./test 45 6
On a une première modification de la variable nombre avec le premier appel de la fonction triplePointeur. On a 3 * 5 = 15. Ensuite, on réappelle triplePointeur dans le printf et on a donc nombre = 3 * 15 = 45.
Et maintenant avec Clang :
$ clang -Wall -o test test.c $ ./test 15 6
Et là, surprise, on obtient 15 !
Pour la réponse à cette énigme (voir commentaires, et au passage merci au posteur anaonyme) :
En fait, l'ordre de calcul des paramètres n'est pas défini dans le langage C. GCC calcule de droite à gauche, donc la variable nombre est modifiée deux fois. Quant à Clang, lui il les calcule de gauche de à droite. Du coup, nombre est affichée avant d'être modifiée une seconde fois.
Raisonnement naif
NOTE: Pardonnez la faute dans le titre (naif -> naïf), mais mon cher WordPress refuse de me mettre un "ï" ...
Il y a quelques temps de cela, je suis tombé par hasard sur un tutoriel en C qui parlait d'une bibliothèque (dirent, utilisée pour ouvrir/parcourir un répertoire). L'auteur, propose à un moment une fonction pour déterminer si l'élément courant est un répertoire ou un fichier :
int isDir(struct dirent* ent)
{
if ((strchr(ent->d_name, '.')) == NULL) /* Si le nom du fichier n'a pas de point (une extension). */
return 1;
else
return 0;
}
Je ne vous donne volontairement pas le lien vers le tutoriel. Mon but n'est pas de critiquer l'auteur ni son tutoriel (qui, soit dit en passant, est très bon hormis cette fonction), mais de mettre l'accent sur les "raisonnements naïfs" que peut avoir le programmeur.
Petite précision importante au passage : Ce tutoriel présente la bibliothèque pour GNU/Linux et Windows, en mettant quand même l'accent sur Linux.
Regardons maintenant ce bout de code de plus près !
Vous l'aurez sans doute remarqué, l'auteur propose de vérifier l'extension pour déterminer s'il s'agit d'un répertoire ou d'un fichier. Aïe ! En plus d'être absurde parce qu'on peut très bien mettre un point dans le nom d'un dossier (ex. : les dossiers cachés), les fichiers n'ont pas forcément d'extension (!) ...
Bref, il s'agit d'un raisonnemnt très naïf qui conduit souvent à de gros bugs dans un programme.
Moralité de l'histoire : bien réfléchir à ce qu'on fait et surtout connaître l'OS (Système d'exploitation) sur lequel on travaille.
Et comme je suis gentil (:-P), je vous mets une fonction correcte :
int
is_dir(const char *path)
{
struct stat buf;
if (stat(path,&buf) == -1){
perror("Error ");
return -1;
}
return S_ISDIR(buf.st_mode);
}
Et il faut inclure (en plus des libs "de base"):
sys/types.h
sys/stat.h
unistd.h
Je ne vous mets pas ces #include en entier parce que cet abruti de WordPress me les supprime (sans doute à cause des chevrons ...)
TCPDF, ton sauveur !
Si toi aussi tu en as mare de PDFlib, TCPDF est là pour toi
En tant que développeur Web, il m'est arrivé de devoir générer des PDF. Le problème étant que la plupart des hébergeurs ne propose que la version gratuite de PDFlib qui est une horreur sans nom (grrr). Mal pensé, mal documenté (et le exemples sont en Java ...) et en plus il est très limité en sa version gratuite ... je vous laisse imaginer la galère pour développer avec ...
Mais ces mauvais moments sont terminés, parce que TCPDF est là (<3) ! En effet, avec TCPDF, pas besoin d'installer quoique ce soit sur le serveur (ce qui aurait posé problème pour de l'hébergement mutualisé), il suffit de l'uploader sur le serveur et d'inclure ce qu'il faut (avec include, require, etc). En plus, c'est beau parce qu'on met directement du code HTML. Concernant la documentation, sur le site on trouve de beaux exemples (en PHP!) clairs et utiles.