开发者

ComboBoxModel events not working

开发者 https://www.devze.com 2023-03-27 23:28 出处:网络
I seem not to grasp the concept of Events and such. After reading a while on how to implement the listeners and such I came across the Java tutorial saying I should extend AbstractListModel to get the

I seem not to grasp the concept of Events and such. After reading a while on how to implement the listeners and such I came across the Java tutorial saying I should extend AbstractListModel to get the data event firing. For some reason it still does开发者_高级运维n't work.

Is there anything I'm doing wrong?

And what kind of code is expected at addListDataListener(ListDataListener l) for it to work? Since I don't understand that either.

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;
    }
}

And to add a listener to the CarComboBox I do:

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


I'm guessing that you are using the official tutorial.

However you should not touch ListModel and ComboBoxModel. Those are more advanced features you probably do not need. The 4 examples in the tutorial do NOT use ListModel and ComboBoxModel.

If you use a standard JComboBox (no ListModel or ComboBoxModel), what happens is that when someone makes a selection, an ActionEvent is fired. This event is magically fired by Swing; you don't have to worry about how it is generated. However what is your responsibility is to have some (zero, one or more) objects being able to receive and do something about the 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());
      }
   }
}

Note that if you don't have any other ActionEvent's fired by different Swing components you can skip the if (e.getSource() instanceof JComboBox) since you know your ActionEvent always comes from a JComboBox.

In my example the JComboBox is inside MyClass, but it does not have to be:

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


You don't need to override addListDataListener() and removeListDataListener() method. The AbstractListModel already take care of the listeners. Here is the implementation of AbstractListModel.addListDataListener():

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

The idea of abstract classes is that they do most of the work for you. Usually you only need to implement abstract methods.


XXListener and XXModel are different sides of the coin: the former is the observer to the latter which is the observable. The listener registers itself to the model when it wants to get notified on changes. It's the responsibility of the model to

  • manage its listeners (that's typically handled already by the AbstractXXModel, as already explained by @userWhateverNumber ;)
  • fire the notifications if appropirate: that's the part a custom model must take over, in your case

like

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

Arguably (there are personal preferences around :-) you often don't need custom model implementations but can just as well re-use the provided DefaultXXModels. In your context and assuming the content of the resultset is immutable it might be an option to fill the default model with the data at construction time, like

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

If, on the other hand, the content changes then your model implementation is invalid anyway: the model must notify its listeners whenever something had changed

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

精彩评论

暂无评论...
验证码 换一张
取 消