Setzen von der Schriftgröße bei einem Shell

tanechka

Bekanntes Mitglied
Hallo zusammen,

ich möchte in meinem Code die Fonts von einer Shell setzen. Dabei möchte ich die Schriftgröße aller Elemente in der Shell ändern.

Code:
package main_gui.gui;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;




public class Test {


    Shell shell;
    static Display display;




    public static void main(String args[]) {
        display = Display.getDefault();
        try {
            Test w = new Test();
            w.open();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }



    public void open() {
        createContents();
        shell.open();
//        shell.layout();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
    }



    protected void createContents() {
        shell = new Shell();
        Control control = shell;
        display = shell.getDisplay();
//        fontRegistry = new FontRegistry(display);
        Font font1 = new Font(display, new FontData("Arial", 10, SWT.BOLD));
        Font font2 = new Font(shell.getDisplay(), new FontData("Arial", 24, SWT.NORMAL));

//        fontRegistry.put("code", new FontData[] { new FontData("Arial", 10, SWT.BOLD) });
//        fontRegistry.put("code1", new FontData[] { new FontData("Arial", 14, SWT.NORMAL) });

        shell.setFont(font1);
        Button btnNewButton = new Button(shell, SWT.NONE);
        btnNewButton.setBounds(265, 105, 75, 25);
        btnNewButton.setText("New Button");
        Label lblSasasasasasasas = new Label(shell, SWT.NONE);
        lblSasasasasasasas.setBounds(26, 36, 346, 63);
        lblSasasasasasasas.setText("sasasasasasasas");
        btnNewButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                font1.dispose();
                control.setFont(font2);
//                shell.setFont(font2);
                shell.requestLayout();
                shell.layout();
            }
        });
    }
}
Ich habe schon einiges ausprobiert und das zeigt keine Wirkung. Es geht nur wenn ich lblSasasasasasasas.setFonts() benuzte, sonst nicht. Habt ihr vielleicht Vorschläge, wie ich das Setzen von Fonts bei einer Shell machen kann? Was mache ich falsch, die Funktion gibt es ja...

Vielen Dank
 
Hallo zusammen,

ich möchte in meinem Code die Fonts von einer Shell setzen. Dabei möchte ich die Schriftgröße aller Elemente in der Shell ändern.

Code:
package main_gui.gui;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;




public class Test {


    Shell shell;
    static Display display;




    public static void main(String args[]) {
        display = Display.getDefault();
        try {
            Test w = new Test();
            w.open();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }



    public void open() {
        createContents();
        shell.open();
//        shell.layout();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
    }



    protected void createContents() {
        shell = new Shell();
        Control control = shell;
        display = shell.getDisplay();
//        fontRegistry = new FontRegistry(display);
        Font font1 = new Font(display, new FontData("Arial", 10, SWT.BOLD));
        Font font2 = new Font(shell.getDisplay(), new FontData("Arial", 24, SWT.NORMAL));

//        fontRegistry.put("code", new FontData[] { new FontData("Arial", 10, SWT.BOLD) });
//        fontRegistry.put("code1", new FontData[] { new FontData("Arial", 14, SWT.NORMAL) });

        shell.setFont(font1);
        Button btnNewButton = new Button(shell, SWT.NONE);
        btnNewButton.setBounds(265, 105, 75, 25);
        btnNewButton.setText("New Button");
        Label lblSasasasasasasas = new Label(shell, SWT.NONE);
        lblSasasasasasasas.setBounds(26, 36, 346, 63);
        lblSasasasasasasas.setText("sasasasasasasas");
        btnNewButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                font1.dispose();
                control.setFont(font2);
//                shell.setFont(font2);
                shell.requestLayout();
                shell.layout();
            }
        });
    }
}
Ich habe schon einiges ausprobiert und das zeigt keine Wirkung. Es geht nur wenn ich lblSasasasasasasas.setFonts() benuzte, sonst nicht. Habt ihr vielleicht Vorschläge, wie ich das Setzen von Fonts bei einer Shell machen kann? Was mache ich falsch, die Funktion gibt es ja...

Vielen Dank

Hi ich habe dein Code ein bisschen angepasst. Schau doch mal ob das das was du willst?

Code:
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;

public class Test {

    Shell shell;
    static Display display;

