Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Программирование на Java часть 2

.pdf
Скачиваний:
134
Добавлен:
16.03.2016
Размер:
3.07 Mб
Скачать

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

Вы не должны работать с JScrollPane напрямую, создавая вне компонента, который будет ее использовать. Что касается приведенного выше примера, вызывая конструктор JScrollPane с JTextArea, вы создаете возможность для JTextArea прокручиваться тогда, когда текст становится слишком длинным:

JScrollPane scroll = new JScrollPane(getTextArea()); add(scroll);

Этот обновленный пример выглядит следующим образом:

Пример JScrollPane

Компонент JScrollPane предоставляет также два компонента JScrollBar, которые он создаст. Эти компоненты JScrollBar содержат методы, которые вы можете использовать для изменения их поведения (их рассмотрение выходят за рамки данного руководства).

Методами, которые вы должны использовать с JScrollPane, являются:

getHorizontalScrollBar():

Возвращает

горизонтальный

компонент JScrollBar.

 

 

getVerticalScrollBar(): Возвращает вертикальный компонент

JScrollBar.

get/setHorizontalScrollBarPolicy(): Эта "политика" может принимать одно из следующих значений: Always (всегда), Never (никогда), или As Needed (по необходимости).

get/setVerticalScrollBarPolicy(): Аналогично горизонтальной функции.

91

3.8.15 JList

Компонент JList является полезным компонентом для предоставления пользователю многих вариантов для выбора. Вы можете представлять его как расширение JComboBox. JList предоставляет больше вариантов и добавляет возможность выбора нескольких вариантов. Выбор между JList и JComboBox часто заключается в следующем: если вам требуется возможность множественного выбора или имеется более 15 вариантов (хотя это число не является общим правилом), вы должны всегда выбирать JList.

Вы должны использовать JList совместно с JScrollPane, как было показано выше, поскольку он может предоставлять больше вариантов, чем помещается в видимой области.

JList имеет также модель выбора (также имеющуюся в JTable), которую вы можете установить в различные типы выбора вариантов. Такими типами являются: одиночный выбор (вы можете выбрать только один вариант), одиночный интервал (вы можете выбрать смежные варианты, но в любом их количестве) и множественный интервал (вы можете выбрать любое число вариантов в любых комбинациях).

JList является первым из компонентов, которые я называю "сложными компонентами", и к которым относятся также компоненты JTable и JTree, допускающие большое количество пользовательских настроек, в том числе внешнего вида и способа обработки данных. Поскольку данное руководство предназначено только для рассмотрения основ Swing, я не буду углубляться в эти расширенные функции, но при работе с этими компонентами вы должны помнить - они более сложны, чем рассмотренные до сих пор компоненты.

JList в Swing выглядит так:

JList

Существует много функций в JList для работы с данными, и, как я уже сказал, это только немногие из тех, которые потребуются для вашей работы с JList. Вот основные методы:

92

get/setSelectedIndex(): Получить/установить выбранную строку списка; в случае со списками с множественным выбором возвращается int[].

get/setSelectionMode(): Как объяснялось ранее,

получить/установить режим выбора в одиночный выбор, одиночный интервал или множественный интервал.

setListData(): Установить данные для использования в JList.

get/setSelectedValue(): Получить выбранный объект (как противоположность выбранному номеру строки).

3.8.16JTree

JTree - это еще один сложный компонент, который не так трудно использовать. Хитрость при работе с JTree состоит в требуемых моделях данных.

JTree наследует свою функциональность из концепции дерева с ветвями и листьями. Вы, возможно, знакомы с этой концепцией по работе с Internet Explorer в Windows - вы можете расширить и свернуть ветвь для отображения различных листьев, которые вы можете отметить, или с которых можете снять отметку.

Скорее всего, вы обнаружите, что древо не настолько полезно в приложении, как таблица или список, поэтому в Интернете нет большого количества полезных примеров. Фактически, аналогично JTable, компонент JTree не имеет каких-либо функций для новичков. Если вы решите использовать JTree, то тут же перейдете на средний уровень и должны будете изучить концепции, лежащие в основе его работы. В примере приложения не используется JTree, поэтому, к сожалению, ни руководство для новичков, ни руководство для среднего уровня квалификации не рассматривает детально этот менее популярный компонент.

Однако бывают ситуации, когда дерево логично использовать в качестве UI-компонента. Система файлов и каталогов - это один из примеров, как в Internet Explorer, и JTree является наилучшим компонентом для данных с иерархической структурой, иными словами, когда данные имеют форму дерева.

