删除 JLabel 中的按钮
Remove buttons in JLabel
我有一个 java swing 项目,如下所示:
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.ImageIcon;
import javax.swing.Box;
import javax.swing.BoxLayout;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
public class DiceGameReplaceDice extends JFrame
{
private JFrame gameFrame;
private JPanel mainPanel;
private JPanel centerPanel = new JPanel();
private JButton diceArray[];
private DiceListener diceListener = new DiceListener();
private ButtonListener buttonListener = new ButtonListener();
private Random rand = new Random();
private int NUM_DICE = 2;
private String diceImages[] = {"./src/1.png", "./src/2.png", "./src/3.png",
"./src/4.png", "./src/5.png", "./src/6.png"};
public static void main(String[] args)
{
new DiceGameReplaceDice();
}
public DiceGameReplaceDice()
{
// Initialize the frame that holds the game
gameFrame = new JFrame();
gameFrame.setSize(800, 600);
gameFrame.setLocation(300, 100);
gameFrame.setTitle("Dice Game");
gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Add Panel
mainPanel = new JPanel();
mainPanel.setLayout(new BorderLayout());
// Instantiate a ButtonListener
buttonListener = new ButtonListener();
// Add 1 Button and 1 Label to a newly created panel
// Add new panel to West
JButton buttonW1 = new JButton("Add Die");
buttonW1.setName("W1");
buttonW1.addActionListener(buttonListener);
JPanel panelWest = new JPanel();
panelWest.setLayout(new BoxLayout(panelWest,BoxLayout.Y_AXIS ));
panelWest.setBackground(new Color(0, 0, 122)); // set to blue
panelWest.add(Box.createVerticalGlue());
panelWest.add(buttonW1);
panelWest.add(Box.createVerticalGlue());
mainPanel.add(panelWest, BorderLayout.WEST);
// Create and display center panel with dice
displayCenterPanel();
// Add mainPanel to frame and display the frame
gameFrame.add(mainPanel);
gameFrame.setVisible(true);
}
private void displayCenterPanel()
{
centerPanel = new JPanel();
centerPanel.setLayout(new BoxLayout(centerPanel,BoxLayout.X_AXIS ));
centerPanel.setBackground(new Color(0, 122, 0)); // set to green
centerPanel.add(Box.createHorizontalGlue());
diceArray = new JButton[NUM_DICE];
// Add 2 Buttons to center panel with images of 2 random dice
for (int i=0; i<NUM_DICE; i++)
{
// Create dice button
int dieNum = rand.nextInt(6)+1;
diceArray[i] = new JButton(new ImageIcon(diceImages[dieNum-1]));
diceArray[i].setName("Dice" + i);
diceArray[i].addActionListener(diceListener);
// Add to center panel
centerPanel.add(diceArray[i]);
centerPanel.add(Box.createHorizontalGlue());
}
mainPanel.add(centerPanel, BorderLayout.CENTER);
// Add mainPanel to frame and display the frame
gameFrame.add(mainPanel);
gameFrame.setVisible(true);
}
// Implement an (inner) class that implements ActionListener
class DiceListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
NUM_DICE -= 1;
displayCenterPanel();
}
}
// Implement an (inner) class that implements ActionListener
class ButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
String button = ((JButton)e.getSource()).getName();
System.out.println("Button Pressed: " + button);
if (button.equals("W1"))
NUM_DICE ++;
System.out.println(NUM_DICE);
displayCenterPanel();
}
}
}
单击 "Add Die" 按钮时,屏幕上会添加一个骰子并正确格式化。但是,当按下骰子并且 NUM_DICE 减少时,单击骰子按钮会导致奇怪的重叠和 "ghost buttons"。你如何解决这个问题?
快速解决方法是在添加新的之前删除 centerPanel
。添加行
mainPanel.remove(centerPanel);
作为您在 displayCenterPanel
中做的第一件事。
但是,您动态操纵布局的方式还有很多不足之处。不用每次都创建一个新的面板,只需修改现有的面板即可:
public class DiceGame {
private JPanel centerPanel = new JPanel();
private Random rand = new Random();
private int numDice = 2;
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new DiceGame());
}
public DiceGame() {
JFrame gameFrame = new JFrame();
gameFrame.setSize(800, 600);
gameFrame.setTitle("Dice Game");
gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BorderLayout());
JButton buttonW1 = new JButton("Add Die");
buttonW1.addActionListener(e -> {
numDice++;
updateCenterPanel();
});
JPanel panelWest = new JPanel();
panelWest.setLayout(new BoxLayout(panelWest, BoxLayout.Y_AXIS));
panelWest.setBackground(new Color(0, 0, 122));
panelWest.add(Box.createVerticalGlue());
panelWest.add(buttonW1);
panelWest.add(Box.createVerticalGlue());
centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.X_AXIS));
centerPanel.setBackground(new Color(0, 122, 0));
mainPanel.add(panelWest, BorderLayout.WEST);
mainPanel.add(centerPanel);
gameFrame.add(mainPanel);
gameFrame.setVisible(true);
}
private void updateCenterPanel() {
centerPanel.removeAll();
centerPanel.add(Box.createHorizontalGlue());
JButton[] diceArray = new JButton[numDice];
for (int i = 0; i < numDice; i++) {
diceArray[i] = new JButton(Integer.toString(rand.nextInt(6) + 1));
diceArray[i].setName("Dice" + i);
diceArray[i].addActionListener(e -> {
numDice--;
updateCenterPanel();
});
centerPanel.add(diceArray[i]);
centerPanel.add(Box.createHorizontalGlue());
}
centerPanel.revalidate();
centerPanel.repaint();
}
}
使组件层次结构失效后,需要重新验证和重新绘制。
备注:
- 当局部变量可以时,不要创建字段。
NUM_DICE
不是final
,所以应该命名为numDice
.
- 当它已经可见时调用
gameFrame.setVisible(true);
什么都不做。
- 当你有一个工作版本时,无论你在做什么,用
pack
替换 JFrame
上的 setSize(...)
并确保正确计算其子项的大小。
我有一个 java swing 项目,如下所示:
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.ImageIcon;
import javax.swing.Box;
import javax.swing.BoxLayout;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
public class DiceGameReplaceDice extends JFrame
{
private JFrame gameFrame;
private JPanel mainPanel;
private JPanel centerPanel = new JPanel();
private JButton diceArray[];
private DiceListener diceListener = new DiceListener();
private ButtonListener buttonListener = new ButtonListener();
private Random rand = new Random();
private int NUM_DICE = 2;
private String diceImages[] = {"./src/1.png", "./src/2.png", "./src/3.png",
"./src/4.png", "./src/5.png", "./src/6.png"};
public static void main(String[] args)
{
new DiceGameReplaceDice();
}
public DiceGameReplaceDice()
{
// Initialize the frame that holds the game
gameFrame = new JFrame();
gameFrame.setSize(800, 600);
gameFrame.setLocation(300, 100);
gameFrame.setTitle("Dice Game");
gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Add Panel
mainPanel = new JPanel();
mainPanel.setLayout(new BorderLayout());
// Instantiate a ButtonListener
buttonListener = new ButtonListener();
// Add 1 Button and 1 Label to a newly created panel
// Add new panel to West
JButton buttonW1 = new JButton("Add Die");
buttonW1.setName("W1");
buttonW1.addActionListener(buttonListener);
JPanel panelWest = new JPanel();
panelWest.setLayout(new BoxLayout(panelWest,BoxLayout.Y_AXIS ));
panelWest.setBackground(new Color(0, 0, 122)); // set to blue
panelWest.add(Box.createVerticalGlue());
panelWest.add(buttonW1);
panelWest.add(Box.createVerticalGlue());
mainPanel.add(panelWest, BorderLayout.WEST);
// Create and display center panel with dice
displayCenterPanel();
// Add mainPanel to frame and display the frame
gameFrame.add(mainPanel);
gameFrame.setVisible(true);
}
private void displayCenterPanel()
{
centerPanel = new JPanel();
centerPanel.setLayout(new BoxLayout(centerPanel,BoxLayout.X_AXIS ));
centerPanel.setBackground(new Color(0, 122, 0)); // set to green
centerPanel.add(Box.createHorizontalGlue());
diceArray = new JButton[NUM_DICE];
// Add 2 Buttons to center panel with images of 2 random dice
for (int i=0; i<NUM_DICE; i++)
{
// Create dice button
int dieNum = rand.nextInt(6)+1;
diceArray[i] = new JButton(new ImageIcon(diceImages[dieNum-1]));
diceArray[i].setName("Dice" + i);
diceArray[i].addActionListener(diceListener);
// Add to center panel
centerPanel.add(diceArray[i]);
centerPanel.add(Box.createHorizontalGlue());
}
mainPanel.add(centerPanel, BorderLayout.CENTER);
// Add mainPanel to frame and display the frame
gameFrame.add(mainPanel);
gameFrame.setVisible(true);
}
// Implement an (inner) class that implements ActionListener
class DiceListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
NUM_DICE -= 1;
displayCenterPanel();
}
}
// Implement an (inner) class that implements ActionListener
class ButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
String button = ((JButton)e.getSource()).getName();
System.out.println("Button Pressed: " + button);
if (button.equals("W1"))
NUM_DICE ++;
System.out.println(NUM_DICE);
displayCenterPanel();
}
}
}
单击 "Add Die" 按钮时,屏幕上会添加一个骰子并正确格式化。但是,当按下骰子并且 NUM_DICE 减少时,单击骰子按钮会导致奇怪的重叠和 "ghost buttons"。你如何解决这个问题?
快速解决方法是在添加新的之前删除 centerPanel
。添加行
mainPanel.remove(centerPanel);
作为您在 displayCenterPanel
中做的第一件事。
但是,您动态操纵布局的方式还有很多不足之处。不用每次都创建一个新的面板,只需修改现有的面板即可:
public class DiceGame {
private JPanel centerPanel = new JPanel();
private Random rand = new Random();
private int numDice = 2;
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new DiceGame());
}
public DiceGame() {
JFrame gameFrame = new JFrame();
gameFrame.setSize(800, 600);
gameFrame.setTitle("Dice Game");
gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BorderLayout());
JButton buttonW1 = new JButton("Add Die");
buttonW1.addActionListener(e -> {
numDice++;
updateCenterPanel();
});
JPanel panelWest = new JPanel();
panelWest.setLayout(new BoxLayout(panelWest, BoxLayout.Y_AXIS));
panelWest.setBackground(new Color(0, 0, 122));
panelWest.add(Box.createVerticalGlue());
panelWest.add(buttonW1);
panelWest.add(Box.createVerticalGlue());
centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.X_AXIS));
centerPanel.setBackground(new Color(0, 122, 0));
mainPanel.add(panelWest, BorderLayout.WEST);
mainPanel.add(centerPanel);
gameFrame.add(mainPanel);
gameFrame.setVisible(true);
}
private void updateCenterPanel() {
centerPanel.removeAll();
centerPanel.add(Box.createHorizontalGlue());
JButton[] diceArray = new JButton[numDice];
for (int i = 0; i < numDice; i++) {
diceArray[i] = new JButton(Integer.toString(rand.nextInt(6) + 1));
diceArray[i].setName("Dice" + i);
diceArray[i].addActionListener(e -> {
numDice--;
updateCenterPanel();
});
centerPanel.add(diceArray[i]);
centerPanel.add(Box.createHorizontalGlue());
}
centerPanel.revalidate();
centerPanel.repaint();
}
}
使组件层次结构失效后,需要重新验证和重新绘制。
备注:
- 当局部变量可以时,不要创建字段。
NUM_DICE
不是final
,所以应该命名为numDice
.- 当它已经可见时调用
gameFrame.setVisible(true);
什么都不做。 - 当你有一个工作版本时,无论你在做什么,用
pack
替换JFrame
上的setSize(...)
并确保正确计算其子项的大小。