    public static void main(String args[]) {
        display = Display.getDefault();
        try {
            Test w = new Test();
            w.open();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void open() {
        createContents();
        shell.open();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
    }

    private int size = 10;
   
    protected void createContents() {
        shell = new Shell();
        shell.setLayout(new GridLayout());
        display = shell.getDisplay();
        Font font1 = new Font(display, new FontData("Arial", size, SWT.BOLD));

        Label label1 = new Label(shell, SWT.NONE);
        label1.setText("Hello World!");
        label1.setFont(font1);
       
        Label label2 = new Label(shell, SWT.NONE);
        label2.setText("Hallo Welt!");
        label2.setFont(font1);
       
        shell.setFont(font1);
        Button btnNewButton = new Button(shell, SWT.NONE);
        btnNewButton.setBounds(265, 105, 75, 25);
        btnNewButton.setText("Verkleinern");
        btnNewButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                Font font = new Font(display, new FontData("Arial", --size, SWT.BOLD));
                for (Control c : shell.getChildren()) {
                    c.setFont(font);
                }
               
                shell.requestLayout();
                shell.layout();
            }
        });
       
        btnNewButton = new Button(shell, SWT.NONE);
        btnNewButton.setBounds(265, 105, 75, 25);
        btnNewButton.setText("Vergrößern");
        btnNewButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                Font font = new Font(display, new FontData("Arial", ++size, SWT.BOLD));
                for (Control c : shell.getChildren()) {
                    c.setFont(font);
                }
               
                shell.requestLayout();
                shell.layout();
            }
        });
    }
}

Grüße
lam

Nachtrag: An sich muss die shell nicht mal repaint werden, sobald das Control eine neue Font bekommt, reicht es.
 
Hallo Iam,
vielen Dank für deine schnelle Antwort. Das macht schon das, was ich brauche. Allerdings in meiner GUI, in der ich das anwende, bei jedem Child-Element gibt es noch weitere Child-Elemente und die Fonts werden da nicht gesetzt. Bei der Anweisung shell.getChildren() werden die Fonts bei den drunterliegenden Children gesetzt. Wie könnte ich alle abgreifen?
 
Hallo Iam,
vielen Dank für deine schnelle Antwort. Das macht schon das, was ich brauche. Allerdings in meiner GUI, in der ich das anwende, bei jedem Child-Element gibt es noch weitere Child-Elemente und die Fonts werden da nicht gesetzt. Bei der Anweisung shell.getChildren() werden die Fonts bei den drunterliegenden Children gesetzt. Wie könnte ich alle abgreifen?

Das kannst du doch über Rekursion lösen in dem du alle Kinder durchiterierst.
Link dazu: https://javabeginners.de/Grundlagen/Rekursion.php

Nachtrag: Aber nicht alle Controls haben Kinder, eventuell muss du davor noch abfragen ob control instanceOf Composite , dann hole deren Kinder.
 
Zuletzt bearbeitet:
Okay beim zweiten mal durchlesen hört sich man Satz sehr abwertend JavaFX gegenüber an.
Ja, das ist kein Zufall 🙂

