Java 如何根据大小更改 JButton 的字体大小?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21063594/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 06:18:56  来源:igfitidea点击:

How to change font size of JButton according to its size?

javaswingfontsjbutton

提问by Andrew Vershinin

I have a java application - a calculator. I want to resize font of buttons dynamically with resizing the window of the app. How to implement it?

我有一个 Java 应用程序 - 一个计算器。我想通过调整应用程序窗口的大小来动态调整按钮的字体大小。如何实施?

My idea is using ComponentEvents. I have initial size of the window of application and initial fonts' sizes. I want to change font size according to button's size, affected by window size change. The problem is how to use the ratio [initial window size] / [initial font size] in the overriden method? The ratio is different for each font.

我的想法是使用 ComponentEvents。我有应用程序窗口的初始大小和初始字体的大小。我想根据按钮的大小更改字体大小,受窗口大小更改的影响。问题是如何在overriden方法中使用[初始窗口大小]/[初始字体大小]的比例?每种字体的比例不同。

import javax.swing.*;
import java.awt.*;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;

public class Main extends JFrame {
    public Main() {
        super("Test");

        JPanel cPane = (JPanel) getContentPane();
        cPane.setLayout(new BorderLayout());
        MyButton sampleButton = new MyButton("Sample text");
        sampleButton.setFont(new Font("Sans Serif", Font.PLAIN, 20));

        MyButton a, b, c, d;
        a = new MyButton("a");
        b = new MyButton("b");
        c = new MyButton("c");
        d = new MyButton("d");




        cPane.add(a, BorderLayout.PAGE_START);
        cPane.add(b, BorderLayout.PAGE_END);
        cPane.add(c, BorderLayout.LINE_START);
        cPane.add(d, BorderLayout.LINE_END);

        cPane.add(sampleButton, BorderLayout.CENTER);
        setSize(300, 200);
        setResizable(true);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setVisible(true);
    }

    public static void main(String... args) {
        new Main();
    }

    class MyButton extends JButton implements ComponentListener {
        public MyButton(String title) {
            super(title);
        }

        @Override
        public void componentResized(ComponentEvent e) {
            //resizing font
        }

        @Override
        public void componentMoved(ComponentEvent e) {

        }

        @Override
        public void componentShown(ComponentEvent e) {

        }

        @Override
        public void componentHidden(ComponentEvent e) {

        }
    }
}

采纳答案by Andrew Thompson

See how you go with this code using GlyphVectorto determine the largest Fontthat will fit.

看看您如何使用此代码GlyphVector来确定Font适合的最大值。

  • The GUI was a little shaky unless there was a delay between setting the frame visible and adding the ComponentListener. I solved that by delaying adding the listener using a single shot Swing Timer.
  • Is is based on Calculetwhich is a fully functioning (if simple) calculator using the ScriptEngine.
  • GUI 有点不稳定,除非在设置框架可见和添加ComponentListener. 我通过使用单次 Swing 延迟添加侦听器来解决这个问题Timer
  • Is 基于Calculet哪个是使用ScriptEngine.

Initial

最初的

Bigger

大

import java.awt.*;
import java.awt.event.*;
import java.awt.font.*;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.util.ArrayList;
import javax.script.*;
import javax.swing.border.Border;

class SwingCalculator implements ActionListener, KeyListener {

    JTextField io;
    ScriptEngine engine;
    ArrayList<JButton> controls;
    final BufferedImage textImage = new BufferedImage(
            100, 100,
            BufferedImage.TYPE_INT_ARGB);

    public int getMaxFontSizeForControls() {
        Graphics2D g = textImage.createGraphics();
        FontRenderContext frc = g.getFontRenderContext();
        int maxSize = 500;
        for (JButton b : controls) {
            // skip the = button..
            if (!b.getText().equals("=")) {
                int max = getMaxFontSizeForControl(b, frc);
                if (maxSize > max) {
                    maxSize = max;
                }
            }
        }
        g.dispose();
        return maxSize;
    }

    public int getMaxFontSizeForControl(JButton button, FontRenderContext frc) {
        Rectangle r = button.getBounds();
        Insets m = button.getMargin();
        Insets i = button.getBorder().getBorderInsets(button);
        Rectangle viewableArea = new Rectangle(
                r.width - 
                (m.right + m.left + i.left + i.right),
                r.height - 
                (m.top + m.bottom + i.top + i.bottom)
                );
        Font font = button.getFont();
        int size = 1;
        boolean tooBig = false;
        while (!tooBig) {
            Font f = font.deriveFont((float) size);
            GlyphVector gv = f.createGlyphVector(frc, button.getText());
            Rectangle2D box = gv.getVisualBounds();
            if (box.getHeight() > viewableArea.getHeight()
                    || box.getWidth() > viewableArea.getWidth()) {
                tooBig = true;
                size--;
            }
            size++;
        }
        return size;
    }

