Bonjour,
Je souhaite que le texte d'un JLabel s'affiche à la verticale.
Je ne souhaite pas me retrouver avec les lettres les unes sous les autres, mais avec le texte réellement à la verticale.
Quelqu'un aurait-il une idée à me soumettre ?
Merci.
Bonjour,
Je souhaite que le texte d'un JLabel s'affiche à la verticale.
Je ne souhaite pas me retrouver avec les lettres les unes sous les autres, mais avec le texte réellement à la verticale.
Quelqu'un aurait-il une idée à me soumettre ?
Merci.
Bonjour,
il me semble qu'un code source a été proposé pour faire ce que tu veux. C'est ici.
Je te remercie, je ne l'avais effectivement pas trouvé.
En fait, je cherchais une solution un peu plus générique.
A vrai dire, je ne souhaite pas effectuer une rotation d'un seul label, mais de tout un groupe, avec d'ailleurs un ensemble d'autres contrôles de type différents.
Fort de cet exemple, j'ai donc entrepris de l'appliquer à un JPanel (après tout, il hérite de JComponent lui aussi). Mais voilà, mes espoirs de voir tout le contenu de mon JPanel effectuer une rotation de 90° ne semblent pas vouloir se réaliser.
Il me semble assez suspect qu'une telle rotation d'éléments ne soit pas plus basique.
Quelqu'un aurait-il une idée pour ne pas avoir à se cogner tous les types d'objets ?
je vient de voir le code qui se trouve la :-)
http://www.developpez.net/forums/sho...80&postcount=5
le probleme quand ont fait ce genre de chose c'est qu'on limite trop les possibilite du Jlabel.
par exemple
si je met une taille de 300 a un label qui en a besoin que de 100 pour s'afficher et que je met l'alignement au centre. comment le label va s'afficher avec ce code? (il sera aligner au top parce que l'alignement n'est pas gerer dans le code ou bien j'ai pas fait tres attention parce que je connait pas la classe ParameterUI et j'ai pas ete plus loin :-) )
si je met un Insets au label c'est pas gerer non plus
si le label est .setEnabled(false) il sera afficher de la meme facon qu'un label .setEnabled(true)
...
quand on veut faire ce genre de chose, normalement on joue sur le (look and) feel en creant son propre UI :-) (c'est juste une common practise personne est obliger )
bon je viens d'en faire un rapidement et un peu commenter (comme j'en aurai aussi besoin un bientot :o) )
c'est quick (but no so dirty code) et tout n'est pas encore terminer. je terminerai une autre fois.
j'ai essayer de garder les meme nom de variables que dans BasicLabelUI. tu peut toujours aller voir dans cette classe si tu comprend pas un truc ou me demander :-)) .
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175 import java.awt.Dimension; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Insets; import java.awt.Rectangle; import java.awt.geom.AffineTransform; import javax.swing.Icon; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.plaf.basic.BasicLabelUI; /** * todo add a description and how to use this class * <code> * JLabel myLabel = new JLabel("some text"); * myLabel.setUI(new VerticalLabelUI(VerticalLabelUI.Direction.CLOCKWISE)); * someContainer.add(myLabel); * </code> * <p/> * todo add restrictions notes (does not support all alphabets...) or * implement them. * * @author bebe * @version draft */ public class VerticalLabelUI extends BasicLabelUI { /** * Direction in which the label's text will be rotated. * <ul> * <li>CLOCKWISE</li> * <li>COUNTERCLOCKWISE</li> * </ul> */ public enum Direction {CLOCKWISE, COUNTERCLOCKWISE} /** * * The default <code>BasicLabelUI</code> instance. This field might * not be used. To change the default instance use a subclass which * overrides the <code>createUI</code> method, and place that class * name in defaults table under the key "LabelUI". */ static { labelUI = new VerticalLabelUI(Direction.COUNTERCLOCKWISE); } /* 90° */ private final double NINETY_DEGREES = Math.PI / 2; /* see BasicLabelUI for description of these fields. I kept the same names.*/ private static Rectangle paintIconR = new Rectangle(); private static Rectangle paintTextR = new Rectangle(); private static Rectangle paintViewR = new Rectangle(); private static Insets paintViewInsets = new Insets(0, 0, 0, 0); /** * Direction how text will be rotated (clcokwise or counterclockwise ? */ protected Direction direction; /** * Create a (look and) feel object to render labels containing vertical * text. * * @param direction */ public VerticalLabelUI(Direction direction) { super(); this.direction = direction; } /* * the dimension returned are inversed !!! * (that's what we expected, so if you want to change this, do it carefully) */ @Override public Dimension getPreferredSize(JComponent c) { Dimension dim = super.getPreferredSize(c); /* prefered width is computed by the parent UI and we just return it parent width is our height and we compute our width using label's fontmetrics. remember the label is rotated this is why it's turned around. */ FontMetrics fm = c.getFontMetrics(c.getFont()); int height = fm.getHeight() + fm.getAscent() + fm.getDescent(); /*todo {check this dim.height: wrong value returned by super.getPreferedSize(c) in all likelihood it's depending on the (default) Locale. */ return new Dimension(height, dim.width); } /** * Javadoc copied from BasicLabelUI.paint * Paint the label text in the foreground color, if the label * is opaque then paint the entire background with the background * color. The Label text is drawn by paintEnabledText() or * paintDisabledText(). The locations of the label parts are computed * by layoutCL. * * @see #paintEnabledText * @see #paintDisabledText * @see #layoutCL */ @Override public void paint(Graphics g, JComponent c) { /* inspired by BasicLabelUI#paint*/ JLabel label = (JLabel) c; String text = label.getText(); Icon icon = (label.isEnabled()) ? label.getIcon() : label.getDisabledIcon(); if ((icon == null) && (text == null)) { return; } FontMetrics fm = g.getFontMetrics(); paintViewInsets = c.getInsets(paintViewInsets); paintViewR.y = paintViewInsets.top; paintViewR.x = paintViewInsets.left; /* as the label is rotated, height and width are inversed. */ paintViewR.height = c.getWidth() - (paintViewInsets.left + paintViewInsets.right); paintViewR.width = c.getHeight() - (paintViewInsets.top + paintViewInsets.bottom); paintTextR.x = 0; paintTextR.y = 0; paintTextR.width = 0; paintTextR.height = 0; paintIconR.x = 0; paintIconR.y = 0; paintIconR.width = 0; paintIconR.height = 0; String clippedText = layoutCL(label, fm, text, icon, paintViewR, paintIconR, paintTextR); Graphics2D g2d = (Graphics2D) g; AffineTransform tr = g2d.getTransform(); if (direction == Direction.CLOCKWISE) { g2d.rotate(NINETY_DEGREES); g2d.translate(0, -c.getWidth()); } else { g2d.rotate(-NINETY_DEGREES); g2d.translate(-c.getHeight(), 0); } if (icon != null) { icon.paintIcon(c, g, paintIconR.x, paintIconR.y); } if (text != null) { int textX = paintTextR.x; int textY = paintTextR.y + fm.getAscent() + fm.getDescent(); if (label.isEnabled()) { paintEnabledText(label, g, clippedText, textX, textY); } else { paintDisabledText(label, g, clippedText, textX, textY); } } g2d.setTransform(tr); } }
et pour tester
(moi j'aurai besoin d'un vertical label avec une icone c'est pour ca que j'ai aussi pris en compte l'icone ;-) )
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 import java.awt.EventQueue; import java.awt.GridBagLayout; import java.awt.Font; import java.net.URL; import java.io.IOException; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.ImageIcon; import javax.swing.Icon; import javax.swing.SwingConstants; import javax.imageio.ImageIO; /** * @author beb * */ public class VerticalUITester { public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { JFrame f = new JFrame("Vertical Label Test"); f.setLayout(new GridBagLayout()); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JLabel myVerticalLabel = null; try { Icon icon = new ImageIcon(ImageIO.read(new URL("http://java.developpez.com/img/small_faq_java.gif"))); myVerticalLabel = new JLabel("مرحبا", icon, SwingConstants.CENTER); myVerticalLabel.setFont(new Font("Lucida Sans", Font.PLAIN, 60)); myVerticalLabel.setUI(new VerticalLabelUI(VerticalLabelUI.Direction.CLOCKWISE)); f.add(myVerticalLabel); myVerticalLabel = new JLabel("صباح الخير", icon, JLabel.LEFT); myVerticalLabel.setFont(new Font("Lucida Sans", Font.PLAIN, 60)); myVerticalLabel.setUI(new VerticalLabelUI(VerticalLabelUI.Direction.COUNTERCLOCKWISE)); f.add(myVerticalLabel); } catch (IOException e) { e.printStackTrace(); } f.setSize(400, 300); f.setVisible(true); } }); } }
je vient de voir l'autre message avant le mien![]()
j'avait pas encore vu que tu voulait faire une rotation de tout un Panel.
je crois (je peut me tromper) que faire rotationer un panel de 90% d'un coup c'est pas possible de maniere simple. j'ai jamait essayer et je croit que c'est un joli challenge![]()
deja il te faut de bonne base sur la creation d'UI pour faire ca (un peu comme je vient de faire mais pour tes autre composant).
ca va en faire du code![]()
![]()
![]()
mais moi je voit pas a quoi ca sert.
de droite a gauche et de gauche a droite je peut comprendre.
mais j'immagine mal un combobox vertical ou un jtable vertical :-S
t'a pas une image de ce que tu veut en fait?
Pour la classe de GENERYS, elle fonctionne belle et bien. Merci à lui, et à vous deux l'info.
En fait, je ne suis pas convaincu que ParameterUI ne soit pas une classe à lui.
Le deux trois petites modif suivantes permettent de la rendre autonome.
Mais je dois admettre que ta solution semble plus prompte à être généralisée à d'autres contrôles. Je vais donc me pencher dessus avec grand intérêt.
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 import javax.swing.*; import java.awt.*; /** * Permet d'afficher un JLabel vertical */ public class JLabelVertical extends JLabel { public void paintComponent(Graphics g) { Graphics2D graphics2D = (Graphics2D) g; super.paintComponents(g); graphics2D.translate(0, getHeight()); graphics2D.rotate(-Math.PI/2); graphics2D.setFont(this.getFont()); graphics2D.drawString(this.getText(), 0 , (getHeight()-getStringHeight())/2); } /* * (non-Javadoc) * @see java.awt.Component#getPreferredSize() */ public Dimension getPreferredSize() { Dimension dimension = new Dimension(getStringHeight(), getStringWidth()); return dimension; } /* * (non-Javadoc) * @see java.awt.Component#getMinimumSize() */ public Dimension getMinimumSize() { return getPreferredSize(); } private int getStringWidth() { FontMetrics metrics = getFontMetrics(this.getFont()); int width = metrics.stringWidth(this.getText()); return width; } private int getStringHeight() { FontMetrics metrics = getFontMetrics(this.getFont()); int height = metrics.getHeight(); return height; } /** Creates a new instance of JLabelVertical */ public JLabelVertical(String txt) { this.setText(txt); } /** Creates a new instance of JLabelVertical */ public JLabelVertical() { } /** * @param args the command line arguments */ public static void main(String[] args) { JFrame jf = new JFrame(); JLabelVertical jlv = new JLabelVertical(); jlv.setText("Toto"); jlv.setFont(new java.awt.Font("Courier New", 0, 10)); jf.setContentPane(new JPanel()); jf.getContentPane().add(jlv); jf.setSize(50,100); jf.setVisible(true); } }
Pour faire bref, je ne compte effectivement pas appliquer cela à n'importe quels contrôles. Dans mon cas, je me contenterai de quelques labels, zones textes, et boutons. A l'occasion, je posterai une image de ce que je serai parvenu à réaliser![]()
A priori, pour les composants passifs, c'est relativement simple. Il te suffit de créer l'image et de la tourner.
Pour les boutons, c'est plus tendu, tu devra passer par l'UI (il faut faire tourner le texte et l'icône avec leurs positions respectives, mais garder le comportement normal des borders et du background).
Pour les composants texte (c'est ma bête noire) à moins de t'y connaître sérieusement, tu vas avoir besoin de temps.
> A priori, pour les composants passifs, c'est relativement simple. Il te suffit de créer l'image et de la tourner.
c'est pas vrai pour tout les alphabets ;-) (chinoi par exemple)
bbclone,
le code de ta classe VerticalLabelUI est assez clair, mais je dois admettre qu'un point reste assez obscure à mes yeux.
Je ne suis pas un pro en trigo, mais lorsque tu redéfinis les propriétés height et width du paintViewR, je ne comprend pas pourquoi tu ne te contentes pas d'inversés ceux récupérés sur c.
Bref pourquoi :
au lieu de :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 paintViewR.height = c.getWidth() - (paintViewInsets.left + paintViewInsets.right); paintViewR.width = c.getHeight() - (paintViewInsets.top + paintViewInsets.bottom);
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 paintViewR.height = c.getWidth(); paintViewR.width = c.getHeight();![]()
Les insets sont des marges internes en général réservées à la bordure (Border) du composant. Si tu n'en tiens pas compte et que tu utilise une LineBorder de 20 pixels de large, le texte risque de chevaucher la bordure, ce qui n'est pas top au niveau rendu.
Dans un JLabel normal, on fait la même chose (sans inverser vertical/horizontal). Il y a des lignes dans le genre :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 paintViewR.height = c.getWidth() - (paintViewInsets.top + paintViewInsets.bottom); paintViewR.width = c.getHeight() - (paintViewInsets.left + paintViewInsets.right);
Le plus simple est tout de meme d'utiliser JXTransformer : http://weblogs.java.net/blog/alexfro...sformer_t.html
Ce composant permet de tourner/scaler n'importe quel composant Swing.
J'avais implemente des composants verticaux de la maniere mentionne par xavlours : en creant une image en memoire du composant et en la tournant. Ca marche bien pour les composants statiques mais aussi pour les boutons.
Bref, quoi qu'il en soit, JXTransformer. C'est plus simple et ca va surement se retrouver dans SwingLabs voire le JDK (c'est un mec de l'equipe Swing qui l'a cree).
Merci xavlours pour ces aspects qui m'avaient échappés.
Romain, pour ce qui est de la classe JXTransformer, il est temps pour moi de l'essayer. L'exemple d'utilisation fourni est extrêmement séduisant. (Bien que je ne perçois toujours pas pourquoi les éléments swing ne fournissent pas ce type d'éléments ergonomiques en standard)
xavlours a bien explique le pourquoi des 2 lignes de codes :-)
je lis aussi le blog de alexfromsun. j'ai vu le JXTransformer et la demo aussi.
c'est seduisant mais je me demande comment les utilisateur reagirons quand il verront un combobox qui s'ouvre vers le haut quand il veront une table qui ajoute des record vers le haut...
le code que j'avais fait date d'avant de l'entry dans le blog et au plus tu recupere de code sur internet au plus tu perd ta creativite.
jai remarquer une autre chose ici. les developeur ne cherche pas a developer de nouvelle chose mais juste a assembler des chose existante. ce qui provoque alors des dizaine de mega de librairie pour pas grand chose.
ca devient moins amusant alors le developement. :-)
Le but du JXTransformer n'est pas de mettre une combo box ou une table a l'envers... Il faudrait deja parvenir a lire le texte a l'envers :p Ce genre de critique ne mene nulle part.
Enfin bref, tu n'es pas le seul a avoir cree un label vertical avant qu'Alex ne propose le JXTransformer (il n'y a qu'a voir l'abus qu'en font les docking frameworks. La difference est que JXTransformer est le seul que je connaisse qui fonctionne avec tous les composants.
Et heureusement que les developpeurs ne cherchent pas a reinventer la roue a chaque fois. C'est certes tres amusant mais quelle perte de temps ! Tout le monde n'a pas la chance de pouvoir consacrer du temps inutilement. Tu sais tres bien que dans un projet il y a des dates a respecter et la reutilisation de code est un atout majeur. En outre, il vaut mieux utiliser quelque chose de teste et eprouve plutot que de repartir de zero et prendre des risques inutiles.
Je trouve curieux que tu parles de creativite dans ce cas. Reecrire quelque chose qui a deja ete fait n'a rien de creatif. Il vaut mieux se reposer sur des fondations existantes pour, justement, etre creatif et inventer de nouvelles choses (ne serait-ce que terminer ton application).
jproto : Ta question est bien pourquoi est-ce que Swing ne permet pas de faire tourner les composants en standard ? Parce que l'interet est proche de zero quand tu prends l'ensemble des developpeurs. L'ajout de fonctionnalites est toujours tres couteux dans une API, non seulement en temps de developpement mais aussi et surtout en support et en stabilite.
crer un label vertical n'a rien de creatif, je parlais dans un sens plus general.
Et j'ai repondu de maniere generale aussi. La reutilisation est quelque chose d'excellent.
reutilisabilite => ok
utiliser 50 lib differente dans un meme projet et utiliser seulement 1% des capacite de la librarie non!
avec le jdk on peut faire enormement de chose.
si les chose sont simple je ne vois pas pourquoi faire appel a des librairies specialiser pour n'utiliser que tres peu de ses possibilite. (durant mon stage j'ai repris une application swing qui utilisait un bon nombre de librairie et aucun des developeur ne se souvenait a quoi ca servait. l'application etait un bordel. j'ai du en quelque sorte jouer le coach pour retravailler l'application et la rendre plus efficace et plus rapide => j'ai former les developeur (2 semaine) et on a tout recommencer > 8 semaines de boulot a notre a 3)
Romain GUI, j'aimarai bien t'expliquer ce qui m'agace chez certain developeur mais... demain je quitte la belgique pour 6 semaines de vacances et en ce moment je prepare ma valise. donc je pense pas que je reviendrai d'ici le mois de septembre...
bonne vacance a ceux qui parte et bon courage aux autre.
a bientot peutetre
ps: la tantot je parlais a un developeur et il etait justement en train de tester une demo de gfx (InfiniteProgressPane). Je lui demande qui a fait cette demo et il me repond "Romain GUI" prononce vrament GUI. il etait sur que c'etait un nick qui voulait dire Graphical User Interface(on t'a bien choisi ton nom
)
Gfx, pour ce qui est de ma remarque, ce n'était pas vraiment une question, mais un timide constat.
Certains langages proposent ce type d'actions sur leurs contrôles de façons plus directes, je ne dois donc pas être le premier à vouloir afficher un bouton à la verticale.![]()
Quoi qu'il en soit, je vous remercie tous pour ces différents apports et orientations qui ont tous eu le mérite de me faire creuser dans des directions différentes, et toutes aussi intéressantes.
Partager