В Swing компонент JTree выглядит так:

93

JTree

Тема 3.9 Пример использования JDBC и SWING вместе

Приведем пример построения таблицы на основе выборки из базы данных. В данном примере были использованы классы DB, User, WorkTableUser из листинга 3.5. Показан класс MyTable потомок класса JTable, с помощью которого строится таблица по объекту класса ResultSet. В класса MyFrame данный объект добавлен к главной панели.

Листинг 3.4

//класс для создания таблицы import java.sql.*;

import java.util.Vector; import javax.swing.JTable;

import javax.swing.table.DefaultTableModel; public class MyTable extends JTable {

public MyTable(ResultSet rs) {

DefaultTableModel dft = new DefaultTableModel(); ResultSetMetaData rsmd;

try {

rsmd = rs.getMetaData();

for (int i = 1; i <= rsmd.getColumnCount(); i++) { dft.addColumn(rsmd.getColumnName(i));

}

while (rs.next()) {

Vector v = new Vector();

for (int i = 1; i <= rsmd.getColumnCount(); i++) { v.add(rs.getString(i));

}

dft.addRow(v);

94

}

setModel(dft); setAutoResizeMode(AUTO_RESIZE_ALL_COLUMNS);

} catch (SQLException ex) {

// TODO Auto-generated catch block System.out.println("Error in MyTable " + ex);

}

}

}

//фрейм, содержащий таблицу import java.awt.event.*;

import java.sql.ResultSet; import javax.swing.*;

public class MyFrame extends JFrame { private JPanel panel;

private JLabel label1, label2;

private JButton button1, button2, button3; private JTextField textField1, textField2; private MyTable table;

private DB db;

private JScrollPane scroll; private MouseAdapter mouse; public MyFrame() {

//установка заголовка и размеров фрейма setTitle("Заголовок");

setBounds(500, 200, 500, 350); panel = new JPanel(null);

//подключение к базе данных

db = new DB("jdbc:mysql://localhost/", "my_db", "root", "");

//создание таблицы

table = new MyTable(db.query("SELECT * FROM user"));

//добавление таблицы в скролл, а скролла к панели scroll = new JScrollPane(table);

scroll.setBounds(50, 50, 200, 150); panel.add(scroll);

//создание всех компонент label1 = new JLabel("Id"); label2 = new JLabel("Name"); button1 = new JButton("Add"); button2 = new JButton("Delete");

button3 = new JButton("Change");

textField1 = new JTextField(String.valueOf(Integer.valueOf(table.getValueAt(table.getRowCount() - 1, 0).toString()) + 1));

textField2 = new JTextField();

95

//позиционирование label1.setBounds(300, 50, 150, 20); textField1.setBounds(300, 90, 150, 20); label2.setBounds(300, 130, 150, 20); textField2.setBounds(300, 170, 150, 20); button1.setBounds(50, 250, 100, 20); button3.setBounds(170, 250, 100, 20); button2.setBounds(290, 250, 100, 20);

// добавление компонент к панели panel.add(label1); panel.add(label2); panel.add(button1); panel.add(button2); panel.add(button3); panel.add(textField1); panel.add(textField2);

//добавление панели к фрейму add(panel);

//добавление кнопок к прослушиванию button1.addActionListener(new ActionListener() {

@Override

public void actionPerformed(ActionEvent e) {

db.addUser(new User(Integer.valueOf(textField1.getText()), textField2.getText()));

updateTable();

textField1.setText(String.valueOf(Integer.valueOf(table.getValueAt(table.getRow Count() - 1, 0).toString()) + 1));

}

});

button2.addActionListener(new ActionListener() { @Override

public void actionPerformed(ActionEvent e) {

db.deleteUser(new User(Integer.valueOf(textField1.getText()), textField2.getText()));

updateTable();

textField1.setText(String.valueOf(Integer.valueOf(table.getValueAt(table.getRow Count() - 1, 0).toString()) + 1));

}

});

button3.addActionListener(new ActionListener() { @Override

public void actionPerformed(ActionEvent e) {

96

db.changeNameUser(new User(Integer.valueOf(textField1.getText()), textField2.getText()));

updateTable();

textField1.setText(String.valueOf(Integer.valueOf(table.getValueAt(table.getRow Count() - 1, 0).toString()) + 1));

}

});

mouse = new MouseAdapter() { @Override

public void mouseClicked(MouseEvent e) { textField1.setText(table.getValueAt(table.getSelectedRow(),

0).toString());

textField2.setText(table.getValueAt(table.getSelectedRow(),

1).toString());

}

};

