Swing Anpassen der Textgröße im JLabel funktioniert nur bedingt

HerrInfo

Aktives Mitglied
Hallo zusammen,
ich versuche in Moment eine GUI für meinen Taschenrechner zu schreiben. Diese ist soweit auch gut, nur leider funktioniert das Anpassen der Textgröße im JLabel beim Drücken des JButtons "Gleich" nicht. Bei den anderen Buttons funktioniert dies. Ich hoffe, ihr könnt mir dabei helfen.

Java:
import javax.swing.*;
import java.awt.*;
import java.util.Objects;

public class MyFrame extends JFrame {
    private String rechnung;
    private boolean weitermachen;
    JLabel rechnunglabel;
    JPanel rechnunghintergrund;
    JPanel rechnungsPanel;
    JButton[] Buttonnumbers = new JButton[10];
    JButton kommerta = new JButton();
    JButton plusminus = new JButton();
    JButton plus = new JButton();
    JButton minus = new JButton();
    JButton mal = new JButton();
    JButton geteilt = new JButton();
    JButton gleich = new JButton();

    JButton ac = new JButton();

    MyFrame() {
        weitermachen = true;
        rechnung = "";
        this.setTitle("Rechner");
        this.setSize(400, 600);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        ImageIcon image = new ImageIcon("D://Java//IntelliJ IDEA Community Edition 2022.2.1//Projekts//Rechner//src//Rechner_logo.png");
        this.setIconImage(image.getImage());
        this.getContentPane().setBackground(new Color(0x123456));
        this.setResizable(false);
        this.setLayout(null);


        rechnunghintergrund = new JPanel();
        rechnunghintergrund.setBounds(0, 0, 400, 125);
        rechnunghintergrund.setBackground(new Color(0x02164E));

        rechnunglabel = new JLabel();
        rechnunglabel.setForeground(Color.WHITE);
        rechnunglabel.setText("");


        for (int i = 0; i < Buttonnumbers.length; i++) {
            Buttonnumbers[i] = new JButton();
            Buttonnumbers[i].setText(String.valueOf(i));
            Buttonnumbers[i].setFont(new Font("Comic Sans", Font.BOLD, 30));
            Buttonnumbers[i].setFocusable(false);
            this.add(Buttonnumbers[i]);
        }
        Buttonnumbers[0].setBounds(110, 500, 70, 50);
        Buttonnumbers[1].setBounds(10, 425, 70, 50);
        Buttonnumbers[2].setBounds(110, 425, 70, 50);
        Buttonnumbers[3].setBounds(210, 425, 70, 50);
        Buttonnumbers[4].setBounds(10, 350, 70, 50);
        Buttonnumbers[5].setBounds(110, 350, 70, 50);
        Buttonnumbers[6].setBounds(210, 350, 70, 50);
        Buttonnumbers[7].setBounds(10, 275, 70, 50);
        Buttonnumbers[8].setBounds(110, 275, 70, 50);
        Buttonnumbers[9].setBounds(210, 275, 70, 50);

        Buttonnumbers[0].addActionListener(e -> {
            addCharakter('0');
            rechnunglabel.setText(rechnung);
            rechnungsgroesseanpassen();
        });
        Buttonnumbers[1].addActionListener(e -> {
            addCharakter('1');
            rechnunglabel.setText(rechnung);
            rechnungsgroesseanpassen();
        });
        Buttonnumbers[2].addActionListener(e -> {
            addCharakter('2');
            rechnunglabel.setText(rechnung);
            rechnungsgroesseanpassen();
        });
        Buttonnumbers[3].addActionListener(e -> {
            addCharakter('3');
            rechnunglabel.setText(rechnung);
            rechnungsgroesseanpassen();
        });
        Buttonnumbers[4].addActionListener(e -> {
            addCharakter('4');
            rechnunglabel.setText(rechnung);
            rechnungsgroesseanpassen();
        });
        Buttonnumbers[5].addActionListener(e -> {
            addCharakter('5');
            rechnunglabel.setText(rechnung);
            rechnungsgroesseanpassen();
        });
        Buttonnumbers[6].addActionListener(e -> {
            addCharakter('6');
            rechnunglabel.setText(rechnung);
            rechnungsgroesseanpassen();
        });
        Buttonnumbers[7].addActionListener(e -> {
            addCharakter('7');
            rechnunglabel.setText(rechnung);
            rechnungsgroesseanpassen();
        });
        Buttonnumbers[8].addActionListener(e -> {
            addCharakter('8');
            rechnunglabel.setText(rechnung);
            rechnungsgroesseanpassen();
        });
        Buttonnumbers[9].addActionListener(e -> {
            addCharakter('9');
            rechnunglabel.setText(rechnung);
            rechnungsgroesseanpassen();
        });

        kommerta.setText(",");
        kommerta.setFont(new Font("Comic Sans", Font.BOLD, 30));
        kommerta.setFocusable(false);
        kommerta.setBounds(210, 500, 70, 50);
        kommerta.addActionListener(e -> {
            if (rechnung.endsWith("-") || rechnung.endsWith("+") || rechnung.endsWith("*") || rechnung.endsWith("/") || rechnung.endsWith(".")) {

            } else {
                addCharakter('.');
            }
            rechnunglabel.setText(rechnung);
            rechnungsgroesseanpassen();
        });
        this.add(kommerta);

        plusminus.setText("+/-");
        plusminus.setFocusable(false);
        plusminus.setBounds(10, 500, 70, 50);
        plusminus.addActionListener(e -> {
            addCharakter('-');
            rechnunglabel.setText(rechnung);
            rechnungsgroesseanpassen();
        });
        this.add(plusminus);

        plus.setText("+");
        plus.setFont(new Font("Comic Sans", Font.BOLD, 30));
        plus.setFocusable(false);
        plus.setBounds(310, 425, 70, 50);
        plus.addActionListener(e -> {
            if (rechnung.endsWith("-") || rechnung.endsWith("+") || rechnung.endsWith("*") || rechnung.endsWith("/") || rechnung.endsWith(".")) {

            } else {
                addCharakter('+');
            }
            rechnunglabel.setText(rechnung);
            rechnungsgroesseanpassen();
        });
        this.add(plus);

        minus.setText("-");
        minus.setFont(new Font("Comic Sans", Font.BOLD, 30));
        minus.setFocusable(false);
        minus.setBounds(310, 350, 70, 50);
        minus.addActionListener(e -> {
            if (rechnung.endsWith("-") || rechnung.endsWith("+") || rechnung.endsWith("*") || rechnung.endsWith("/") || rechnung.endsWith(".")) {

            } else {
                addCharakter('-');
            }
            rechnunglabel.setText(rechnung);
            rechnungsgroesseanpassen();
        });
        this.add(minus);

        mal.setText("x");
        mal.setFont(new Font("Comic Sans", Font.BOLD, 30));
        mal.setFocusable(false);
        mal.setBounds(310, 275, 70, 50);
        mal.addActionListener(e -> {
            if (rechnung.endsWith("-") || rechnung.endsWith("+") || rechnung.endsWith("*") || rechnung.endsWith("/") || rechnung.endsWith(".")) {

            } else {
                addCharakter('*');
            }
            rechnunglabel.setText(rechnung);
            rechnungsgroesseanpassen();
        });
        this.add(mal);

        geteilt.setText("/");
        geteilt.setFont(new Font("Comic Sans", Font.BOLD, 30));
        geteilt.setFocusable(false);
        geteilt.setBounds(310, 200, 70, 50);
        geteilt.addActionListener(e -> {
            if (rechnung.endsWith("-") || rechnung.endsWith("+") || rechnung.endsWith("*") || rechnung.endsWith("/") || rechnung.endsWith(".")) {

            } else {
                addCharakter('/');
            }
            rechnunglabel.setText(rechnung);
            rechnungsgroesseanpassen();
        });
        this.add(geteilt);

        ac.setText("AC");
        ac.setBounds(210, 200, 70, 50);
        ac.setFocusable(false);
        ac.addActionListener(e -> {

            for (JButton number : Buttonnumbers) {
                number.setEnabled(true);
            }
            kommerta.setEnabled(true);
            plusminus.setEnabled(true);
            plus.setEnabled(true);
            minus.setEnabled(true);
            mal.setEnabled(true);
            geteilt.setEnabled(true);
            gleich.setEnabled(true);

            try {
                Thread.sleep(100);
            } catch (InterruptedException ex) {
                throw new RuntimeException(ex);
            }
            rechnunglabel.setText("");
            rechnunglabel.setForeground(Color.WHITE);
            this.rechnung = "";
            weitermachen = true;
            Rechner.loesung = "";
            Rechner.zwischenloesung = 0;
            rechnungsgroesseanpassen();
        });
        this.add(ac);


        gleich.setText("=");
        gleich.setFont(new Font("Comic Sans", Font.BOLD, 30));
        gleich.setFocusable(false);
        gleich.setBounds(310, 500, 70, 50);
        gleich.addActionListener(e -> {

            for (JButton number : Buttonnumbers) {
                number.setEnabled(false);
            }
            kommerta.setEnabled(false);
            plusminus.setEnabled(false);
            plus.setEnabled(false);
            minus.setEnabled(false);
            mal.setEnabled(false);
            geteilt.setEnabled(false);
            gleich.setEnabled(false);

            weitermachen = false;

            try {
                Thread.sleep(100);
            } catch (InterruptedException ex) {
                throw new RuntimeException(ex);
            }
            if (Objects.equals(Rechner.loesung, "Error")) {
                rechnunglabel.setVisible(false);
                rechnunglabel.setText("Das kann ich noch nicht rechnen");
                rechnunglabel.setForeground(Color.RED);
                rechnunglabel.setVisible(true);
            } else {
                rechnung = Rechner.loesung;
                rechnunglabel.setText(rechnung);
            }
            rechnungsgroesseanpassen();
        });

        this.add(gleich);


        //this.setExtendedState(MAXIMIZED_BOTH); Fullscreen


        rechnunglabel.setBounds(100, 50, 1000, 25);
        rechnunglabel.setFont(new Font("Comic Sans", Font.BOLD, 20));
        rechnunglabel.setForeground(Color.WHITE);
        this.add(rechnunglabel);
        this.add(rechnunghintergrund);
        this.setVisible(true);
    }

