2011-08-15 19 views
2

イベントなどの概念を把握していないようです。リスナーを実装する方法について少しずつ読んだ後、私はJavaチュートリアルで、データイベントの発生を取得するためにAbstractListModelを拡張するべきだと言っていました。なんらかの理由で、まだ動作しません。ComboBoxModelイベントが動作しない

私が間違っていることはありますか?

addListDataListener(ListDataListener l)にはどのようなコードが必要ですか?私はそれも理解していないので。

public class CarComboBox extends AbstractListModel<Object> implements ComboBoxModel<Object> { 

    private JdbcRowSet jdbc; 
    private int size = 0; 
    private String selection; 

    public CarComboBox() { 
     try { 
      jdbc = new Query().getCarInfo(); 

      jdbc.beforeFirst(); 
      while (jdbc.next()) { 
       size++; 
      } 
      jdbc.beforeFirst(); 
     } 
     catch (SQLException ex) { 
      System.err.println(ex.toString()); 
     } 
    } 

    @Override 
    public void setSelectedItem(Object anItem) { 
     selection = (String) anItem; 
    } 

    @Override 
    public Object getSelectedItem() { 
     return selection; 
    } 

    @Override 
    public void addListDataListener(ListDataListener l) { 
    } 

    @Override 
    public void removeListDataListener(ListDataListener l) { 
    } 

    @Override 
    public int getSize() { 
    return size; 
    } 

    @Override 
    public String getElementAt(int index) { 
     try { 
      jdbc.absolute(index + 1); 
      return jdbc.getString(2); 
     } 
     catch (SQLException ex) { 
      System.out.println(ex.toString()); 
     } 
     return null; 
    } 
} 

そして、私がやるCarComboBoxにリスナーを追加する:

CarComboBox ccb = new CarComboBox(); 
ccb.addListDataListener(new ListDataListener() 
+0

を変更した時はいつでもモデルあなたが使用しているGUIを指定する別のタグを追加する必要があり、そのリスナーに通知しなければなりません。これはスイングのようには見えません。 – toto2

+2

実際には、それはスイングです... – aymeric

+0

ダム - 別の空の 'addListDataListener' - ネット上のどこでも動作する' addListDataListener'を持つコードサンプルがないようです。 – Martin

答えて

6

公式tutorialを使用していると思います。

ただし、ListModelとComboBoxModelには触れないでください。これらは、おそらく必要のない高度な機能です。 チュートリアルの4つの例では、ListModelとComboBoxModelを使用していません。

標準のJComboBox(ListModelまたはComboBoxModelなし)を使用すると、誰かが選択すると、ActionEventが発生します。このイベントはSwingによって魔法のように発砲されます。どのように生成されるか心配する必要はありません。あなたが他のActionEventのは、別のスイングによってトリガーされていない場合という

public class MyClass implements ActionListener { 
    JComboBox comboBox = ...; 

    ... 
     // You must register explicitly every ActionListener that you 
     // want to receive ActionEvent's from comboBox. 
     // Here we register this instance of MyClass. 
     comboBox.addActionListener(this); 
    ... 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     if (e.getSource() instanceof JComboBox) { 
     System.out.println("MyClass registered an ActionEvent from a JComboBox."); 
     System.out.println("Selected: " + 
       ((JComboBox) e.getSource()).getSelectedItem()); 
     } 
    } 
} 

注:ただし、あなたの責任は、いくつか(0個、1個またはそれ以上)のオブジェクトが受信してのActionEventについて何かをすることができるということですものですコンポーネントが の場合、if (e.getSource() instanceof JComboBox)をスキップすることができます。なぜなら、あなたのActionEventは常にJComboBoxから来ると分かっているからです。

私の例ではJComboBoxがMyClassの内側にあるが、それは必要はありません:

JComboBox comboBox = ...; 
MyClass myClass = ...; 
comboBox.addActionListener(myClass); 
... 
comboBox.addActionListener(someOtherActionListener); 
4

あなたはaddListDataListener()removeListDataListener()メソッドをオーバーライドする必要はありません。 AbstractListModelはすでにリスナーを世話しています。ここAbstractListModel.addListDataListener()の実装です:

public void addListDataListener(ListDataListener l) { 
    listenerList.add(ListDataListener.class, l); 
} 

抽象クラスのアイデアは、彼らはあなたのための作業の大半を行うことです。通常、抽象メソッドを実装するだけです。

+0

ありがとうございます。そして、それはどこに 'addListDataListener'の例が見つからないのかを説明します。実際に自分で実装する必要はありません。 – Martin

3

XXListenerとXXModelコインの異なる側である:前者が観察され、後者に観察され。リスナーは、変更を通知されたいときにモデルに登録します。それは、カスタムモデルを取らなければならない部分です:;(すでに@userWhateverNumberで説明したようにそれは一般的に、AbstractXXModelによってすでに処理されます)

  • 通知火appropirate場合は
    • は、そのリスナーを管理

      にモデルの責任です以上、あなたのケースで

      @Override 
      public void setSelectedItem(Object item) { 
          selection = item; 
          fireContentChanged(this, -1, -1); 
      } 
      

      よう

    は間違いなく(あなたが頻繁にない:-)の周りの個人的な好みがありますカスタムモデルの実装が必要ですが、提供されているDefaultXXModelsを再利用することもできます。あなたの文脈ではと結果セットの内容は

    DefaultComboBoxModel model = new DefaultComboBoxModel(); 
    forEachRowInResultSet { 
        model.addElement(resultSet.getString(2)); 
    } 
    

    のような一方で、コンテンツの変更は、あなたのモデル、場合、構築時にデータをデフォルトモデルを埋めるためのオプションであるかもしれない不変であると仮定すると実装はとにかく無効です:何かが

    Object one = model.getElementAt(index); 
    Object other = model.getElementAt(index) 
    if (!one.equals(other)) { 
        listener must have received a contentsChanged 
    } 
    
  • +0

    これは非常に明確で分かりやすく、背景情報を与えてくれてありがとう。全体のことをすぐに文脈に入れるのは簡単です。 – Patrick

    関連する問題