Создание собственных компонентов




Рассмотрим, как работает модель, на простом примере JComboBox. В материале об объекте класса JComboBox было показано, как добавлять элементы к данным, вызывая setItem(). Хотя это и приемлемо для простых демонстраций, в реальных приложениях так делают не часто. В конце концов, когда имеется 25 вариантов, и они постоянно меняются, неужели вы захотите проходить по ним в цикле, вызывая addItem() 25 раз? Конечно же, нет.

JComboBox имеет метод setModel(), который принимает экземпляр класса ComboBoxModel. Вы должны использовать этот метод вместо метода addItem() для создания данных в JComboBox.

Предположим, что имеется ArrayList с алфавитом в качестве данных («A», «B», «C» и так далее):

MyComboModel model = new MyComboModel(alphaList);

myComboBox.setModel(model);

public class MyComboModel implements ComboBoxModel {

private List data = new ArrayList();

private int selected = 0;

public MyComboModel(List list) {

data = list;

}

public void setSelectedItem(Object o) {

selected = data.indexOf(o);

}

public Object getSelectedItem() {

return data.get(selected);

}

public int getSize() {

return data.size();

}

public Object getElementAt(int i) {

return data.get(i);

}

}

Хорошей стороной использования модели является то, что вы можете повторно использовать ее снова и снова. Предположим, что данные в JComboBox должны быть изменены с букв алфавита на числа от 1 до 27. Вы можете выполнить это изменение одной простой строкой, которая использует новый List данных для заполнения JComboBox без использования дополнительного кода:

myComboBox.setModel(new MyComboModel(numberList));

Модели являются полезными возможностями Swing, поскольку они предоставляют возможность повторного использования кода и намного более легко работают с данными. Как это часто случается в крупномасштабных приложениях, разработчики серверной части создают и извлекают данные и передают их UI-разработчикам. Обязанностью UI-разработчика является работать с данными и отображать их правильно, а модели – инструменты, которые делают это.

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

Это простое по внешнему виду приложение, которое позволит вам увидеть в действии все элементы Swing. Данный пример должен ответить на любые вопросы, которые, возможно, остались у вас от предыдущих занятий. Перед началом работы посмотрим на законченный продукт:

Шаг 1: Размещение компонентов

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

Шаг 2: Инициализация данных

Приложение не может работать без данных. Давайте подумаем о том, какого рода данные нам нужны для данного приложения. Во-первых, нам необходим список городов для выбора города отправления и прибытия. Затем, нам необходим список рейсов для поиска.

Для этого примера используются фиктивные данные, потому что главное в приложении — это Swing, а не данные. Все данные создаются в классе DataHandler. Этот класс управляет городами отправления и прибытия, а также обрабатывает операции поиска рейсов и извлечения записей.

Города сохраняются в простых объектах String. Однако рейсы хранятся в объектах данных, называемых Flights, содержащих поля для города отправления, города прибытия, номера рейса и количества доступных билетов.

Шаг 3: Управление событиями

Исследуем приложение и рассмотрим действия, которые должны происходить. Во-первых, нужно знать, когда пользователь нажимает кнопку Search, для того чтобы можно было выполнить поиск рейсов. Во-вторых, вы должны знать, когда пользователь выбирает таблицу записей для предотвращения возможных ошибок при попытках пользователя купить билет на рейс тогда, когда не были выбраны записи в таблице. Наконец, необходимо знать, когда пользователь нажимает кнопку Purchase для передачи выбранных данных в класс обработчика данных.

Начнем с кнопки Search. Как говорилось выше, вы должны вызвать метод addActionListener() кнопки для регистрации на события, возникающие при ее нажатии. Для простоты был использован класс FlightReservation для прослушивания всех возможных событий. Вот код обработки нажатия кнопки Search:

String dest = getComboDest().getSelectedItem().toString();

String depart = getComboDepart().getSelectedItem().toString();

List l = DataHandler.searchRecords(depart, dest);

flightModel.updateData(l);

Два города выбираются из комбинированных списков и используются для поиска записей соответствующих рейсов. Как только рейсы найдены, записи передаются в табличную модель таблицы, более подробно о работе табличных моделей рассказано ниже. Но знайте, что как только табличная модель обновила данные, она отобразит результаты.

Затем исследуем, что происходит при нажатии пользователем кнопки Purchase:

Object o = flightModel.getData().get(getTblFlights().getSelectedRow());