    public void addCharakter(Character Zeichen) {
        this.rechnung = this.rechnung + Zeichen;
    }

    public String getRechnung() {
        return rechnung;
    }

    public boolean getweitermachen() {
        return weitermachen;
    }

    private void rechnungsgroesseanpassen() {
        switch (rechnunglabel.getText().length()) {
            case 0 -> {
                rechnunglabel.setFont(new Font("Comic Sans", Font.BOLD, 20));
                rechnunglabel.setBounds(100, 50, 1000, 25);
            }
            case 18 -> rechnunglabel.setFont(new Font("Comic Sans", Font.BOLD, 19));
            case 20 -> rechnunglabel.setFont(new Font("Comic Sans", Font.BOLD, 18));
            case 22 -> rechnunglabel.setFont(new Font("Comic Sans", Font.BOLD, 17));
            case 24 -> {
                rechnunglabel.setFont(new Font("Comic Sans", Font.BOLD, 16));
                rechnunglabel.setBounds(90, 50, 1000, 25);
            }
            case 26 -> {
                rechnunglabel.setFont(new Font("Comic Sans", Font.BOLD, 15));
                rechnunglabel.setBounds(80, 50, 1000, 25);
            }
            case 28 -> {
                rechnunglabel.setFont(new Font("Comic Sans", Font.BOLD, 14));
                rechnunglabel.setBounds(70, 50, 1000, 25);
            }
            case 34 -> {
                rechnunglabel.setFont(new Font("Comic Sans", Font.BOLD, 13));
                rechnunglabel.setBounds(60, 50, 1000, 25);
            }
            case 40 -> {
                rechnunglabel.setFont(new Font("Comic Sans", Font.BOLD, 12));
                rechnunglabel.setBounds(50, 50, 1000, 25);
            }
            case 46 -> {
                rechnunglabel.setFont(new Font("Comic Sans", Font.BOLD, 11));
                rechnunglabel.setBounds(40, 50, 1000, 25);
            }
            case 48 -> {
                rechnunglabel.setFont(new Font("Comic Sans", Font.BOLD, 10));
                rechnunglabel.setBounds(30, 50, 1000, 25);
            }
        }
    }
}
 