    SwingCalculator() {
        // obtain a reference to the JS engine
        engine = new ScriptEngineManager().getEngineByExtension("js");

        JPanel gui = new JPanel(new BorderLayout(2, 2));
        controls = new ArrayList<JButton>();

        JPanel text = new JPanel(new GridLayout(0, 1, 3, 3));
        gui.add(text, BorderLayout.NORTH);
        io = new JTextField(15);
        Font font = io.getFont();
        font = font.deriveFont(font.getSize() * 1.7f);
        io.setFont(font);
        io.setHorizontalAlignment(SwingConstants.TRAILING);
        io.setFocusable(false);
        text.add(io);

        JPanel buttons = new JPanel(new GridLayout(4, 4, 2, 2));
        gui.add(buttons, BorderLayout.CENTER);
        addButton(buttons, "7");
        addButton(buttons, "8");
        addButton(buttons, "9");
        addButton(buttons, "/");

        addButton(buttons, "4");
        addButton(buttons, "5");
        addButton(buttons, "6");
        addButton(buttons, "*");

        addButton(buttons, "1");
        addButton(buttons, "2");
        addButton(buttons, "3");
        addButton(buttons, "-");

        addButton(buttons, "0");
        addButton(buttons, ".");
        addButton(buttons, "C");
        addButton(buttons, "+");

        JButton equals = new JButton("=");
        equals.addKeyListener(this);
        controls.add(equals);
        equals.addActionListener(this);
        gui.add(equals, BorderLayout.EAST);

        gui.setBorder(new EmptyBorder(5, 5, 5, 5));

        final JFrame f = new JFrame("Calculet");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setContentPane(gui);
        f.pack();
        f.setMinimumSize(f.getSize());
        f.setLocationByPlatform(true);
        f.setVisible(true);

        final ComponentListener cl = new ComponentAdapter() {

            @Override
            public void componentResized(ComponentEvent e) {
                int ii = getMaxFontSizeForControls();
                for (JButton b : controls) {
                    if (!b.getText().equals("=")) {
                        b.setFont(b.getFont().deriveFont((float) ii));
                    }
                }
            }
        };
        ActionListener al = new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                f.addComponentListener(cl);
            }
        };
        Timer t = new Timer(500, al);
        t.setRepeats(false);
        t.start();
    }

    public void addButton(Container c, String text) {
        JButton b = new JButton(text);
        b.addActionListener(this);
        b.addKeyListener(this);
        controls.add(b);
        c.add(b);
    }

    public void calculateResult() {
        try {
            Object result = engine.eval(io.getText());
            if (result == null) {
                io.setText("Output was 'null'");
            } else {
                io.setText(result.toString());
            }
        } catch (ScriptException se) {
            io.setText(se.getMessage());
        }
    }

    public void actionPerformed(ActionEvent ae) {
        String command = ae.getActionCommand();
        if (command.equals("C")) {
            io.setText("");
        } else if (command.equals("=")) {
            calculateResult();
        } else {
            io.setText(io.getText() + command);
        }
    }

    private JButton getButton(String text) {
        for (JButton button : controls) {
            String s = button.getText();
            if (text.endsWith(s)
                    || (s.equals("=")
                    && (text.equals("Equals") || text.equals("Enter")))) {

                return button;
            }
        }
        return null;
    }

    /*
     * START - Because I hate mice.
     */
    public void keyPressed(KeyEvent ke) {
    }

    public void keyReleased(KeyEvent ke) {
        String s = ke.getKeyText(ke.getKeyCode());
        JButton b = getButton(s);
        if (b != null) {
            b.requestFocusInWindow();
            b.doClick();
        }
    }

    public void keyTyped(KeyEvent ke) {
    }

    public static void main(String[] args) {
        Runnable r = new Runnable() {

            @Override
            public void run() {
                new SwingCalculator();
            }
        };
        // Swing GUIs should be created and updated on the EDT
        // http://docs.oracle.com/javase/tutorial/uiswing/concurrency
        SwingUtilities.invokeLater(r);
    }
}

回答by trashgod

Compare the approaches shown hereand here. The former uses an available JComponent.sizeVariant.

比较此处此处显示的方法。前者使用可用的JComponent.sizeVariant.

image1

图片1

The latter cites an example using FontMentrics.

后者引用了一个使用FontMentrics.

image2

图像2

Or TextLayout.

或者TextLayout

image3

图像3