Bien le bonjour à vous chers développeurs Java,
[Explication en détail, CF le résumé en fin de post au besoin !]
Je viens à vous aujourd'hui car j'ai un problème avec Swing qui m'agace profondément. Avant toute chose, j'ai réussi à régler ce problème. Néanmoins, la solution trouvée est à mon goût hideuse, et je souhaiterais aussi bien comprendre d'où vient le problème que mettre en place quelque chose de plus propre.
Le problème est donc le suivant:
J'ai une image sous format BufferedImage que je souhaite afficher dans ma frame (c'est conceptuellement simple, mais ça sera mis en application dans une appli plus vaste).
Je crée une ImageIcon que je place dans un JLabel, que je place lui-même dans un JPanel qui est défini comme contentPane de ma JFrame.
Lors du premier chargement de l'image, aucun soucis, l'image est bien affichée, tout va bien.
En plus de celà, je crée un ComponentListener sur le resizing de ma fenêtre, et je cherche à changer l'image dans mon IconImage en effectuant son resizing. Ma fonction prenant en paramètre une BufferedImage de taille (X,Y) et renvoyant une BufferedImage de taille (X',Y') fonctionne parfaitement, et je peux donc mettre en oeuvre celà. Le soucis, c'est qu'un simple labelImage.setIcon(resizedImage) ne suffit pas. L'image affichée n'est pas mise à jour, et j'ai beau jouer de tous les validate() revalidate() reloadUI() (je crois bien que ce dernier n'a néanmoins rien à voir) pack() et autres méthodes de mise à jour de mon affichage, rien n'y fait !
Alors même que les sysout sur la taille des panel/imageIcon/frame me confirment bien que le changement de taille a été pris en compte.
Le seul moyen que j'ai trouvé pour corriger le problème a été de créer un nouveau JPanel, y ajouter mon JLabel auquel on aura ajouté le ImageIcon au préalable, et définir ce nouveau JPanel comme contentPane :/ C'est à mon goût très laid.
Voici donc le code actuel qui fonctionne:
Code de l'event de resizing et de la méthode appellée pendant celui ci:
Code en entier :
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 /** * Tout un tas de truc au dessus */ fenetre.addComponentListener(new ComponentAdapter() { public void componentResized(ComponentEvent e) { if(fenetre.getWidth() != widthFenetre || fenetre.getHeight() != heighFenetre) { if (si != null) { Runnable doResizeImage = new Runnable() { public void run() { majImage(); } }; SwingUtilities.invokeLater(doResizeImage); }; } } }); /** * Tout un tas de truc en dessous, et fin de la classe puis déclaration des * méthodes de la classe */ public void majImage() { BufferedImage resizedImage = resize(si.getBufferedImage(), panel.getHeight(), panel.getWidth()); // Resize est un méthode static de la classe réalisant le resizing de l'image passée en entrée selon les paramètres fournis panel = new JPanel(); ImageIcon icon = new ImageIcon(resizedImage); labelImage = new JLabel(icon); panel.add(labelImage); fenetre.setContentPane(panel); panel.revalidate(); }
Résumé : Dans la fonction majImage() fournie dans le premier bloc de code, comment éviter d'avoir à redéfinir l'ensemble du contentPane pour mettre à jour l'image visualisée dans la JFrame (qui contient un JPanel en contentFrame, qui contient un JLabel qui contient une ImageIcon qui contient une bufferedImage).
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125 private JFrame fenetre; private JPanel panel; private ImageIcon imageIcon; private SourceImage si; // Objet de la bibliothèque PixelMed private JLabel labelImage; public AffichageFenetre() { // Définition de la JFrame fenetre = new JFrame(); fenetre.setSize(400, 400); this.widthFenetre = 400; this.heighFenetre = 400; fenetre.setResizable(true); fenetre.setLocationRelativeTo(null); fenetre.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); fenetre.setLayout(new BorderLayout()); // Ajout du JPanel en ContentPane panel = new JPanel(); fenetre.setContentPane(panel); // Définition des menus menuBar = new JMenuBar(); menu1 = new JMenu("Fichier"); JMenuItem ouvrirFichier = new JMenuItem("Ouvrir Image"); menu1.add(ouvrirFichier); menuBar.add(menu1); fenetre.setJMenuBar(menuBar); // Définition d'un actionListener pour l'ouverture d'un JFileChooser ouvrirFichier.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { File fichierSelectionne = ouvertureFileChooser(); if (isDicom(fichierSelectionne)) { afficherImage(fichierSelectionne.getPath()); } } }); // Définition d'un resizing event sur notre fenêtre fenetre.addComponentListener(new ComponentAdapter() { public void componentResized(ComponentEvent e) { if(fenetre.getWidth() != widthFenetre || fenetre.getHeight() != heighFenetre) // Si et seulement si la taille de la fenêtre a changée { if (si != null) { // Si un objet image a été choisi par le JFileChooser Runnable doResizeImage = new Runnable() { public void run() { majImage(); } }; SwingUtilities.invokeLater(doResizeImage); }; } } }); fenetre.setVisible(true); widthFenetre = fenetre.getWidth(); heighFenetre = fenetre.getHeight(); } /** * Méthode appelée lors de l'event de resizing de la fenêtre. */ public void majImage() { BufferedImage resizedImage = resize(si.getBufferedImage(), panel.getHeight(), panel.getWidth()); panel = new JPanel(); ImageIcon icon = new ImageIcon(resizedImage); labelImage = new JLabel(icon); panel.add(labelImage); fenetre.setContentPane(panel); panel.revalidate(); } /** * Méthode appelée lorsqu'un fichier a été sélectionné, afin d'afficher l'image s'il s'agit d'une image. */ public void afficherImage(String path){ try { si = new SourceImage(path); this.imageIcon = new ImageIcon(resize(si.getBufferedImage(), panel.getHeight(), panel.getWidth())); this.labelImage = new JLabel(imageIcon); panel.add(new JLabel(imageIcon)); fenetre.pack(); } catch (Exception e) { e.printStackTrace(); } } /** * Méthode de resizing de l'image passée en entrée aux dimensions passées en entrée également. */ public static BufferedImage resize(BufferedImage img, int newH, int newW) { int w = img.getWidth(); int h = img.getHeight(); BufferedImage dimg = new BufferedImage(newW, newH, BufferedImage.TYPE_BYTE_GRAY); Graphics2D g = dimg.createGraphics(); g.drawImage(img, 0, 0, newW, newH, 0, 0, w, h, null); g.dispose(); return dimg; } /** * Appel au JFileChooser. */ public File ouvertureFileChooser() { JFileChooser chooser = new JFileChooser(); chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); chooser.setMultiSelectionEnabled(false); int returnVal = chooser.showOpenDialog(fenetre); if(returnVal == JFileChooser.APPROVE_OPTION) { return chooser.getSelectedFile(); } else return null; }
D'avance, merci pour vos réponses, j'espère que vous saurez m'éclairer, car j'y ai déjà passé près de 6 heures hier à essayer de comprendre ce qui n'allait pas et une bonne heure aujourd'hui également. Comme je manque un peu de temps ces derniers jours, je met un peu un message à la mer ici en quelque sorte.
Bonne journée à vous !
Partager