Anhänge

  • Bild.PNG
    Bild.PNG
    15,2 KB · Aufrufe: 9
  • Bild2.PNG
    Bild2.PNG
    17,3 KB · Aufrufe: 6
Ich bin mir ziemlich sicher dass das Problem mit dem Thread.sleep zusammenhängt, da du damit quasi den Haupthread der GUI für 100 ms einfrierst. Quick & Dirty könnte ein label.repaint() im Anschluss helfen, besser jedoch wäre es wenn du einen javax.swing.Timer benutzen würdest, der nach 100 ms deine übrigen Befehle ausführt.

Generell würde ich dir für bessere Lesbarkeit raten den Code in mehrer Klassen und Funktionen auszulagern. Z.b. eine Klasse für die Events die ActionListener implementiert, zumindest für die größeren Events.
 
Hallo zusammen,
ich versuche in Moment eine GUI für meinen Taschenrechner zu schreiben. Diese ist soweit auch gut,
Du solltest die GUI vom eigentlichen Rechner trennen. Und redundanten Code vermeiden.
Normalerweise schreibt man zuerst den Rechner und dann die passende GUI dazu.
Du könntest aber ein Interface vereinbaren. z.B.
Java:
public interface Calculator {
    /**
     * Checks, if string contains a valid term.
     *
     * @param txt
     *            String containing calculation
     * @return boolean
     */
    public boolean isValid(String txt);

