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

는 또한 ['의회 처리] 고려 (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의 모든 반복이 그렇게 마지막으로 b4 당신이 창조하신 JButton 마지막을 의미한다 b4 변수에 새로운 JButton 객체 참조를 할당한다.