2014-02-15 60 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