Action listener is not working on certain buttons
java, swing
Solution
The "action command" of a button is not necessarily the text of the button. Try replacing the test for the text with
`if (e.getSource() == button[1])`
or similar to have a reliable test. If that worked at all, it was more likely luck - there's nothing in the spec to suggest that the button text will be the action command, and in fact if you use a `javax.swing.Action`, it usually will not be.
There are a number of other problems with this code that make it more difficult to read and predict what it does:
- If testing a string constant, always use the form `"THE CONSTANT".equals(something)` since you can guarantee that the constant is not null; the other way around is a null pointer exception.
- In this case, if you were keeping the test code, you could use switch-over-strings
- You do a null check on pnl, and then later try to assign it. In fact it will not be null. Move the initialization code to the constructor, getting rid of `createGui`, and make the Pnl field final. Then the code is simpler and you enlist the compiler to prove pnl cannot be null, eliminating that entire category of bug from the realm of possibility.
- When reconstructing the GUI, if you remove and add components at runtime, you need the `invalidate(); revalidate(); repaint();` incantation to make sure the display is updated - whether the code here works or not will vary by JDK and look and feel. And actually, you don't need to reconstruct the GUI at all.
Problem
I have problem making actionlistener work on certain buttons after I "restart" my map. The thing is btns[1] to btns[9] do not work at all ! It might be some problem with my variables, I am not sure. I tried everything. These buttons are simply not working after I start new Map (After I press button btns[0] .. New Map ). Here is my code, hope you help me guys. New Board(null) - if there's null in constructor, it is supposed to create blanket map, which I have coded in constructor of Board class(I guess it doesn't really matter, because it is working first time I launch the new Game(null) ). If you find it impossible to find out why it is not working, I uploaded my whole game to sendspace = http://www.sendspace.com/file/pvwtoo - Jar form, http://www.sendspace.com/file/l18khb - BlueJ form - for better coordination if necessary. Thanks a lot in advance for all your help. Luke ``` import javax.swing.*; import java.awt.event.*; import java.awt.*; public class Game extends JFrame implements ActionListener { Board b; Menu m; Container c = getContentPane(); JPanel pnl; ImageIcon ii; JLabel jl; JTextArea jt; private JButton [] btns = new JButton[10]; String selectMore = "Select more = false"; int posx,posy; public Game(Map m) { createGui(m); } public void createGui(Map mm) { b = new Board(mm); //m = new Menu(); c.add(b); pnl = new JPanel(); ii = new ImageIcon(this.getClass().getResource("menu.png")); pnl.setLayout(new GridLayout(16,10)); pnl.setSize(100,608); //pnl.add(m); pnl.setBackground(Color.BLACK); c.add(pnl,BorderLayout.LINE_END); setTitle("Strgame"); c.setBackground(Color.BLACK); //this.pack(); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(800, 608); setLocationRelativeTo(null); setResizable(false); //setUndecorated(true); //setExtendedState(Frame.MAXIMIZED_BOTH); setVisible(true); manageButtons(); infoPanel(); pnl.requestFocusInWindow(); requestFocusInWindow(); } public void manageButtons() { if(pnl!=null){pnl.removeAll();} btns[0] = new JButton("New Map"); btns[1] = new JButton("Change XY to House 1"); btns[2] = new JButton("Change XY to House 2"); btns[3] = new JButton("Change XY to Road 1"); btns[4] = new JButton("Change XY to Road 2"); btns[5] = new JButton("Change XY to Road 3"); btns[6] = new JButton("Change XY to Grass"); btns[7] = new JButton("Get info of selected"); btns[9] = new JButton(selectMore); for(int i = 0; i < 10; i++) { if(btns[i] != null) { btns[i].addActionListener(this); btns[i].setPreferredSize(new Dimension(213,10)); btns[i].setBorder(BorderFactory.createLineBorder(Color.BLACK, 1)); btns[i].setBackground(Color.lightGray); pnl.add(btns[i]); } } } public void infoPanel() { jl = new JLabel("Info"); jl.setForeground(Color.lightGray); jl.setHorizontalAlignment(SwingConstants.CENTER); pnl.add(jl); jt = new JTextArea(); //jt.setPreferredSize(new Dimension(211,10)); //jt.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1)); jt.setBackground(Color.lightGray); //jt.setHorizontalAlignment(SwingConstants.CENTER); jt.setMargin(new Insets(2,2,2,2)); jt.setEditable(false); jt.setText(" Not selected"); pnl.add(jt); } public int posx() { int [] pom = b.lastPosSelected(); posx = pom[0]; return posx; } public int posy() { int [] pom = b.lastPosSelected(); posy = pom[1]; return posy; } public void actionPerformed(ActionEvent e) { String action = e.getActionCommand(); if(action.equals("New Map")) { createGui(null); b.revalidate(); b.repaint(); c.repaint(); } else if(action.equals("Change XY to House 1")) { b.changexy("house"); b.revalidate(); b.repaint(); c.repaint(); } else if(action.equals("Change XY to House 2")) { b.changexy("house1"); b.revalidate(); b.repaint(); c.repaint(); } else if(action.equals("Change XY to Road 1")) { b.changexy("road"); b.revalidate(); b.repaint(); c.repaint(); } else if(action.equals("Change XY to Road 2")) { b.changexy("road1"); b.revalidate(); b.repaint(); c.repaint(); } else if(action.equals("Change XY to Road 3")) { b.changexy("road2"); b.revalidate(); b.repaint(); c.repaint(); } else if(action.equals("Change XY to Grass")) { b.changexy("grass"); b.revalidate(); b.repaint(); c.repaint(); } else if(action.equals("Select more = false")) { b.selMore(); b.repaint(); selectMore = "Select more = true"; btns[9].setText(selectMore); } else if(action.equals("Select more = true")) { b.selMore(); b.repaint(); selectMore = "Select more = false"; btns[9].setText(selectMore); } else if(action.equals("Get info of selected")) { jt.setText(" Name: "+b.getSelected()+"\n Costs: "+b.getSelectedCost()); } } public static void main(String[] args) { new Game(null); } } ```