1

私は次の場所にあるこのコードに取り組んでいます

http://pastebin.com/7bCFtUHL

基本的には数独を解いた後にクリアするクリアメソッド(ボタン)を追加したいです。すべてのセルを通過してnullにするループを作成しようとしましたが、正確に接続する方法が完全にはわかりません。また、他のボタンがあるGUIに接続できるように、どのクラスで作成する必要があるのか​​ もわかりません。

編集:これは私が現在得た明確な方法です

public void clearCells(){
    for (int y = 0; y < 9; y++) {
        for (int x = 0; x < 9; x++) {
            cells[y][x] = null;
            cells[y][x].setText("");
        }
    }
}

これを別のクラスの JButton にアタッチする必要があります。

私のクリアボタンはこんな感じ

JButton clear = new JButton("Clear");

clear.addActionListener(new ActionListener() {

    public void actionPerformed(ActionEvent e)
    {
        //Code                    
    }        
    }
);

actionPerformed メソッドを clearCells メソッドに接続するには、どのコードを追加する必要がありますか?

4

1 に答える 1

3

繰り返しになりますが、モデル自体に clear メソッドの「肉」を入れます。ソリューションの一般的な形式は、これを行うことです。

clear.addActionListener(new ActionListener() {

  public void actionPerformed(ActionEvent e) {
       myModel.clearCells();
  }
});

Model クラスにはvoid clearCells()、セルを反復処理してクリアする public メソッドがあります。


編集 1
注: ええ、私はあなたのペーストビン コード リンクを見ました。1 つの大きな問題は、SwingSudokuBoard クラスが SudokuBoard クラスを拡張していることです。これは、代わりに構成を使用する必要がある継承の誤用です。SwingSudokuBoard クラスは、SudokuBoard オブジェクトのインスタンスを保持し、そのインスタンスに対してメソッドを呼び出す必要があります。


編集2
あなたは尋ねます:

私はあなたを完全に理解できるかどうか確信が持てません。ボタンを取得したのと同じクラスに clear メソッドを持たせたいのですが、セルを呼び出すことができません。x.clearCells(); を追加しました。xは何ですか?私のメインクラスは、SwingSudokuBoard.clearCells(); のようなものです。? いずれにせよ、あなたの言うことを追加すると、プログラムは clearCells メソッドとセルを静的にしたいという苦情を言います。しかし、それらを静的にすると、NullPointerException が発生します。

Model-View-Control (MVC) パターンまたはその短縮バージョンを使用する必要があると思います。おそらく、プログラムが小さいため、ビューとコントロールを組み合わせたものです。別のモデル クラスを用意することをお勧めします。これはおそらく SudokuBoard クラスで、次にビュー クラス、ここではおそらく SwingSudokuBoard クラスです。ビューのコントロール メソッド (ActionListeners) は、モデルのclearCells()メソッドを呼び出します。ここでは静的なものを使用しないでください。


編集3
あなたは尋ねます:

これらの行に沿って何かを推測します。モデル: SudokuBoard; 表示: SwingSudokuBoard; コントロール: SwingSudoKiller。それはどうなりますか?上記のコントロールに actionListener を投稿します。他のクラスはどのように見えますか?明確な方法は、数独ボードにしたいモデルにあると思いますが、そこのセルと接続できません。

私は専門家ではなく、正式なプログラミング トレーニングも受けていないため、理論は私の弱点の 1 つですが、MVC の私の解釈では、ビューはモデルをリッスンし、モデルが変更を通知するとそれ自体を更新し、コントロールはビューをリッスンし、モデルに通知することでビューの変更に応答します。この正確なパターンにはバリエーションがあり、文字どおりに正確に従う必要はありませんが、これらすべての重要な点は、コード内で個別の懸念事項を可能な限り分離して、「カップリング」(クラス) は低いか「緩い」、「結束力」 (同じ問題を扱うコード) は高いか「きつい」です。

あなたのプログラムでは、あなたが行っているのと同じように、匿名の内部リスナーを使用してビューとコントロールを結合します。SwingSudokuBoard クラスであるビュー/コントロールに、SudokuBoard クラスのインスタンスをクラス フィールドとして保持させ、ビュー/コントロールの匿名リスナーに SudokuBoard フィールドのメソッドを呼び出させるようにします。以前にこの種のことを行ったとき、モデルに SwingPropertyChangeSupport オブジェクトと publicメソッドaddPropertyChangeListener(...)およびremovePropertyChangeListener(...)メソッドを与えることで、モデルが監視されることをサポートしました。そうすれば、ビューはモデルの変更に簡単に対応できます。