    /**
     * Evaluates term and returns result represented by a String.
     *
     * @param txt
     *            String containing calculation
     * @return String
     */
    public String evaluate(String txt);

}
Dann einen Dummy Calculator schreiben.
Java:
public class EasyCalc implements Calculator {
    // Use a Parser class here.

    @Override
    public boolean isValid(String txt) {
        // TODO
        return true;
    }

    @Override
    public String evaluate(String txt) {
        // TODO
        return txt;
    }

}
Und anschließend eine GUI entwickeln.
1670726288540.png
Java:
import javax.swing.JFrame;

public class StartEasyCalc {
    public static void main(String[] args) {
        JFrame frame = new JFrame("Calculator");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new CalculatorGUI(new EasyCalc(), 80));
        frame.pack();
        frame.setVisible(true);
        frame.setResizable(false);
    }
}
Java:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.border.BevelBorder;
import javax.swing.border.Border;

@SuppressWarnings("serial")
public class CalculatorGUI extends JPanel {
    private JButton[] button;
    private Display display;
    private int btnWidth;
    private Calculator calc;
    private String memory = null;

    public CalculatorGUI(Calculator calc, int btnWidth) {
        this.btnWidth = btnWidth;
        this.calc = calc;
        setBackground(new Color(0x02164E));
        this.calc = calc;
    }

    public void addNotify() {
        super.addNotify();
        create();
    }

    private void create() {
        setLayout(null);
        int off = btnWidth / 5;
        int width = 5 * off + 4 * btnWidth;
        int height = 12 * width / 11;
        int numBtnPerLine = 4;
        int btnHeight = getBtnHeight();
        setPreferredSize(new Dimension(width, height));
        int displayHeight = height / 5;
        display = new Display(width - 2 * off, displayHeight);
        add(display);
        display.setBounds(off, off, width - 2 * off, displayHeight);
        createButtons(off, numBtnPerLine, btnHeight, displayHeight);
    }

