События ComboBoxModel не работают - PullRequest
3 голосов
/ 15 августа 2011

Кажется, я не понимаю концепцию событий и тому подобное. Прочитав некоторое время о том, как реализовать слушателей и тому подобное, я наткнулся на туториал по Java, в котором говорилось, что мне нужно расширить AbstractListModel, чтобы запустить событие данных. По какой-то причине это все еще не работает.

Что-то я делаю не так?

А какой код ожидается на 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()

Ответы [ 3 ]

6 голосов
/ 15 августа 2011

Я предполагаю, что вы используете официальный учебник .

Однако вы не должны касаться 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());
      }
   }
}

Обратите внимание: если у вас нет других ActionEvent, запущенных различными компонентами Swing, вы можете пропустить if (e.getSource() instanceof JComboBox), поскольку вы знаете, что ActionEvent всегда происходит из JComboBox.

В моем примере JComboBox находится внутри MyClass, но это не обязательно должно быть:

JComboBox comboBox = ...;
MyClass myClass = ...;
comboBox.addActionListener(myClass);
...
comboBox.addActionListener(someOtherActionListener);
4 голосов
/ 16 августа 2011

XXListener и XXModel - это разные стороны медали: первая является наблюдателем, вторая - наблюдаемой.Слушатель регистрируется в модели, когда хочет получить уведомление об изменениях.Модель несет ответственность за то, чтобы

  • управлял своими слушателями (как правило, это уже обрабатывается в AbstractXXModel, как уже объяснено в @userWhwhatNumber;)
  • запускает уведомления, если они подходят: эточасть, которую должна взять на себя пользовательская модель, в вашем случае

как

@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
} 
4 голосов
/ 15 августа 2011

Вам не нужно переопределять addListDataListener() и removeListDataListener() метод.AbstractListModel уже позаботится о слушателях.Вот реализация AbstractListModel.addListDataListener () :

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

Идея абстрактных классов состоит в том, что они выполняют большую часть работы за вас.Обычно вам нужно только реализовать абстрактные методы.

...