只有最后一个 JPanel ActionListeners 工作
Only last JPanel ActionListeners working
我正在为游戏创建一个菜单,并尝试创建 4 个 JPanel,每个 JPanel 都能够滚动浏览玩家可以使用的头像。
它适用于一个 JPanel 实例,但不能超过一个,并且只有最后一个 JPanel 可以运行。我认为这一定与 JPanels 中每个组件的创建有关,但我无法弄清楚。
我会 post 下面的 class。
@SuppressWarnings("serial")
public class Menu extends JPanel implements ActionListener {
JLabel playerAvatar;
JLabel playerTxt;
JButton playerPlus;
JButton playerMinus;
Font font_1 = new Font("calibri", Font.BOLD, 55);
Font font_2 = new Font("calibri", Font.BOLD, 30);
int playerAvatarCount = -1;
public Menu() {
init();
}
public void init() {
setOpaque(false);
setLayout(new FlowLayout());
setPreferredSize(new Dimension(1000, 800));
JPanel[] players = new JPanel[4];
players[0] = playerChoose(1);
players[1] = playerChoose(2);
players[2] = playerChoose(3);
players[3] = playerChoose(4);
for (int i = 0; i < 4; i++) {
add(players[i]);
}
}
private JPanel playerChoose(int i) {
JPanel plyrPanel = new JPanel();
plyrPanel.setPreferredSize((new Dimension(240, 200)));
plyrPanel.setOpaque(false);
playerAvatar = new JLabel("", SwingConstants.CENTER);
playerAvatar.setIcon(new ImageIcon("C:\Users\Travis\workspace\BoardGame\none.png"));
playerAvatar.setBackground(Color.WHITE);
playerAvatar.setOpaque(true);
playerAvatar.setBorder(BorderFactory.createLineBorder(Color.decode("#5B5C5C"), 3));
playerAvatar.setPreferredSize(new Dimension(105, 155));
playerPlus = new JButton(">");
playerPlus.setPreferredSize(new Dimension(60, 155));
playerPlus.setFont(font_1);
playerPlus.setForeground(Color.decode("#5B5C5C"));
playerPlus.setBorder(BorderFactory.createLineBorder(Color.decode("#5B5C5C"), 1));
playerPlus.setBackground(Color.decode("#B2DBA4"));
playerPlus.addActionListener(this);
playerMinus = new JButton("<");
playerMinus.setPreferredSize(new Dimension(60, 155));
playerMinus.setFont(font_1);
playerMinus.setForeground(Color.decode("#5B5C5C"));
playerMinus.setBorder(BorderFactory.createLineBorder(Color.decode("#5B5C5C"), 1));
playerMinus.setBackground(Color.decode("#B2DBA4"));
playerMinus.addActionListener(this);
playerTxt = new JLabel("Player " + i + "", SwingConstants.CENTER);
playerTxt.setFont(font_2);
playerTxt.setOpaque(false);
playerTxt.setForeground(Color.WHITE);
plyrPanel.add(playerMinus);
plyrPanel.add(playerAvatar);
plyrPanel.add(playerPlus);
plyrPanel.add(playerTxt);
validate();
return plyrPanel;
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == playerPlus) {
playerAvatar
.setIcon(new ImageIcon("C:\Users\Travis\workspace\BoardGame\frog" + ++playerAvatarCount + ".png"));
}
if (e.getSource() == playerMinus) {
playerAvatar
.setIcon(new ImageIcon("C:\Users\Travis\workspace\BoardGame\frog" + --playerAvatarCount + ".png"));
}
if (playerAvatarCount < 0) {
playerAvatar.setIcon(new ImageIcon("C:\Users\Travis\workspace\BoardGame\none.png"));
playerAvatarCount = -1;
} else if (playerAvatarCount > 3) {
playerAvatar.setIcon(new ImageIcon("C:\Users\Travis\workspace\BoardGame\frog3.png"));
playerAvatarCount = 3;
}
}
}
在您的方法中,您重新创建了按钮 playerPlus = new JButton(">");
但随后在 actionPerformed() 中,您通过与字段进行比较来检查来源
if (e.getSource() == playerPlus)
该字段仅包含最后创建的按钮,因此条件
if (e.getSource() == playerPlus)
if (e.getSource() == playerMinus)
总是错误的。
最简单的方法是为按钮定义名称并在检查中使用该名称
playerPlus = new JButton(">");
playerPlus .setName(">");
然后检查将是
if (e.getSource() instanceof JButton && ">".equals(((JButton)e.getSource()).getName()) ) {
//do your logic here
}
这是因为您将 JButtons
定义为 class 中的字段。当您调用 playerChoose(int)
时,您将 playerPlus and playerMinus
分配给新 JButton 的引用。每次调用 playerChoose 时都会发生这种情况。因此,当 ActionListener 将事件源 (e.getSource()
) 与存储在 playerPlus 或 playerMinus 中的引用进行比较时,只有最后定义的引用起作用,因为那是最后一次设置 playerPlus/playerMinus。
你真的需要面向对象。这 4 个菜单元素中的每一个都是 class 的一种类型,它们都应该有自己的 playerPlus 和 playerMinus 实例按钮。
public class MenuElement extends JPanel {
JLabel playerAvatar;
JLabel playerTxt;
JButton playerPlus;
JButton playerMinus;
public void initComponent() {
//lay out your elements here
}
public void addListeners() {
//setUpYour listeners here
}
}
如果您像这样编写 class,那么您的菜单元素将引用它自己的播放器加号和减号按钮实例。您遇到的问题是您有一个 playerPlus 和 playerMinus 实例,它们在四个不同的组件之间共享。
我正在为游戏创建一个菜单,并尝试创建 4 个 JPanel,每个 JPanel 都能够滚动浏览玩家可以使用的头像。
它适用于一个 JPanel 实例,但不能超过一个,并且只有最后一个 JPanel 可以运行。我认为这一定与 JPanels 中每个组件的创建有关,但我无法弄清楚。
我会 post 下面的 class。
@SuppressWarnings("serial")
public class Menu extends JPanel implements ActionListener {
JLabel playerAvatar;
JLabel playerTxt;
JButton playerPlus;
JButton playerMinus;
Font font_1 = new Font("calibri", Font.BOLD, 55);
Font font_2 = new Font("calibri", Font.BOLD, 30);
int playerAvatarCount = -1;
public Menu() {
init();
}
public void init() {
setOpaque(false);
setLayout(new FlowLayout());
setPreferredSize(new Dimension(1000, 800));
JPanel[] players = new JPanel[4];
players[0] = playerChoose(1);
players[1] = playerChoose(2);
players[2] = playerChoose(3);
players[3] = playerChoose(4);
for (int i = 0; i < 4; i++) {
add(players[i]);
}
}
private JPanel playerChoose(int i) {
JPanel plyrPanel = new JPanel();
plyrPanel.setPreferredSize((new Dimension(240, 200)));
plyrPanel.setOpaque(false);
playerAvatar = new JLabel("", SwingConstants.CENTER);
playerAvatar.setIcon(new ImageIcon("C:\Users\Travis\workspace\BoardGame\none.png"));
playerAvatar.setBackground(Color.WHITE);
playerAvatar.setOpaque(true);
playerAvatar.setBorder(BorderFactory.createLineBorder(Color.decode("#5B5C5C"), 3));
playerAvatar.setPreferredSize(new Dimension(105, 155));
playerPlus = new JButton(">");
playerPlus.setPreferredSize(new Dimension(60, 155));
playerPlus.setFont(font_1);
playerPlus.setForeground(Color.decode("#5B5C5C"));
playerPlus.setBorder(BorderFactory.createLineBorder(Color.decode("#5B5C5C"), 1));
playerPlus.setBackground(Color.decode("#B2DBA4"));
playerPlus.addActionListener(this);
playerMinus = new JButton("<");
playerMinus.setPreferredSize(new Dimension(60, 155));
playerMinus.setFont(font_1);
playerMinus.setForeground(Color.decode("#5B5C5C"));
playerMinus.setBorder(BorderFactory.createLineBorder(Color.decode("#5B5C5C"), 1));
playerMinus.setBackground(Color.decode("#B2DBA4"));
playerMinus.addActionListener(this);
playerTxt = new JLabel("Player " + i + "", SwingConstants.CENTER);
playerTxt.setFont(font_2);
playerTxt.setOpaque(false);
playerTxt.setForeground(Color.WHITE);
plyrPanel.add(playerMinus);
plyrPanel.add(playerAvatar);
plyrPanel.add(playerPlus);
plyrPanel.add(playerTxt);
validate();
return plyrPanel;
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == playerPlus) {
playerAvatar
.setIcon(new ImageIcon("C:\Users\Travis\workspace\BoardGame\frog" + ++playerAvatarCount + ".png"));
}
if (e.getSource() == playerMinus) {
playerAvatar
.setIcon(new ImageIcon("C:\Users\Travis\workspace\BoardGame\frog" + --playerAvatarCount + ".png"));
}
if (playerAvatarCount < 0) {
playerAvatar.setIcon(new ImageIcon("C:\Users\Travis\workspace\BoardGame\none.png"));
playerAvatarCount = -1;
} else if (playerAvatarCount > 3) {
playerAvatar.setIcon(new ImageIcon("C:\Users\Travis\workspace\BoardGame\frog3.png"));
playerAvatarCount = 3;
}
}
}
在您的方法中,您重新创建了按钮 playerPlus = new JButton(">");
但随后在 actionPerformed() 中,您通过与字段进行比较来检查来源
if (e.getSource() == playerPlus)
该字段仅包含最后创建的按钮,因此条件
if (e.getSource() == playerPlus)
if (e.getSource() == playerMinus)
总是错误的。
最简单的方法是为按钮定义名称并在检查中使用该名称
playerPlus = new JButton(">");
playerPlus .setName(">");
然后检查将是
if (e.getSource() instanceof JButton && ">".equals(((JButton)e.getSource()).getName()) ) {
//do your logic here
}
这是因为您将 JButtons
定义为 class 中的字段。当您调用 playerChoose(int)
时,您将 playerPlus and playerMinus
分配给新 JButton 的引用。每次调用 playerChoose 时都会发生这种情况。因此,当 ActionListener 将事件源 (e.getSource()
) 与存储在 playerPlus 或 playerMinus 中的引用进行比较时,只有最后定义的引用起作用,因为那是最后一次设置 playerPlus/playerMinus。
你真的需要面向对象。这 4 个菜单元素中的每一个都是 class 的一种类型,它们都应该有自己的 playerPlus 和 playerMinus 实例按钮。
public class MenuElement extends JPanel {
JLabel playerAvatar;
JLabel playerTxt;
JButton playerPlus;
JButton playerMinus;
public void initComponent() {
//lay out your elements here
}
public void addListeners() {
//setUpYour listeners here
}
}
如果您像这样编写 class,那么您的菜单元素将引用它自己的播放器加号和减号按钮实例。您遇到的问题是您有一个 playerPlus 和 playerMinus 实例,它们在四个不同的组件之间共享。