如何让Java计算器的JButton/JPanel随JFrame自适应调整大小?
实现Java计算器的自适应布局
你的计算器当前使用**绝对布局(null layout)**和固定坐标(setBounds),这是组件无法随窗口拉伸调整的核心原因。要实现自适应,需要替换为Java Swing提供的弹性布局管理器,以下是改造后的完整方案:
关键改造点
- 移除
frame.setLayout(null)和所有setBounds调用,改用BorderLayout作为窗口主布局,搭配GridLayout管理按钮面板 - 使用
BorderFactory.createEmptyBorder()设置整体边距,替代固定的坐标偏移 - 用
frame.pack()替代固定窗口尺寸,让窗口自动适配组件大小,同时设置最小尺寸避免窗口过小 - 为按钮面板设置合适的行列数和间距,确保按钮均匀分配空间
改造后的完整代码
import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class Calculator implements ActionListener { JFrame frame; JTextField textfield; JButton[] numberButtons = new JButton[10]; JButton[] functionButtons = new JButton[14]; JButton addButton, subButton, mulButton, divButton; JButton decButton, equButton, delButton, clrButton, negButton; JButton perButton, absButton, piButton, sqrButton, srootButton; // 补充原代码缺失的常量定义 private final Color functionColor = new Color(255, 159, 67); private final Color numberColor = new Color(51, 51, 51); private final Color top = new Color(204, 204, 204); private final String add = "+", sub = "-", mul = "×", div = "÷", equ = "=", delete = "←"; Font myFont = new Font("Helvetica", Font.BOLD, 30); double num1, num2, result = 0; char operator; Calculator() { frame = new JFrame("Calculator"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 主布局改用BorderLayout,设置整体边距 frame.setLayout(new BorderLayout(10, 10)); frame.setBorder(BorderFactory.createEmptyBorder(25, 25, 25, 25)); textfield = new JTextField(); textfield.setFont(myFont); textfield.setEditable(false); textfield.setBorder(null); // 文本框放在顶部,自动填充水平空间 frame.add(textfield, BorderLayout.NORTH); // 初始化功能按钮 addButton = new JButton(add); addButton.setBackground(functionColor); subButton = new JButton(sub); subButton.setBackground(functionColor); mulButton = new JButton(mul); mulButton.setBackground(functionColor); divButton = new JButton(div); divButton.setBackground(functionColor); equButton = new JButton(equ); equButton.setBackground(functionColor); decButton = new JButton("."); decButton.setBackground(numberColor); decButton.setForeground(Color.WHITE); clrButton = new JButton("AC"); clrButton.setBackground(top); clrButton.setForeground(Color.BLACK); negButton = new JButton("+/- "); negButton.setBackground(top); negButton.setForeground(Color.BLACK); delButton = new JButton(delete); delButton.setBackground(top); delButton.setForeground(Color.BLACK); perButton = new JButton("%"); perButton.setBackground(top); perButton.setForeground(Color.BLACK); absButton = new JButton("|x|"); absButton.setBackground(top); absButton.setForeground(Color.BLACK); piButton = new JButton("𝝅"); piButton.setBackground(top); piButton.setForeground(Color.BLACK); sqrButton = new JButton("x²"); sqrButton.setBackground(top); sqrButton.setForeground(Color.BLACK); srootButton = new JButton("√x"); srootButton.setBackground(top); srootButton.setForeground(Color.BLACK); // 功能按钮数组赋值 functionButtons[0] = addButton; functionButtons[1] = subButton; functionButtons[2] = mulButton; functionButtons[3] = divButton; functionButtons[4] = decButton; functionButtons[5] = equButton; functionButtons[6] = delButton; functionButtons[7] = clrButton; functionButtons[8] = negButton; functionButtons[9] = perButton; functionButtons[10] = piButton; functionButtons[11] = absButton; functionButtons[12] = sqrButton; functionButtons[13] = srootButton; // 为功能按钮添加监听和样式 for (int i = 0; i < 14; i++) { functionButtons[i].addActionListener(this); functionButtons[i].setFont(myFont); functionButtons[i].setFocusable(false); } // 初始化数字按钮 for (int i = 0; i < 10; i++) { numberButtons[i] = new JButton(String.valueOf(i)); numberButtons[i].addActionListener(this); numberButtons[i].setFont(myFont); numberButtons[i].setFocusable(false); numberButtons[i].setBackground(numberColor); numberButtons[i].setForeground(Color.WHITE); } // 创建中间面板容器,用垂直BoxLayout管理三个按钮面板 JPanel centerContainer = new JPanel(); centerContainer.setLayout(new BoxLayout(centerContainer, BoxLayout.Y_AXIS)); centerContainer.setBorder(BorderFactory.createEmptyBorder(20, 0, 0, 0)); // 顶部功能按钮面板 JPanel topPan = new JPanel(); topPan.setLayout(new GridLayout(1, 4, 10, 10)); topPan.add(negButton); topPan.add(absButton); topPan.add(clrButton); topPan.add(delButton); centerContainer.add(topPan); // 次级功能按钮面板 JPanel secPan = new JPanel(); secPan.setLayout(new GridLayout(1, 4, 10, 10)); secPan.add(piButton); secPan.add(perButton); secPan.add(sqrButton); secPan.add(srootButton); secPan.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); centerContainer.add(secPan); // 数字与运算按钮面板 JPanel panel = new JPanel(); panel.setLayout(new GridLayout(4, 4, 10, 10)); panel.add(numberButtons[7]); panel.add(numberButtons[8]); panel.add(numberButtons[9]); panel.add(mulButton); panel.add(numberButtons[4]); panel.add(numberButtons[5]); panel.add(numberButtons[6]); panel.add(subButton); panel.add(numberButtons[1]); panel.add(numberButtons[2]); panel.add(numberButtons[3]); panel.add(addButton); panel.add(numberButtons[0]); panel.add(decButton); panel.add(equButton); panel.add(divButton); centerContainer.add(panel); // 将中间容器添加到窗口中央 frame.add(centerContainer, BorderLayout.CENTER); // 设置窗口最小尺寸,自动适配组件大小 frame.setMinimumSize(new Dimension(400, 500)); frame.pack(); frame.setVisible(true); } @Override public void actionPerformed(ActionEvent e) { // 保留原有的事件处理逻辑,此处省略具体实现 } public static void main(String[] args) { SwingUtilities.invokeLater(Calculator::new); } }
额外优化建议
- 如果希望按钮字体随窗口大小动态调整,可以重写组件的
paintComponent方法,结合FontMetrics计算适配字体 - 无需为按钮设置固定尺寸,布局管理器会根据窗口大小自动分配空间
内容的提问来源于stack exchange,提问作者Sajal
相关产品推荐
相关产品推荐