あなたは次のように述べています:

明確な方法は、数独ボードにしたいモデルにあると思いますが、そこのセルと接続できません。

これが何を意味するのかわかりません。モデルはセルを保持します。おそらく、モデルが保持する論理セルではなく、ビューが保持する表示セルを意味しているのでしょう。ビューはモデルにリスナーを追加し、モデルへの変更が通知されると、モデルにそのデータを要求し、それを使用して視覚化されたセルを更新します。


編集 4
例:

import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.*;
import javax.swing.event.SwingPropertyChangeSupport;

public class OverlySimpleModelView {

   private static void createAndShowGui() {
      Model model = new Model();
      ViewControl viewControl = new ViewControl(model);

      JFrame frame = new JFrame("OverlySimpleModelView");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(viewControl.getMainComponent());
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

class ViewControl {
   private JPanel mainPanel = new JPanel();
   private JTextField number1Field = new JTextField(5);
   private JTextField number2Field = new JTextField(5);
   private JTextField productField = new JTextField(5);

   private Model model;

   public ViewControl(Model model) {
      this.model = model;
      model.addPropertyChangeListener(new MyPropChngListener());
      productField.setEditable(false);
      productField.setFocusable(false);

      mainPanel.add(number1Field);
      mainPanel.add(new JLabel(" * "));
      mainPanel.add(number2Field);
      mainPanel.add(new JLabel(" = "));
      mainPanel.add(productField);

      CalculateAction calculateAction = new CalculateAction("Calculate", KeyEvent.VK_C);
      mainPanel.add(new JButton(calculateAction));
      number1Field.addActionListener(calculateAction);
      number2Field.addActionListener(calculateAction);
      mainPanel.add(new JButton(new ClearAction("Clear", KeyEvent.VK_L)));
   }

   public JComponent getMainComponent() {
      return mainPanel;
   }

   private class MyPropChngListener implements PropertyChangeListener {
      @Override
      public void propertyChange(PropertyChangeEvent evt) {
         number1Field.setText(String.valueOf(model.getNumber1()));
         number2Field.setText(String.valueOf(model.getNumber2()));
         productField.setText(String.valueOf(model.calculateProduct()));
      }
   }

   private class CalculateAction extends AbstractAction {

      public CalculateAction(String text, int keyCode) {
         super(text);
         putValue(MNEMONIC_KEY, keyCode);
      }

      @Override
      public void actionPerformed(ActionEvent evt) {
         try {
            double number1 = Double.parseDouble(number1Field.getText());
            double number2 = Double.parseDouble(number2Field.getText());

            model.setNumber1(number1);
            model.setNumber2(number2);
         } catch (NumberFormatException e) {
            e.printStackTrace();
         }
      }
   }

   private class ClearAction extends AbstractAction {

      public ClearAction(String text, int keyCode) {
         super(text);
         putValue(MNEMONIC_KEY, keyCode); // to allow buttons a mnemonic letter
      }

      @Override
      public void actionPerformed(ActionEvent evt) {
         model.clear();
      }
   }
}

class Model {
   public static final String NUMBERS_CHANGED = "numbers changed";
   private double number1 = 0.0;
   private double number2 = 0.0;
   private SwingPropertyChangeSupport propChngSupport = 
         new SwingPropertyChangeSupport(this);



   public double getNumber1() {
      return number1;
   }

   public double getNumber2() {
      return number2;
   }

   public void clear() {
      setNumber1(0.0);
      setNumber2(0.0);
   }

   // make number1 field a "bound" property, one that notifies listeners if it is changed.
   public void setNumber1(double number1) {      
      Double oldValue = this.number1;
      Double newValue = number1;
      this.number1 = number1;
      propChngSupport.firePropertyChange(NUMBERS_CHANGED, oldValue , newValue);
   }

   // ditto for the number2 field
   public void setNumber2(double number2) {
      Double oldValue = this.number2;
      Double newValue = number2;
      this.number2 = number2;
      propChngSupport.firePropertyChange(NUMBERS_CHANGED, oldValue , newValue);
   }

   public double calculateProduct() {
      return number1 * number2;
   }

   public void addPropertyChangeListener(PropertyChangeListener listener) {
      propChngSupport.addPropertyChangeListener(listener);
   }

   public void removePropertyChangeListener(PropertyChangeListener listener) {
      propChngSupport.removePropertyChangeListener(listener);
   }
}

または、数値の配列を使用するため、より良いかもしれません:

import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.*;
import javax.swing.event.SwingPropertyChangeSupport;

public class OverlySimpleModelView {

   private static void createAndShowGui() {
      Model model = new Model(5);
      ViewControl viewControl = new ViewControl(model);

      JFrame frame = new JFrame("OverlySimpleModelView");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(viewControl.getMainComponent());
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

class ViewControl {
   private JPanel mainPanel = new JPanel();
   private JTextField[] numberFields;
   private JTextField productField = new JTextField(5);

   private Model model;

   public ViewControl(Model model) {
      this.model = model;
      model.addPropertyChangeListener(new MyPropChngListener());
      productField.setEditable(false);
      productField.setFocusable(false);

      CalculateAction calculateAction = new CalculateAction("Calculate", KeyEvent.VK_C);

      numberFields = new JTextField[model.getNumberFieldsLength()];
      for (int i = 0; i < numberFields.length; i++) {
         numberFields[i] = new JTextField("0.0", 5);
         mainPanel.add(numberFields[i]);
         numberFields[i].addActionListener(calculateAction);

         if (i < numberFields.length - 1) {
            mainPanel.add(new JLabel(" + "));
         } else {
            mainPanel.add(new JLabel(" = "));
         }
      }
      mainPanel.add(productField);

      mainPanel.add(new JButton(calculateAction));
      mainPanel.add(new JButton(new ClearAction("Clear", KeyEvent.VK_L)));
   }

   public JComponent getMainComponent() {
      return mainPanel;
   }

   private class MyPropChngListener implements PropertyChangeListener {
      @Override
      public void propertyChange(PropertyChangeEvent evt) {
         for (int i = 0; i < numberFields.length; i++) {
            numberFields[i].setText(String.valueOf(model.getNumber(i)));
         }
         productField.setText(String.valueOf(model.calculateSum()));
      }
   }

   private class CalculateAction extends AbstractAction {

      public CalculateAction(String text, int keyCode) {
         super(text);
         putValue(MNEMONIC_KEY, keyCode);
      }

      @Override
      public void actionPerformed(ActionEvent evt) {
         try {
            double[] numbers = new double[numberFields.length];
            for (int i = 0; i < numbers.length; i++) {
               numbers[i] = Double.parseDouble(numberFields[i].getText());
            }

            model.setNumbers(numbers);
         } catch (NumberFormatException e) {
            e.printStackTrace();
         }
      }
   }

   private class ClearAction extends AbstractAction {

      public ClearAction(String text, int keyCode) {
         super(text);
         putValue(MNEMONIC_KEY, keyCode); // to allow buttons a mnemonic letter
      }

      @Override
      public void actionPerformed(ActionEvent evt) {
         model.clear();
      }
   }
}

class Model {
   public static final String NUMBERS_CHANGED = "numbers changed";
   private double[] numbers;
   private SwingPropertyChangeSupport propChngSupport = 
         new SwingPropertyChangeSupport(this);

   public Model(int length) {
      numbers = new double[length];
   }

   public void setNumbers(double[] numbers) {
      double[] oldValue = this.numbers;
      double[] newValue = numbers;
      this.numbers = numbers;
      propChngSupport.firePropertyChange(NUMBERS_CHANGED, oldValue , newValue);

   }

   public double calculateSum() {
      double sum = 0.0;
      for (double number : numbers) {
         sum += number;
      }
      return sum;
   }

   public double getNumber(int i) {
      return numbers[i];
   }

   public int getNumberFieldsLength() {
      return numbers.length;
   }

   public void clear() {
      double[] newNumbers = new double[numbers.length];
      setNumbers(newNumbers);
   }

   public void addPropertyChangeListener(PropertyChangeListener listener) {
      propChngSupport.addPropertyChangeListener(listener);
   }

   public void removePropertyChangeListener(PropertyChangeListener listener) {
      propChngSupport.removePropertyChangeListener(listener);
   }
}
于 2013-03-02T15:36:34.273 に答える