table.addMouseListener(mouse);

//установка операции по нажатию на крестик setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//прорисовка фрейма

setVisible(true);

}

public void updateTable() { panel.remove(scroll);

table = new MyTable(db.query("SELECT * FROM user")); table.addMouseListener(mouse);

scroll = new JScrollPane(table); scroll.setBounds(50, 50, 200, 150); panel.add(scroll); panel.updateUI();

}

}

В результате запуска данного кода получим фрейм, изображенный на рисунке 3.4

97

Рисунок 7.4

При нажатии на кнопку Add новый пользователь добавляется в базу данных, Change – меняется имя, Delete – пользователь удаляется из БД и таблица обновляется. На рисунке 7.5 показан фрейм после добавления user7, удаления user2 и редактирование user3.

Рисунок 3.5

В данной главе были показаны примеры использования лишь некоторых компонент. Библиотека swing дает большие возможности для создания пользовательских интерфейсов, поэтому рекомендуем продолжить изучение данной библиотеки по документации или по специальным справочникам по swing.

98

Тема 3.10 Работа с датой и временем

3.10.1 Date

Класс Date предназначен для работы с текущими датой и временем и позволяет отталкиваться от них для решения своих задач. При выходе новых версий Java часть методов класса была перемещена в классы Calendar и DateFormat.

При импорте выбирайте java.util.Date, а не java.sql.Date.

У класса есть два конструктора:

Date()

Date(long milliseconds)

Первый конструктор без параметров инициализирует объект текущей датой и временем. Во втором конструкторе вы можете указать количество миллисекунд, прошедших с полуночи 1 января 1970 года.

Методы:

boolean after(Date date) - если объект класса Date содержит более позднюю дату, чем указано в параметре, то возвращается true

boolean before(Date date) - если объект класса Date содержит более раннюю дату, чем указано в параметре, то возвращается true

int compareTo(Date date) - сравнивает даты. Возвращает 0, если совпадают, отрицательное значение - если вызывающая дата более ранняя, положительное значение - если вызывающая дата более поздняя, чем в параметре

boolean equals(Object object) - если даты совпадают, то возвращается

true

long getTime() - возвращает количество миллисекунд, прошедших с полуночи 1 января 1970 года

void setTime(long milliseconds) - устанавливает время и дату в виде числа миллисекунд, прошедших с полночи 1 января 1970 года.

Если вы посмотрите документацию, то увидите, что существует множество методов для получения или установки отдельных компонентов времени и даты, например, getMinutes()/setMinutes() и др. Все они являются устаревшими и вместо них следует использовать класс Calendar.

Простой пример вывода даты на экран.

// Создадим объект Date

99

Date date = new Date();

textViewInfo.setText(date.toString());

С помощью метода getTime() можно отобразить количество миллисекунд, прошедших с 1 января 1970 года. Обновим пример

// Создадим объект Date Date date = new Date(); long millis = date.getTime();

textViewInfo.setText(String.valueOf(millis));

3.10.2 Calendar

Абстрактный класс Calendar позволяет преобразовать время в миллисекундах в более удобном виде - год, месяц, день, часы, минуты, секунды. Существуют также подклассы, например, GregorianCalendar.

Переменная типа boolean под именем areFieldsSet указывает, были установлены компоненты времени. Переменная fields - это массив целочисленных значений, содержащий компоненты времени. Переменная isSet - массив типа boolean, указывающий, был ли установлен специфический компонент времени. Переменная time (тип long) содержит текущее время объекта. Переменная isTimeSet (тип boolean) указывает, что было установлено текущее время.

У класса много методов. Вкратце опишем часть из них:

abstract void add(int field, int value) - добавляет value к компоненту времени или даты, указанному в параметре field (например, Calendar.HOUR). Чтобы отнять, используйте отрицательное значение.

boolean after(Object calendar) - возвращает значение true, если вызывающий объект класса Calendar содержит более позднюю дату, чем calendar.

boolean before(Object calendar) - возвращает значение true, если вызывающий объект класса Calendar содержит более раннюю дату, чем calendar.

final void clear() - обнуляет все компоненты времени в вызывающем объекте.

final void clear(int field) - обнуляет компонент, указанный в параметре

field

int get(int field) - возвращает значение одного компонента, например,

Calendar.MINUTE

synchronized static Locale[] getAvailableLocales() - возвращает массив объектов класса Locale, содержащий региональные данные

100