int tixx = Integer.parseInt(getTxtNumTixx().getText());

DataHandler.updateRecords(o, tixx);

Теперь наоборот, когда пользователь нажимает кнопку Purchase, табличная модель вычисляет, какой рейс выбрал пользователь, и передает эту запись и количество билетов для покупки в обработчик данных.

Наконец, вы должны проверить ошибки и убедиться в том, что никто не пытается купить билет, не выбрав рейса в таблице. Самый простой способ сделать это — запретить компоненты, которые может использовать пользователь для покупки билетов (текстовое поле и кнопку) и разрешать их только после выбора пользователем строки:

boolean selected = getTblFlights().getSelectedRow() > -1;

getLblNumTixx().setEnabled(selected);

getTxtNumTixx().setEnabled(selected);

getBtnPurchase().setEnabled(selected);

Шаг 4: Модели

Далее рассмотрим модели, используемые вами для обработки всех данных, передаваемых в обе стороны в этом приложении. Анализируя приложения и изучив этот демонстрационный пример, вы должны четко увидеть, что вам нужны две модели: модель для JComboBoxes и модель для JTable.

Начнем с простейшей модели JComboBox. Хотя есть некоторые важные моменты, помните о преимуществах использования моделей. И хотя у вас имеется только один класс модели, вы повторно используете его, создавая два экземпляра класса и предоставляя их каждому из JComboBox. Таким образом, оба экземпляра могут обрабатывать свои собственные данные, хотя вы пишете только один класс для этого. Пример:

comboModel1 = new CityComboModel(DataHandler.getCities());

comboModel2 = new CityComboModel(DataHandler.getCities());

Перейдем к модели для JTable. Эта модель сложнее, чем для JComboBox, и требует более пристального рассмотрения. Начнем с ваших знаний ComboBoxModel и посмотрим, что нужно добавить для JTable. Поскольку JTable содержит те же данные, что и ComboBox, но в нескольких столбцах, вам нужна более полная информация из модели. То есть, кроме знания количества строк данных вы должны знать количество столбцов, названия столбцов и значение конкретной ячейки, а не только самого объекта. Это позволяет вам не только отобразить объект данных, но также отобразить поля объекта данных. В данном примере мы не отображаем объект Flight; вместо этого мы отображаем поля: город отправления, город прибытия, номер рейса и количество доступных билетов. Ниже приведен код, используемый для создания TableModel и для установки этой модели для JTable:

flightModel = new FlightTableModel();

getTblFlights().setModel(flightModel);

Шаг 5: Звонки и свистки

В любом приложении пользователи ожидают определенное количество звонков и свистков как дополнительную функциональность, а также как способ предотвратить возникновение ошибок. В данном примере, хотя основная функциональность по поиску рейса и покупке билетов работает, вы не рассматривали возможные ошибки, которые могут возникать. Для защиты от ошибок вы должны добавить сообщение об ошибке при попытках пользователя заказать больше билетов, чем доступно. Как отобразить ошибки? Если вы вспомните раздел о компоненте JOptionPane, Swing имеет готовый компонент для такого рода немедленной реакции.

Рассмотрим условие ошибки, а также то, что активизирует сообщение об ошибке:

try {

DataHandler.updateRecords(o, tixx);

} catch (Exception ex) {

// отобразить здесь сообщение об ошибке

}

Теперь необходимо реализовать уведомление об ошибке. Воспользуемся классом JOptionPane и его настройками. Выделим настройки, которые хотим иметь в сообщении об ошибке, перед тем, как решим, какой тип JOptionPane создавать. Это должно быть сообщение об ошибке, а не информационное сообщение. Используйте простой заголовок, например «Error». Детальное сообщение состоит из того, что выдала исключительная ситуация. И, наконец, ошибка возникла по вине пользователей, поэтому должно быть достаточно наличия кнопок OK и Cancel.

Вот код для создания такой JOptionPane:

JOptionPane.showConfirmDialog(this, ex.getMessage(), "Error",

JOptionPane.OK_CANCEL_OPTION, JOptionPane.ERROR_MESSAGE);

Обратите внимание на взаимосвязи событие / слушатель – как взаимодействующие компоненты принимают участие во взаимоотношении событие / слушатель, то есть на то, как заинтересованные стороны (особенно другие компоненты) должны регистрироваться на эти события.



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2017-06-11 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: