动作侦听器不能处理某些按钮

时间:2013-07-11 22:51:21

标签: java swing

我在“重新启动”地图后让actionlistener在某些按钮上工作时遇到问题。事情是btns [1]到btns [9]根本不起作用!我的变量可能有些问题,我不确定。我尝试了一切。启动新地图后,这些按钮根本无法工作(按下按钮btns [0] ..新地图后)。这是我的代码,希望你帮助我们。新板(null) - 如果构造函数中有null,它应该创建一个毯子映射,我已经在Board类的构造函数中编码了(我想这并不重要,因为它是第一次启动新游戏时工作(null))。

如果你发现无法找到它无法正常工作的原因,我将整个游戏上传到sentpace = http://www.sendspace.com/file/pvwtoo - Jar形式,http://www.sendspace.com/file/l18khb - BlueJ表格 - 以便在必要时进行更好的协调。非常感谢您提供的所有帮助。 路加

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);
}

}

3 个答案:

答案 0 :(得分:5)

按钮的“动作命令”不一定是按钮的文本。尝试用

替换文本的测试

if (e.getSource() == button[1])

或类似的进行可靠的测试。如果它完全有效,那么更有可能是幸运 - 规范中没有任何内容表明按钮文本将是动作命令,事实上如果你使用javax.swing.Action,它通常不会。

此代码还存在许多其他问题,使其更难以阅读和预测它的作用:

  • 如果测试字符串常量,请始终使用"THE CONSTANT".equals(something)形式,因为您可以保证常量不为空;另一种方法是空指针异常。
    • 在这种情况下,如果您保留测试代码,则可以使用switch-over-strings
  • 您对pnl执行空检查,然后尝试分配它。实际上它不会为空。将初始化代码移动到构造函数,删除createGui,并使Pnl字段最终。然后代码更简单,并且你要求编译器证明 pnl不能为null,从可能性的范围中消除整个类别的bug。
  • 重建GUI时,如果在运行时删除并添加组件,则需要invalidate(); revalidate(); repaint();咒语以确保显示更新 - 此处的代码是否有效将因JDK和外观而异。实际上,您根本不需要重建GUI。

答案 1 :(得分:5)

我认为,当重置程序状态而不是将当前显示的GUI更改为其初始状态时,最好不要以几乎递归的方式创建新的GUI。这可能是你的问题所在。

换句话说,我会改变这个:

  if (action.equals("New Map")) {
     createGui(null);
     b.revalidate();
     b.repaint();
     c.repaint();
  }

到此:

  if (action.equals("New Map")) {
     b.reset();
  }

当然会给Board类一个reset()方法,它会重置它的状态和显示。

要获得更多帮助,请发布sscce,而不是指向大型复杂GUI的链接。


编辑,我的SSCCE

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;
   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);
      c.add(b);

      pnl = new JPanel();
      pnl.setLayout(new GridLayout(16, 10));
      pnl.setSize(100, 608);
      pnl.setBackground(Color.BLACK);
      c.add(pnl, BorderLayout.LINE_END);

      setTitle("Strgame");
      c.setBackground(Color.BLACK);
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      setSize(800, 608);
      setLocationRelativeTo(null);

      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");
      System.out.println("btns[1] hash: " + btns[1].hashCode());
      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.setBackground(Color.lightGray);
      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) {
      Object source = e.getSource();
      System.out.println("source hash: " + source.hashCode());

      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);
   }

}

class Board extends JPanel {

   private Map map;
   private JLabel xyLabel = new JLabel("    ");

   public Board(Map map) {
      this.map = map;
      add(xyLabel);

   }

   public String getSelectedCost() {
      return "getSelectedCose";
   }

   public String getSelected() {
      return "getSelected";
   }

   public void selMore() {

   }

   public void changexy(String xy) {
      xyLabel.setText(xy);
   }

   public int[] lastPosSelected() {

      return new int[] { 1, 2, 3, 4 };
   }

}

class Map {

}

如果你运行这个,你会从打印的哈希码中看到你的gui正在从创建的第一组按钮获得响应,而不是第二组,这就是你的GUI不起作用的原因。

例如,我的输出看起来像这样:

btns[1] hash: 17514905
source hash: 17514905
source hash: 17514905
source hash: 12934710
btns[1] hash: 23063136
source hash: 17514905

同样,如果您遵循我的初步建议,这一切都可以解决: 重置 您的主板,不要替换它,当然也不要替换所有菜单纽扣。

此外,您需要在设置后pack()设置GUI,而不是设置任何尺寸。

答案 2 :(得分:2)

顺便点击它的方式很好的程序。你在这个程序中有一些奇怪的事情,我认为你可以改进,它可以解决这个问题,并使你的应用程序运行得更好。

  1. 将所有内容添加到UI后,最好不要删除所有内容并重新添加,但有一些例外,但如果可能的话,请回避它。资源效率低下,你可能会遇到奇怪的问题,例如由于多个对象实例在GUI线程中挥之不去而面临的问题。

  2. 正如气垫船先前所述,你应该在你的棋盘类中创建一个名为clearBoard或clearMap的方法来擦除地图,然后在你想要一张新地图时调用它。

  3. 我在你的代码中实现了这一点,并使一切正常,但我注意到哪些类包含什么的奇怪的差异。当我将clearBoard方法添加到Board类并将clearMap添加到地图Map类时,我最初只是重新初始化了map [] []变量。但奇怪的事发生了!图标永远不会从电路板上消失,但点击“获取所选信息”按钮返回它是一个草节点,而不是。这里有2个数组,一个包含Board类中的图像,另一个包含Map类中的图像。您应该将图像移出板类并进入地图类。我的建议是,从Board中删除数组Image [] []图像,只留下一个包含地图数据的2d数组,然后在绘制地图时获取图像。

  4. 如果你想看看我改变了什么,我可以上传你改变的来源。

    - 最佳