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

我有一个java应用程序 – 一个计算器。 我想通过调整应用程序窗口的大小来动态调整按钮的字体大小。 怎么实现呢?

我的想法是使用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) { } } } 

了解如何使用GlyphVector来确定最适合的Font

  • 除非在设置框架可见和添加ComponentListener之间存在延迟,否则GUI有点不稳定。 我通过使用单次拍摄Swing Timer延迟添加监听器来解决这个问题。
  • 是基于Calculet ,它是一个使用ScriptEnginefunction齐全(如果简单)的计算器。

初始

大

 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 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(); 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); } } 

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

此搜索

后者引用了使用FontMentrics的示例。

图像2

TextLayout

图像3