3

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

如果您发现无法找出它为什么不起作用,我将我的整个游戏上传到 sendspace = 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);
}

}
4

3 回答 3

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

同样,如果您遵循我最初的建议,这一切都可以解决:重置您的 Board,不要更换它,当然也不要更换所有的菜单按钮。

此外,您将需要pack()在设置之后使用您的 GUI,而不是设置任何东西的大小。

于 2013-07-11T23:10:32.510 回答
5

按钮的“动作命令”不一定是按钮的文本。尝试将文本的测试替换为

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

或类似的有可靠的测试。如果这确实有效,那更有可能是运气——规范中没有任何内容表明按钮文本将成为操作命令,事实上,如果您使用 a javax.swing.Action,通常不会。

这段代码还有许多其他问题,使得阅读和预测它的作用变得更加困难:

  • 如果测试字符串常量,请始终使用该形式,"THE CONSTANT".equals(something)因为您可以保证该常量不为空;另一种方法是空指针异常。
    • 在这种情况下,如果您保留测试代码,则可以使用 switch-over-strings
  • 您对 pnl 进行空检查,然后尝试分配它。实际上它不会为空。将初始化代码移至构造函数,去掉createGui,并使 Pnl 字段成为最终字段。然后代码更简单,您让编译器证明pnl 不能为空,从而从可能性领域消除了整个错误类别。
  • 重构 GUI 时,如果您在运行时删除和添加组件,则需要使用invalidate(); revalidate(); repaint();咒语来确保更新显示 - 这里的代码是否有效将因 JDK 和外观而异。实际上,您根本不需要重建 GUI。
于 2013-07-11T23:09:00.773 回答
2

不错的程序,顺便说一句有趣的点击它。你在这个程序中发生了一些奇怪的事情,我认为你可以改进它,它会解决这个问题,并使你的应用程序运行得更好。

  1. 将所有内容添加到 UI 后,将所有内容删除并重新添加并不是最佳做法,有一些例外情况,但如果可能的话,请避开它​​。它是资源效率低下的,并且由于在 GUI 线程中徘徊的多个对象实例,您最终可能会遇到奇怪的问题,例如您所面临的问题。

  2. 正如前面所说的气垫船,您应该在您的板类中创建一个名为 clearBoard 或 clearMap 的方法,该方法将擦除地图,然后在您需要新地图时调用它。

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

如果您想查看我更改的内容,我可以上传您更改的源。

-最好的

于 2013-07-11T23:38:57.113 回答