Was ich sagen will ist, wenn man JavaFX gemacht hat, will man andere ältere Frontend APIs nicht mehr machen.
Nun, ich habe JavaFX öfters eine Chance gegeben (und werde das auch weiterhin tun), aber es wird nicht besser :-( So kehre ich immer wieder zu Swing zurück.
 
Ja, das ist kein Zufall 🙂


Nun, ich habe JavaFX öfters eine Chance gegeben (und werde das auch weiterhin tun), aber es wird nicht besser :-( So kehre ich immer wieder zu Swing zurück.

Schade, weil ich finde JavaFX ist eine verbesserte Variante von Swing. Alleine eine Tabelle oder Liste aufzustellen ist in Swing so aufwendig, abgesehen davon gibt es in Swing direkt kein Databinding und noch einiges mehr... Aber das weiß du wahrscheinlich schon alles.

Was ist deiner meiner nach nicht besser?
 
Was ist deiner meiner nach nicht besser?
JavaFX ist m.E. völlig over-engineered mit der Folge, dass es eher ein Toolkit (friss oder stirb) denn ein Framework (pass mich an) ist.

Es fängt schon damit an, dass für JavaFX ein eigener Programmeinstiegspunkt definiert wurde und eine Klasse Application abgeleitet werden muss. Weiter geht es mit der Tatsache, dass die halbe Collections API dupliziert wurde, dann dieses fürchterliche Property-Konzept, das gefühlt drei Milliarden Interfaces mit sich bringt und mit dem man sein Modell verseuchen soll. Reicht nicht schon Java Beans? Nein, jetzt braucht man auch noch JavaFX Beans.

Alles ist - zumindest in den Beispielen - explizit, so dass Tabellen völlig ineffizient werden. Erweiterbarkeit von Komponenten: das meiste ist private und somit nicht in abgeleiteten Klassen nutzbar. Wir hatten hier mal ein einfaches Beispiel, bei dem es darum ging, ein simples Label anzupassen.... der JavaFX-Weg: eine Krücke mit einem Listener, denn mal eben eine passende Komponente erstellen, ist nicht.

JavaFX ist IMO für eine ganz bestimmte Klasse von Anwendungen gedacht und geeignet. Für den großen Rest ist es m. E. unbrauchbar. Zumindest habe ich z. B. noch keine IDE gesehen, die auf JavaFX basiert.

Apropos: vielleicht habe ich das Binding unter FX auch einfach noch nicht verstanden. Machen wir mal ein einfaches, aber typisches Beispiel:
Java:
class Person {
    private String firstName;
    private String lastName
    // Getter und Setter 
}

In der Klasse befinden sich keine JavaFX-spezifischen Dinge.

Jetzt bitte ein Fenster mit zwei Textfeldern zur Bearbeitung einer Person, sowie zwei Buttons OK und Abbrechen. Natürlich darf die angezeigte Person-Instanz nicht verändert werden, wenn nicht auf OK gedrückt wird. Außerdem soll OK nur enabled sein, wenn tatsächlich Änderungen vorgenommen wurden.

Mit JGoodies Binding unter Swing (alle verwendeten Klassen stammen entweder von Swing oder JGoodies) sieht das in etwa so aus:
Java:
PresentationModel model = new PresentationModel(person);
JTextField firstName = BasicComponentFactory.createTextField(model.getBufferedModel("firstName"));
JTextField lastName = BasicComponentFactory.createTextField(model.getBufferedModel("lastName"));
JButton button = new JButton("OK");
button.addActionListener(e -> model.triggerCommit());
PropertyConnector.connect(model, PresentationModel.PROPERTYNAME_BUFFERING, button, "enabled");


Wie funktioniert das nun in JavaFX?
 
JavaFX ist m.E. völlig over-engineered mit der Folge, dass es eher ein Toolkit (friss oder stirb) denn ein Framework (pass mich an) ist.

Es fängt schon damit an, dass für JavaFX ein eigener Programmeinstiegspunkt definiert wurde und eine Klasse Application abgeleitet werden muss. Weiter geht es mit der Tatsache, dass die halbe Collections API dupliziert wurde, dann dieses fürchterliche Property-Konzept, das gefühlt drei Milliarden Interfaces mit sich bringt und mit dem man sein Modell verseuchen soll. Reicht nicht schon Java Beans? Nein, jetzt braucht man auch noch JavaFX Beans.

Alles ist - zumindest in den Beispielen - explizit, so dass Tabellen völlig ineffizient werden. Erweiterbarkeit von Komponenten: das meiste ist private und somit nicht in abgeleiteten Klassen nutzbar. Wir hatten hier mal ein einfaches Beispiel, bei dem es darum ging, ein simples Label anzupassen.... der JavaFX-Weg: eine Krücke mit einem Listener, denn mal eben eine passende Komponente erstellen, ist nicht.

JavaFX ist IMO für eine ganz bestimmte Klasse von Anwendungen gedacht und geeignet. Für den großen Rest ist es m. E. unbrauchbar. Zumindest habe ich z. B. noch keine IDE gesehen, die auf JavaFX basiert.

Apropos: vielleicht habe ich das Binding unter FX auch einfach noch nicht verstanden. Machen wir mal ein einfaches, aber typisches Beispiel:
Java:
class Person {
    private String firstName;
    private String lastName
    // Getter und Setter
}

In der Klasse befinden sich keine JavaFX-spezifischen Dinge.

Jetzt bitte ein Fenster mit zwei Textfeldern zur Bearbeitung einer Person, sowie zwei Buttons OK und Abbrechen. Natürlich darf die angezeigte Person-Instanz nicht verändert werden, wenn nicht auf OK gedrückt wird. Außerdem soll OK nur enabled sein, wenn tatsächlich Änderungen vorgenommen wurden.

Mit JGoodies Binding unter Swing (alle verwendeten Klassen stammen entweder von Swing oder JGoodies) sieht das in etwa so aus:
Java:
PresentationModel model = new PresentationModel(person);
JTextField firstName = BasicComponentFactory.createTextField(model.getBufferedModel("firstName"));
JTextField lastName = BasicComponentFactory.createTextField(model.getBufferedModel("lastName"));
JButton button = new JButton("OK");
button.addActionListener(e -> model.triggerCommit());
PropertyConnector.connect(model, PresentationModel.PROPERTYNAME_BUFFERING, button, "enabled");


Wie funktioniert das nun in JavaFX?
Bei vielen Punkten stimme ich dir zu es ist vielleicht over-engineered, aber schlussendlich für den Anwender ist es doch bequem zu benutzen und einfach mit wenig Aufwand kommt man schnell zum Ziel. Bei Custom Controls habe ich noch nicht viel Erfahrung, aber wenn ich etwas erweitern will kommt es mir sehr einfach vor, vor allem mit FXML ist das easy peasy.

Für so ein ähnliches Binding habe ich hier in JavaFX
Code:
StringProperty firstnameProperty = new SimpleStringProperty();
        StringProperty lastnameProperty = new SimpleStringProperty();
        BooleanBinding isEnabled = firstnameProperty.isNotEmpty().and(lastnameProperty.isNotEmpty());
        
        TextField firstName = new TextField();
        TextField lastName = new TextField();
        Button button = new Button("OK");
        button.setOnMouseClicked(e -> {
            
        });
        button.disableProperty().bind(isEnabled);

Nicht viel mehr Aufwand.
 
Zu viel Schreibarbeit, dachte ich könnt es mir sparen 🙂

Nagut nehmen wir das so hin, es ist Geschmackssache.
Mit Geschmackssache hat das nichts zu tun. Es gibt Anforderungen, die umgesetzt werden müssen und der Aufwand dafür ist messbar.

Swing ist veraltet, das ist keine Frage. FXML ist eine gute Sache, auch das ist keine Frage. JavaFX war als Swing-Ersatz angedacht. Dann erwarte ich, dass ich von JavaFX bei der Arbeit unterstützt werde (wie das z. B. bei FXML der Fall ist) und nicht, dass ich mir mehr Arbeit aufhalse.

In Deinem Listener oben müsste ich jetzt per Hand die Properties in das Person-Objekt kopieren. So weit ist es mit dem Binding von JavaFX also nicht her. Klar, man könnte sich eine Lib besorgen, die das für einen übernimmt (sofern es eine solche gibt) - aber wo ist dann der Vorteil von FX gegenüber Swing?
 
Das kannst du doch über Rekursion lösen in dem du alle Kinder durchiterierst.
Link dazu: https://javabeginners.de/Grundlagen/Rekursion.php

Nachtrag: Aber nicht alle Controls haben Kinder, eventuell muss du davor noch abfragen ob control instanceOf Composite , dann hole deren Kinder.
Ich habe in meinem Shell folgende Kinder liegen ein Menu und ein ScrolledComposite. Mit meiner rekursiven Funktion versuche ich die Fonts bei allen Elementen meiner Shell zu setzen. Leider habe ich festgestellt, dass die Fonts von Menu gar nicht gesetzt werden
Code:
    public void setFonts(Control control, Font font) {
        if (control instanceof Shell) {
            for (Control el : ((Shell) control).getChildren()) {
                setFonts(el, font);
            }
        } else if (control instanceof ScrolledComposite) {
            for (Control el : ((ScrolledComposite) control).getChildren()) {
                setFonts(el, font);
            }
        } else if (control instanceof SashForm) {
            for (Control el : ((SashForm) control).getChildren()) {
                setFonts(el, font);
            }
        } else if ((control instanceof Composite) & (!(control instanceof Tree) & !(control instanceof Combo)
                & !(control instanceof Table) & !(control instanceof ToolBar))) {
            for (Control el : ((Composite) control).getChildren()) {
                setFonts(el, font);
            }
        }else {
            control.setFont(font);
        }
    }
In der Schleife:
Code:
  if (control instanceof Shell) {
            for (Control el : ((Shell) control).getChildren()) {
                setFonts(el, font);
            }
        }
taucht nur der ScrolledComposite als Kind von Shell auf. Gibt es dafür eine Erklärung?
 

Zurück
Oben