我在“重新启动”地图后让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);
}
}
答案 0 :(得分:5)
按钮的“动作命令”不一定是按钮的文本。尝试用
替换文本的测试 if (e.getSource() == button[1])
或类似的进行可靠的测试。如果它完全有效,那么更有可能是幸运 - 规范中没有任何内容表明按钮文本将是动作命令,事实上如果你使用javax.swing.Action
,它通常不会。
此代码还存在许多其他问题,使其更难以阅读和预测它的作用:
"THE CONSTANT".equals(something)
形式,因为您可以保证常量不为空;另一种方法是空指针异常。
createGui
,并使Pnl字段最终。然后代码更简单,并且你要求编译器证明 pnl不能为null,从可能性的范围中消除整个类别的bug。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)
顺便点击它的方式很好的程序。你在这个程序中有一些奇怪的事情,我认为你可以改进,它可以解决这个问题,并使你的应用程序运行得更好。
将所有内容添加到UI后,最好不要删除所有内容并重新添加,但有一些例外,但如果可能的话,请回避它。资源效率低下,你可能会遇到奇怪的问题,例如由于多个对象实例在GUI线程中挥之不去而面临的问题。
正如气垫船先前所述,你应该在你的棋盘类中创建一个名为clearBoard或clearMap的方法来擦除地图,然后在你想要一张新地图时调用它。
我在你的代码中实现了这一点,并使一切正常,但我注意到哪些类包含什么的奇怪的差异。当我将clearBoard方法添加到Board类并将clearMap添加到地图Map类时,我最初只是重新初始化了map [] []变量。但奇怪的事发生了!图标永远不会从电路板上消失,但点击“获取所选信息”按钮返回它是一个草节点,而不是。这里有2个数组,一个包含Board类中的图像,另一个包含Map类中的图像。您应该将图像移出板类并进入地图类。我的建议是,从Board中删除数组Image [] []图像,只留下一个包含地图数据的2d数组,然后在绘制地图时获取图像。
如果你想看看我改变了什么,我可以上传你改变的来源。
- 最佳