使用JPanel在GUI中相互覆盖图层

我在制作简单计算器的布局时遇到了麻烦。 发生的事情是,除了我的减法按钮保留为背景之外,一切看起来都很好,我必须猜测我的其他按钮能够点击它们的位置。 当我点击它们时,我能够看到它们,直到我取消它们。 有没有什么办法解决这一问题? 我不会发布数学算法,因为这个问题不需要。

import javax.swing.*; import java.awt.*; import java.awt.event.*; public class GUIcalc extends JFrame implements ActionListener { private JPanel panel; private JPanel buttonpanel; private JPanel text; private JLabel sumfield; private BorderLayout layout; private GridLayout grid; private Container container; private boolean toggle=true; private float sum; private int num1; private int num2; JButton one = new JButton("1"); JButton two = new JButton("2"); JButton three = new JButton("3"); JButton four = new JButton("4"); JButton five = new JButton("5"); JButton six = new JButton("6"); JButton seven = new JButton("7"); JButton eight = new JButton("8"); JButton nine = new JButton("9"); JButton zero = new JButton("0"); JButton multi = new JButton("*"); JButton divide = new JButton("/"); JButton equal = new JButton("="); JButton add = new JButton("+"); JButton subtract = new JButton("-"); JButton deci = new JButton("."); private final Font number= new Font("monspaced", Font.ITALIC, 20); JFrame guiFrame; private int counter; /** * @param args */ public GUIcalc() { super("Calculator"); sumfield = new JLabel(""+sum); sumfield.setLocation(0, 0); sumfield.setSize(245, 45); add(sumfield); seven=new JButton("7"); seven.setLocation(0,50); seven.setSize(50, 50); seven.addActionListener(this); add(seven); eight=new JButton("8"); eight.setLocation(55,50); eight.setSize(50, 50); eight.addActionListener(this); add(eight); nine=new JButton("9"); nine.setLocation(110,50); nine.setSize(50, 50); nine.addActionListener(this); add(nine); divide=new JButton("/"); divide.setLocation(165,50); divide.setSize(50, 50); divide.addActionListener(this); add(divide); six=new JButton("6"); six.setLocation(0,105); six.setSize(50, 50); six.addActionListener(this); add(six); five=new JButton("5"); five.setLocation(55,105); five.setSize(50, 50); five.addActionListener(this); add(five); four=new JButton("4"); four.setLocation(110,105); four.setSize(50, 50); four.addActionListener(this); add(four); multi=new JButton("*"); multi.setLocation(165,105); multi.setSize(50, 50); multi.addActionListener(this); add(multi); three=new JButton("3"); three.setLocation(0,165); three.setSize(50, 50); three.addActionListener(this); add(three); two=new JButton("2"); two.setLocation(55,165); two.setSize(50, 50); two.addActionListener(this); add(two); one=new JButton("1"); one.setLocation(110,165); one.setSize(50, 50); one.addActionListener(this); add(one); add=new JButton("+"); add.setLocation(165,165); add.setSize(50, 50); add.addActionListener(this); add(add); zero=new JButton("0"); zero.setLocation(0,220); zero.setSize(50, 50); zero.addActionListener(this); add(zero); deci=new JButton("."); deci.setLocation(55,220); deci.setSize(50, 50); deci.addActionListener(this); add(deci); equal=new JButton("="); equal.setLocation(110,220); equal.setSize(50, 50); equal.addActionListener(this); add(equal); subtract=new JButton("-"); subtract.setLocation(165,220); subtract.setSize(50, 50); subtract.addActionListener(this); add(subtract); } 

您的问题是您尝试在使用BorderLayout(JFrame的contentPane)的容器中设置组件的绝对位置和大小。 快速简便的解决方案是通过setLayout(null)使JFrame contentPane的布局为null

虽然这很快捷,而且很有效,但它也是错误的,因为它会迫使您创建在某个屏幕分辨率下在一个平台上看起来很好的严格GUI,在其他分辨率或其他平台上看起来很糟糕,几乎不可能根据需要修改。 更好的解决方案是使用布局管理器。 坚持这个例子……


编辑
例如,如果……

  • 您的主GUI使用BorderLayout
  • 您添加了显示数字的JTextField到主GUI BorderLayout.NORTH,也称为BorderLayout.PAGE_START
  • 为按钮创建一个JPanel,比如称为btnPanel,并将其添加到主GUI BorderLayout.CENTER。
  • 给btnPanel一个GridLayout大小以接受所有按钮。
  • 在创建它们时将JButtons添加到btnPanel。
  • 不是设置JButton的大小,而是为什么不设置更大的字体,让按钮和GUI大小本身以容纳更大的字体。

例如,以这种方式完成的代码如下所示:

在此处输入图像描述

 import java.awt.BorderLayout; import java.awt.Font; import java.awt.GridLayout; import javax.swing.*; public class GUIcalc2 extends JPanel { private static final String[][] BTN_TEXTS = { { "7", "8", "9", "/" }, { "6", "5", "4", "*" }, { "3", "2", "1", "+" }, { "0", ".", "=", "-" } }; private static final int GAP = 3; private static final float TF_SIZE = 18f; private static final float BTN_SIZE = 24f; private JButton[][] buttons = new JButton[BTN_TEXTS.length][BTN_TEXTS[0].length]; private JTextField textField = new JTextField(10); public GUIcalc2() { textField.setFont(textField.getFont().deriveFont(TF_SIZE)); JPanel btnPanel = new JPanel(new GridLayout(BTN_TEXTS.length, BTN_TEXTS[0].length, GAP, GAP)); for (int row = 0; row < BTN_TEXTS.length; row++) { for (int col = 0; col < BTN_TEXTS[0].length; col++) { JButton btn = new JButton(BTN_TEXTS[row][col]); // add ActionLIstener here btn.setFont(btn.getFont().deriveFont(Font.BOLD, BTN_SIZE)); btnPanel.add(btn); buttons[row][col] = btn; } } setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP)); setLayout(new BorderLayout(GAP, GAP)); add(textField, BorderLayout.PAGE_START); add(btnPanel, BorderLayout.CENTER); } private static void createAndShowGui() { GUIcalc2 mainPanel = new GUIcalc2(); JFrame frame = new JFrame("Calc"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.getContentPane().add(mainPanel); frame.pack(); frame.setLocationByPlatform(true); frame.setVisible(true); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGui(); } }); } } 

现在为了使用布局管理器的代码之美,假设你现在想要在顶部添加一行按钮来执行内存function,例如内存清除,内存替换,内存添加,......所有你需要做的事情(来自GUI视图立场)是添加另一行String常量:

 private static final String[][] BTN_TEXTS = { {"MC", "MR", "MS", "M+"}, // new line ! { "7", "8", "9", "/" }, { "6", "5", "4", "*" }, { "3", "2", "1", "+" }, { "0", ".", "=", "-" } }; 

这样做和GUI的机会:

在此处输入图像描述

并注意所有按钮resize以允许包含在顶行中的较大文本字符串,并且他们这样做而无需编写任何其他代码来执行此操作。

尝试使用与您的代码类似的操作,并注意您必须更改添加组件下方或右侧的所有组件的位置,以及错误和错误的风险。

当然你还需要添加逻辑代码,但这是另一个讨论的主题。