    public void createButtons(int off, int numBtnPerLine, int btnHeight, int displayHeight) {
        String[] btnNames = { "mr", "ms", "ac", "/", "7", "8", "9", "x", "4", "5", "6", "-", "1", "2", "3", "+", "+/-",
                "0", ",", "=" };
        button = new JButton[btnNames.length];
        Border b = BorderFactory.createBevelBorder(BevelBorder.RAISED);
        for (int i = 0; i < btnNames.length; i++) {
            button[i] = new JButton(btnNames[i]);
            add(button[i]);
            int idX = i % numBtnPerLine;
            int idY = i / numBtnPerLine;
            int x = off + idX * btnWidth + idX * off;
            int y = displayHeight + 2 * off + idY * btnHeight + idY * off;
            button[i].setBounds(x, y, btnWidth, btnHeight);
            button[i].setFont(getFont(button[i].getText()));
            button[i].setBorder(b);
            button[i].setBackground(Color.GREEN.darker());
            button[i].setFocusable(false);
            button[i].setForeground(Color.WHITE);
            button[i].addActionListener(e -> {
                String cmd = e.getActionCommand();
                String txt = display.getText();
                switch (cmd) {
                case "=": // calculate result
                    display.setText(calc.evaluate(txt));
                    return;
                case "mr": // read memory
                    if (memory != null)
                        display.setText(memory);
                    return;
                case "ms": // store memory
                    memory = txt;
                    return;
                case "ac":
                    display.clear();
                    return;
                default: // build calculation string
                    if (calc.isValid(txt + cmd))
                        display.setText(txt + cmd);
                }
            });
        }
    }

    public int getBtnHeight() {
        return 3 * btnWidth / 5;
    }

    private Font getFont(String txt) {
        int size = FontUtil.fitTextSize(getGraphics(), txt, (int) (btnWidth * .33), 3 * getBtnHeight() / 4);
        return new Font("Comic Sans", Font.BOLD, size);
    }

}
Java:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.border.BevelBorder;

@SuppressWarnings("serial")
public class Display extends JLabel {
    public Display(int width, int height) {
        setPreferredSize(new Dimension(width, height));
        setOpaque(true);
        setBackground(Color.LIGHT_GRAY);
        setForeground(Color.WHITE);
        setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
        setHorizontalAlignment(JLabel.RIGHT);
        setFont(new Font("Comic Sans", Font.BOLD, height / 2));
    }

    public void clear() {
        setText("");
    }

    @Override
    public void setText(String txt) {
        int size = FontUtil.fitTextSize(getGraphics(), txt, getWidth() - 10, getHeight() / 2);
        if (size < getHeight() / 5)
            return;
        Font font = new Font("Comic Sans", Font.BOLD, size);
        setFont(font);
        super.setText(txt);
    }

}
Java:
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;

public class FontUtil {
    public static int fitTextSize(Graphics g, String txt, int width, int size) {
        if (g == null)
            return 0;
        Font fontOld = g.getFont();
        FontMetrics fm = null;
        do {
            g.setFont(new Font("Comic Sans", Font.BOLD, size--));
            fm = g.getFontMetrics();
        } while (fm.stringWidth(txt) > width);
        g.setFont(fontOld);
        return size;
    }

}
Jetzt fehlt lediglich ein Parser und der eigentliche Rechner.
 
Was heißt "funktioniert nicht"? Mal abgesehen davon, dass dieses absolute Layout bescheiden ist, wird die Textgröße doch angepasst.
Dankeschön für die schnelle und Ausführliche Antwort.
Funktioniert nicht bedeutet in dem Fall, dass der rote Text(siehe Bild 1) nicht wie die Zahlen(siehe Bild2) verkleinert wird und in die Mitte versetzt wird.
 
Ich werde auf jeden Fall erst einmal Übersicht in meinen Code zu bringen. Daran, die GUI in unterschiedliche Klassen einzuteilen, habe ich gar nicht gedacht. Die Idee von @Blender3D finde ich sehr hilfreich und ich werde mir sie nochmal genauer anschauen. Vielen Dank dafür.
 

Zurück
Oben