www.mikrocontroller.net

Forum: PC-Programmierung java Schriftgröße an Komponente anpassen


Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bei einem JSpinner kannst du einen eigenen Editor implementieren:
http://java.sun.com/j2se/1.4.2/docs/api/javax/swin...
> 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.

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So könnte z.B. ein read only Editor für einen JSpinner dann aussehen 
(vorgehen ist für einen JButton ähnlich)
package test;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Insets;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JSpinner;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class SpinnerTest {

    public static void main(String[] args) {
        JSpinner spinner = new JSpinner();
        SpinnerEditor editor = new SpinnerEditor();
        editor.upDateFrom(spinner);
        spinner.addChangeListener(editor);
        spinner.setEditor(editor);
        JFrame frame = new JFrame();
        frame.setSize(200, 100);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.add(spinner);
        frame.setVisible(true);
    }

    private static class SpinnerEditor extends JLabel implements ChangeListener {

        private static final long serialVersionUID = -1601826295344734066L;

        @Override
        public void stateChanged(ChangeEvent ce) {
            if (ce.getSource() instanceof JSpinner) {
                JSpinner spinner = (JSpinner) ce.getSource();
                upDateFrom(spinner);
            }
        }

        public void upDateFrom(JSpinner spinner) {
            setText(spinner.getValue().toString());
        }

        @Override
        protected void paintComponent(Graphics g) {
            //nur um zu sehen wie unser Orginal zeichnet...
            super.paintComponent(g);
            //wir werden in rot darüberzeichenen...
            g.setColor(Color.RED);
            //Ränder bestimmen....
            Insets insets = getInsets();
            int x = insets.left;
            int y = insets.top;
            //Breite und Höhe bestimmen
            Dimension size = getSize();
            int w = size.width - x - insets.right;
            int h = size.height - y - insets.bottom;
            //Rahmen zeichenen für tests...
            g.drawRect(x, y, w - 1, h - 1);
            Font font = g.getFont();
            String text = getText();
            FontMetrics fm = g.getFontMetrics(font);
            while (fm.stringWidth(text) < w && fm.getMaxAscent() + fm.getMaxDescent() < h) {
                font = font.deriveFont(font.getSize2D() + 0.5f);
                fm = g.getFontMetrics(font);
            }
            g.setFont(font);
            //nun endlich zeichnen...
            g.drawString(text, x, y + font.getSize());
            //Zeichen von Bounding Box in Blau
            g.setColor(Color.BLUE);
            g.drawRect(x, y, fm.stringWidth(text), fm.getMaxAscent() + fm.getMaxDescent());
        }
    }
}
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)

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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:
    private static class DynButton extends JButton {
        private static final long serialVersionUID = -6029717230072874871L;

        public DynButton(String string) {
            super(string);
        }

        @Override
        protected void paintComponent(Graphics g) {
            calcFont(g);
            super.paintComponent(g);
        }

        private void calcFont(Graphics g) {
            Insets insets = getInsets();
            Insets margin = getMargin();
            int x = insets.left + margin.left;
            int y = insets.top + margin.top;
            //Breite und Höhe bestimmen
            Dimension size = getSize();
            int w = size.width - x - insets.right - margin.right;
            int h = size.height - y - insets.bottom - margin.bottom;
            Font font = g.getFont();
            String text = getText();
            FontMetrics fm = g.getFontMetrics(font);
            while (fm.stringWidth(text) < w && fm.getMaxAscent() + fm.getMaxDescent() < h) {
                font = font.deriveFont(font.getSize2D() + 0.5f);
                fm = g.getFontMetrics(font);
            }
            g.setFont(font);
        }
    }
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.

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.)

Autor: tabina (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.