2014-02-15 61 views
0

我有一个带回家的任务,我需要制作一个数独板来显示板上文件的整数,并允许某人单击一个JButton并输入一个缺失值。Java Swing(问题与ActionListener)

我已经得到了使用JPanel显示板并将文本文件打印到各个按钮,但我无法弄清楚如何让addActionListener拿起任何缺少值的按钮。它只适用于空白的最后一个按钮。 (空白按钮的值为0)。

我的问题是为什么只有最后一个空白按钮被定位。共有6个,但只有最后一个点击后弹出对话框?

public class MyCustomeFrame extends JFrame { 
    private int[][] numbers; 
    private String[] nums; 
    JButton b1; 
    JButton b2; 
    JButton b3; 
    JButton b4; 

    private JPanel p2; 

    public MyCustomeFrame() { 
     // Create the border layout 
     setLayout(new BorderLayout(5, 5)); 

     // Create a new panel for the buttons to be placed on 
     JPanel p1 = new JPanel(); 

     // Create 3 buttons 

     b1 = new JButton("Load"); 
     b2 = new JButton("Save"); 
     b3 = new JButton("Check"); 

     // Adds the 3 buttons to the panel 
     p1.add(b1); 
     p1.add(b2); 
     p1.add(b3); 

     // Create the event handlers for when the button is pressed 
     b1.addActionListener(new MyButtonHandler()); 
     b2.addActionListener(new MyButtonHandler()); 
     b3.addActionListener(new MyButtonHandler()); 


     // Place the panel south in the window 
     add(p1, BorderLayout.SOUTH); 

     p2 = new JPanel(); 

     // Define the grid parameters 
     p2.setLayout(new GridLayout(9, 9, 5, 5)); 

     // Show the grid 
     add(p2, BorderLayout.CENTER); 
     int[][] numbers = new int[9][9]; 
     int rowIdx = 0; 



     //This is where i read the input file located on my computer and place the numbers on the Sudoku board 
     try { 
      BufferedReader bReader = new BufferedReader(new FileReader(
       "C:\\Users\\Derek\\Desktop\\input.txt")); 

      String line = bReader.readLine(); 

      while (line != null) { 
       nums = line.split(","); 

       for (int i = 0; i < numbers[0].length; i++) { 
        numbers[rowIdx][i] = Integer.parseInt(nums[i]); 

        // This creates the individual buttons that are then placed on the board 
        if (numbers[rowIdx][i] >= 1) { 
         p2.add(new JButton(nums[i])); 
        } else { 

         //this is where I'm having the issue 
         b4 = new JButton(" "); 
         p2.add(b4); 
         b4.addActionListener(new MyButtonHandler()); 
        } 
       } 

       rowIdx++; 
       line = bReader.readLine(); 
      } 
      bReader.close(); 
     } catch (FileNotFoundException g) { 
      System.out.println("File Not Found!"); 
     } catch (IOException g) { 
      System.out.println("Something went wrong...Try Again"); 
      g.printStackTrace(); 
     } 
    } 

    class MyButtonHandler implements ActionListener { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
      if (e.getSource() == b1) { 
       System.out.println("Loading File..."); 

      } else if (e.getSource() == b2) { 
       System.out.println("Saving File..."); 

       try { 
        BufferedWriter bWriter = new BufferedWriter(new FileWriter(
         new File("C:\\SudokuSave.txt"), true)); 

        bWriter.close(); 

       } catch (IOException e1) { 
        // TODO Auto-generated catch block 
        e1.printStackTrace(); 
       } 
      } else if (e.getSource() == b3) { 
       System.out.println("Checking Solution..."); 

      } else if (e.getSource() == b4) { 
       System.out.println("clicked"); 
       JOptionPane.showInputDialog("Input a number between 1 - 9"); 
      } 
     } 
    } 
} 

回答

2

的原因问题https://stackoverflow.com/a/21803753

一些提示已经指出的维亚切斯拉夫:

你应该使用正确的变量名。调用JButton b2是可怕的。当它是一个“加载”按钮时,则称它为loadButton。当它是“保存”按钮时,将其称为saveButton。代码被写入(最多)一次,但可能读取数百次。在最好的情况下,Java代码应该像散文一样阅读。

在构造函数中读取具有硬编码名称的文件以构建GUI组件是非常糟糕的做法。你应该考虑创建一个包含您可以从创建GUI的信息,一些“数据模型”,并拆分的

  1. 过程中读取文件和数据存储在数据模型,
  2. 创建来自数据模型的GUI。

这也将让你通过打印

System.out.println("Something went wrong...Try Again"); 

为了解决你的问题,你可以考虑使用匿名听众来处理异常不是更好。创建一个单一的ActionListener,这是负责所有按钮不是很灵活。通常,您只想将一个按钮上的单击与一个(私有)方法调用相关联。因此,例如,你可以写

JButton saveButton = new JButton("Save"); 
saveButton.addActionListener(new ActionListener() { 
{ 
    @Override 
    public void actionPerformed(ActionEvent) { 
     saveButtonWasPressed(); 
    } 
}); 
特别是对于你有 几个按钮机智类似的功能的情况下

,这种方法提供了一个优势:你可以为每个按钮创建匿名的听众,他们每个人的包含所需约点击了哪个按钮信息 - 大致适用于您的代码:

if (numbers[rowIdx][i] == 0) { 
    JButton b = new JButton(" "); 
    panel.add(b); 
    b.addActionListener(createActionListener(rowIdx, i)); 
} 

... 

private ActionListener createActionListener(
    final int row, final int column) { 
    ActionListener actionListener = new ActionListener() { 
    { 
     @Override 
     public void actionPerformed(ActionEvent) { 
      System.out.println("Pressed button in row "+row+", column "+column); 
     } 
    }; 
    return actionListener; 
} 
+1

还要考虑['Action'](http://docs.oracle.com/javase/tutorial/uiswing/misc/action.html )“来分离组件的功能和状态。“ – trashgod

+0

@trashgod当然!对于数独板的按钮网格来说,这可能不是太好,但对于标准动作(加载,保存..)动作绝对是要走的路,特别是当相同的功能应该是在Button和MenuItem中使用,或者当像I18N这样的东西进入时... – Marco13

+0

['JDigit'](http://stackoverflow.com/a/4151403/230513)是一个使用'AbstractAction'的例子。 – trashgod

1

你的错误很简单 - 的for每次迭代你分配一个新的JButton对象引用变量b4所以最后b4是指最后你创造了JButton