hi, vielleicht hat ja von euch jemand nen Plan: Ich benutze einen Layout-Manager, der die Komponenten mit der Fenstergröße skaliert. Ich möchte auch die Schriftgröße entsprechend mitskalieren. Hat da jemand eine Idee? Was mir einfällt, wäre, dass man sich auf das Resize-Event registriert und dann von Hand die Größen anpasst, aber das erscheint mir arg umständlich. Geht das nicht auch irgendwe automatisch? Gruß, Vlad
Wenn die Komponente (welche überhaupt) das nicht von sich aus unterstützt so musst du dich selbst darum kümmern. Ist es den überhaupt wünschenswert das sich die Schrift mitsamt der Komponente vergrößert? Was soll passieren wenn zwar die Höhe/Größe der Schrift sich anpasst aber aufgrund der Textmenge die Breite nicht mehr passt?
das ganze sollte natürlich so funtkionieren, dass die Boundingbox der Schrift komplett in der Komponente liegt, was anderes macht meiner Meinung nach auch gar keinen Sinn. Die schrift soll also so groß wie möglich sein, ohne über die Ränder zu laufen. Konkret handelt es sich um JButton und JSpinner
Bei einem JSpinner kannst du einen eigenen Editor implementieren: http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/JSpinner.html > The editor is created by the JSpinner's constructor and can be > changed with the editor property. The JSpinner's editor stays > in sync with the model by listening for ChangeEvents. Bei einem Button, könntest du AbstractButton oder JButton erweitern und Kontrolle über die paintComponent Methode übernehmen. Hört sich etwas komplizierter an, ist aber eigentlich ganz einfach.
So könnte z.B. ein read only Editor für einen JSpinner dann aussehen (vorgehen ist für einen JButton ähnlich)
1 | package test; |
2 | import java.awt.Color; |
3 | import java.awt.Dimension; |
4 | import java.awt.Font; |
5 | import java.awt.FontMetrics; |
6 | import java.awt.Graphics; |
7 | import java.awt.Insets; |
8 | import javax.swing.JFrame; |
9 | import javax.swing.JLabel; |
10 | import javax.swing.JSpinner; |
11 | import javax.swing.event.ChangeEvent; |
12 | import javax.swing.event.ChangeListener; |
13 | |
14 | public class SpinnerTest { |
15 | |
16 | public static void main(String[] args) { |
17 | JSpinner spinner = new JSpinner(); |
18 | SpinnerEditor editor = new SpinnerEditor(); |
19 | editor.upDateFrom(spinner); |
20 | spinner.addChangeListener(editor); |
21 | spinner.setEditor(editor); |
22 | JFrame frame = new JFrame(); |
23 | frame.setSize(200, 100); |
24 | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); |
25 | frame.setLocationRelativeTo(null); |
26 | frame.add(spinner); |
27 | frame.setVisible(true); |
28 | }
|
29 | |
30 | private static class SpinnerEditor extends JLabel implements ChangeListener { |
31 | |
32 | private static final long serialVersionUID = -1601826295344734066L; |
33 | |
34 | @Override
|
35 | public void stateChanged(ChangeEvent ce) { |
36 | if (ce.getSource() instanceof JSpinner) { |
37 | JSpinner spinner = (JSpinner) ce.getSource(); |
38 | upDateFrom(spinner); |
39 | }
|
40 | }
|
41 | |
42 | public void upDateFrom(JSpinner spinner) { |
43 | setText(spinner.getValue().toString()); |
44 | }
|
45 | |
46 | @Override
|
47 | protected void paintComponent(Graphics g) { |
48 | //nur um zu sehen wie unser Orginal zeichnet...
|
49 | super.paintComponent(g); |
50 | //wir werden in rot darüberzeichenen...
|
51 | g.setColor(Color.RED); |
52 | //Ränder bestimmen....
|
53 | Insets insets = getInsets(); |
54 | int x = insets.left; |
55 | int y = insets.top; |
56 | //Breite und Höhe bestimmen
|
57 | Dimension size = getSize(); |
58 | int w = size.width - x - insets.right; |
59 | int h = size.height - y - insets.bottom; |
60 | //Rahmen zeichenen für tests...
|
61 | g.drawRect(x, y, w - 1, h - 1); |
62 | Font font = g.getFont(); |
63 | String text = getText(); |
64 | FontMetrics fm = g.getFontMetrics(font); |
65 | while (fm.stringWidth(text) < w && fm.getMaxAscent() + fm.getMaxDescent() < h) { |
66 | font = font.deriveFont(font.getSize2D() + 0.5f); |
67 | fm = g.getFontMetrics(font); |
68 | }
|
69 | g.setFont(font); |
70 | //nun endlich zeichnen...
|
71 | g.drawString(text, x, y + font.getSize()); |
72 | //Zeichen von Bounding Box in Blau
|
73 | g.setColor(Color.BLUE); |
74 | g.drawRect(x, y, fm.stringWidth(text), fm.getMaxAscent() + fm.getMaxDescent()); |
75 | }
|
76 | }
|
77 | }
|
Je nach darstellbarem Inhalt kann man hier noch etwas justieren und z.B. die Höhe noch etwas anders berechnen (z.B. bei Zahlen kann man direkt nur von der Baseline rechnen)
wow, Danke, hast dir ja richtig Arbeit gemacht. Ich werds bei gelegenheit mal ausprobieren, danke. Mir ist folgendes noch nicht ganz klar: du zeichnest das super "nur um zu sehen wie unser Orginal zeichnet..." wenn das später weggelassen wird, fehlt doch der Rest des Controlls, oder? Bei den Spinnern gehts vielleicht noch, da die zweigeteilt sind, aber bei Buttons? da müsste man ja den kompletten button selbst zeichnen.
Bei meinem Spinnerbeispiel kannst du das einfach auskommentieren. Ein Editor ist wirklich in diesem Fall nur für den Dartstellungsbereich des Controls zuständig. Wenn das ganze editierbar sein soll wird wohl etwas trickreicher, ggf. kann man auch einfach die benötigte Fontgrösse berechnen und dann den Font setzen und ein repaint auslösen falls sich die Fontgröße geändert hat. Bei einem Button funktioniert auch folgendes:
1 | private static class DynButton extends JButton { |
2 | private static final long serialVersionUID = -6029717230072874871L; |
3 | |
4 | public DynButton(String string) { |
5 | super(string); |
6 | }
|
7 | |
8 | @Override
|
9 | protected void paintComponent(Graphics g) { |
10 | calcFont(g); |
11 | super.paintComponent(g); |
12 | }
|
13 | |
14 | private void calcFont(Graphics g) { |
15 | Insets insets = getInsets(); |
16 | Insets margin = getMargin(); |
17 | int x = insets.left + margin.left; |
18 | int y = insets.top + margin.top; |
19 | //Breite und Höhe bestimmen
|
20 | Dimension size = getSize(); |
21 | int w = size.width - x - insets.right - margin.right; |
22 | int h = size.height - y - insets.bottom - margin.bottom; |
23 | Font font = g.getFont(); |
24 | String text = getText(); |
25 | FontMetrics fm = g.getFontMetrics(font); |
26 | while (fm.stringWidth(text) < w && fm.getMaxAscent() + fm.getMaxDescent() < h) { |
27 | font = font.deriveFont(font.getSize2D() + 0.5f); |
28 | fm = g.getFontMetrics(font); |
29 | }
|
30 | g.setFont(font); |
31 | }
|
32 | }
|
Da das paintComponent wohl davon ausgeht das bereits der korrekte Font gesetzt ist. Allerdings muss man da noch den Margin berücksichtigen wie ich gerade festgestellt habe.
ok, hätt nicht gedacht, dass das so geht. Ich hätte da mit einer Endlosschleife gerechnet, da ein Ändern der Font ja ein Repaint auslöen sollte. Edit: Oh ich seh grad, die Font wird nicht bem Button, sondern beim Graphics objekt gesetzt.
Vlad Tepesch schrieb: > Oh ich seh grad, die Font wird nicht bem Button, sondern beim Graphics > objekt gesetzt. Ja ich hab auch erst überlegt den Font direkt anzupassen, man müsste dan nur abbrechen sobald aktuelle Fontgröße = berechnete Größe. *ABER:* vermutlich würde man dadurch auch sobald die Komponenten einmal vergrößert wurde diese nicht mehr verkleinern können (oder noch eine Routine bauen welche den Font wieder verkleinert ggf.)
Wie würde man das für eine Checkbox lösen? Ich möchte, dass immer der ganze Text einer Checkbox sichtbar ist. Wenn der Textbereich kürzer ist, müsste die Schriftgröße angepasst werden. Das oben beschriebene Vorgehen funktioniert bei mir prima mit Buttons, aber nicht bei Checkboxen. Gruß, tabina
tabina schrieb: > Wie würde man das für eine Checkbox lösen? Wie gesagt das muss man gff. für verschiedene Komponenten eine eigene Lösung finden. Soll den nur der Text oder auch das Icon Skaliert werden? Bei der Berechnung musst du auf jeden Fall noch die Breite des Icons berücksichtigen. (gilt im Übrigen eigentlich auch für den Button). Das ganze ist wie gesagt nur eine Art Demo und sicher weit von der Perfektion entfernt ;) > Das oben beschriebene Vorgehen funktioniert bei mir prima mit Buttons, > aber nicht bei Checkboxen. Was funktioniert den nicht?
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.