1138
Часть
11.
Библиотека
Java
Организуя
параллельное
выполнение
в
потоке
данных,
следует
также
прини
мать
во
внимание
порядок
следования
в
нем
элементов.
Потоки данных могут
быть
как
упорядоченными,
так
и
неупорядоченными.
Если
источник
данных
упо
рядочен,
то,
как
правило,
упорядочен
и
поток
данных.
Но иногда
можно
добиться
повышения
производительности,
если
применяемый
поток данных
неупорядочен.
В
этом
случае
каждую
часть
потока
данных
можно
обрабатывать
отдельно,
не
со
гласуя
ее
с
остальными
частями.
В
тех
случаях,
когда
порядок
следования
опера
ций
не
имеет
особого
значения,
можно
выбрать
режим
работы
без
упорядочения,
вызвав
метод
unordered
(),общая
форма
которого
приведена
ниже.
S
unordered
()
И
наконец,
при
выполнении метода
forEach
()
упорядоченность
параллель
ного
потока
может
не
сохраняться.
Если
же
при
выполнении
операции над
каждым
элементом
в
параллельном
потоке
данных
требуется
сохранить
его
упорядочен
ность, то лучше воспользоваться методом forEachOrdered ().Этот
меняется таким же образом, как и метод forEach ().
метод
при
Отображение
Нередко
элементы
одного
потока
данных
требуется
отобразить
на
элемен
ты
другого
потока.
Например,
из
базы
данных,
содержащей
имя,
номер
телефона
и
адрес
электронной
почты
в
одном
потоке данных,
требуется
отобразить
только
имя
и
адрес
электронной
почты
в
другом
потоке.
А
в
качестве
другого
примера
можно
привести
преобразование,
которое
требуется
выполнить
только
над
не
которыми
элементами
в
потоке
данных.
Операции
отображения
весьма
распро
странены, и
поэтому
в
потоковом прикладном
интерфейсе
API
предоставляется
их
встроенная
поддержка.
Самое
общее
отображение
выполняется
методом
map
( ) .
Ниже
приведена
его
обобщенная
форма.
<R>
Stream<R>
map(Function<? super т,
функция_отображения)
?
extends
R>
Здесь
параметр
R обозначает
тип
элементов
из
нового
потока
данных;
пара
метр
т
-
тип
элементов
из
вызывающего
потока
данных;
параметр
функция_
отображения-
экземпляр
функционального
интерфейса
Function,
выполняю
щий
отображение.
Функция
отображения
должна
выполнять
операцию
без
сохра
нения
состояния
и
без
вмешательства.
А
метод
map
( )
выполняет
промежуточную
операцию, поскольку он возвращает |
новый поток данных. |
|
Интерфейс Func t i on является |
функциональным |
и |
j ava. util. function следущим образом: |
|
объявляется
в
пакете
Function<T,
R>
Здесь
параметр
т
по
отношению
к
методу
map
( )
обозначает
тип
элемента,
а
па
раметр
R -
результат
отображения.
В функциональном
интерфейсе
Function
объявляется
следующий
абстрактный
метод:
R
apply(T
значение)
1140
Часть
11.
Библиотека
Java
поток данных объектов типа NamePhone отображаются только телефонов, тогда как адреса электронной почты отбрасываются.
имена
и
номера
11 11 11
Применить |
метод |
map() |
для |
создания |
нового |
потока данных, |
содержащего |
только |
избранные |
||
элементы |
из исходного |
потока |
|
import import
java.util.*; java.util.stream
.*;
class NamePhoneEmail |
|
||
String |
name; |
|
|
String |
phonenum; |
|
|
String |
email; |
|
|
NamePhoneEmail(String |
n, |
||
name |
= n; |
|
|
phonenum |
= р; |
|
|
= |
е; |
|
String
р,
String
е) |
{ |
class NamePhone |
{ |
|
|
String |
name; |
|
|
String |
phonenum; |
|
|
NamePhone(String |
n, |
||
name |
= n; |
|
|
phonenum = |
р; |
|
String
р)
{
class |
StreamDemo5 { |
|
|
|
|
|
|
|
|
|
|
puЫic static void |
main(String[] |
args) |
|
|
|||||||
11 |
Список |
имен, |
номеров |
телефонов |
и |
|
|
||||
11 |
адресов |
электронной почты |
|
|
new |
ArrayList<>(); |
|||||
ArrayList<NamePhoneEmail> myList = |
|||||||||||
myList .add (new |
NamePhoneEmail |
("Ларри", |
"555-5555", |
||||||||
|
|
|
|
|
|
|
"Larry@HerbSchildt.com")); |
||||
myList.add(new |
NamePhoneEmail("Джeймc", |
"555-4444", |
|||||||||
|
|
|
|
|
|
|
"James@HerbSchildt.com")); |
||||
myList. add (new |
NamePhoneEmail |
("Мэри", |
"555-3333", |
||||||||
|
|
|
|
|
|
|
"Mary@HerbSchildt.com") ); |
||||
System.out.println("Иcxoдныe |
элементы |
из |
списка myList: |
||||||||
myList.stream() |
.forEach( |
(а) |
-> |
{ |
|
|
|
||||
|
System.out.println(a.name |
+ |
" |
" |
+ a.phonenum |
||||||
|
|
|
|
+ " |
" |
+ |
а. emai l) ; |
|
|
||
} ) |
; |
|
|
|
|
|
|
|
|
|
|
System.out.println(); |
|
|
|
|
|
|
|
||||
11 |
отобразить на |
новый поток |
данных |
|
|
||||||
11 |
только |
имена |
и |
номера |
телефонов |
|
|
|
");
|
Глава |
29. Потоковый прикладной интерфейс API |
||||
Stream<NamePhone> |
nameAndPhone = |
myList.stream() .map( |
||||
(а) |
-> |
new |
NamePhone(a.name,a.phonenum) |
|||
) ; |
|
|
|
|
|
|
System.out.println( |
|
|
|
|
|
|
"Список |
имен и |
номеров |
телефонов: |
"); |
||
nameAndPhone.forEach( |
(а) |
-> |
{ |
+ a.phonenum); |
||
System.out.println(a.name + |
" " |
|||||
} ) ; |
|
|
|
|
|
|
1141
Ниже приведен результат, выводимый данной программой.
рить исходные элементы списка с отображаемыми.
Он
позволяет
све
Исходные элементы из списка myList: |
||
Ларри |
555-5555 |
Larry@HerbSchildt.com |
Джеймс |
555-4444 |
James@HerbSchildt.com |
Мэри 555-3333 Mary@HerbSchildt.com |
Список |
имен и |
номеров |
Ларри |
555-5555 |
|
Джеймс |
555-4444 |
|
Мэри 555-3333 |
|
телефонов:
Несколько
промежуточных
операций
можно
объединить
в
единый
конвейер,
что |
позволяет составлять |
щем |
фрагменте кода для |
элементы имени и номера |
довольно получения телефона,
эффективные действия. |
Например, в следую |
|
нового потока |
данных, |
содержащего только |
совпадающие с |
именем "Джеймс'; сначала вы |
зывается
метод
f
i
1
ter
(),а затем
метод
map
():
Stream<NamePhone> |
|
.filter((a) |
|
.map( (а) |
-> |
nameAndPhone = myList.stream() |
|
-> |
a.name.equals("Джeймc")) |
new |
NamePhone(a.name,a.phonenum)); |
Такая операция фильтрации весьма характерна для составления запросов базы данных. Приобретя некоторый опыт обращения с потоковым прикладным интер фейсом АР!, вы непременно обнаружите, что из подобных цепочек операций мож
но
составлять
довольно
сложные
запросы,
объединения
и выборки
информации
в
потоке данных. Помимо описанной
выше
формы,
имеются
еще
три
формы
метода
map
( ) .
Все
они
возвращают
поток данных
примитивного
типа
и
приведены
ниже.
IntStream |
mapToint(TointFunction<? super Т> |
|
|
|
|
функция_отображения) |
|
LongStream |
mapToLong(ToLongFunction<? super |
Т> |
|
|
|
функция_отображения) |
|
DouЬleStream |
mapToDouЬle(ToDouЬleFunction<? |
super |
|
|
|
функция_отображения) |
Т>
Каждая
задаваемая
функция_
отображения
должна
реализовывать
абстракт
ный
метод,
определяемый
в
заданном
интерфейсе
и
возвращающий
значение
ука
занного
типа.
Например,
в
интерфейсе
ToDouЬleFunct
ion
определяется
метод
1162
Часть
11.
Библиотека
Java
11
Использовать метод
split()
import
java.util.regex.*;
class |
RegExpr9 { |
void main(String args[J) |
{ |
||
puЬlic static |
|||||
11 |
составить |
шаблон для |
сопоставления |
со |
|
11 |
набранными |
строчными |
буквами |
|
|
Pattern pat |
= |
Pattern.compile(" [ , . ! ] |
"); |
словами,
String
strs[]
=
pat.split("one two,
alpha9
l2!done.");
for(int i=O; i < strs.length; i++)
System.out.println("Cлeдyющaя лексема:
" |
+ |
strs[i]);
Ниже
приведены
результаты
выполнения
данной
программы.
Следующая Следующая Следующая Следующая Следующая
лексема: лексема: лексема: лексема: лексема:
one two alpha9 12 done
Как
следует
из
результатов,
входная
последовательность
сводится
к
отдельным
лексемам.
Обратите внимание
на
отсутствие
разделителей
в
выводимых
результатах.
Два
варианта
сопоставления
с
шаблоном
Несмотря
на
то
что
описанные
способы
сопоставления
с
шаблонами
отлича
ются
высокой
степенью
гибкости
и высокой
производительностью,
имеются
два
других варианта,
которые
могут
оказаться
полезными
в
определенных
обстоя
тельствах.
Так,
если
требуется
только
одноразовое
сопоставление
с
шаблоном,
то для этой цели можно воспользоваться |
методом matches |
(), |
в классе Раt tern. Ниже приведена общая |
форма этого метода. |
|
определяемым
static
boolean
matches(String
шаблон,
CharSequence
строка)
Метод
matches
()
возвращает
логическое
значение
true,
если
заданный
шаблон
совпадает
с
указанной
строкой,
а
иначе
-
логическое
значение
false.
Этот
метод
автоматически
компилирует
заданный
шаблон,
а затем
осуществля
ет
поиск
на
совпадение
с
ним.
Для
неоднократного
применения
шаблона
вызов
метода
matches
()
оказывается
менее
эффективным,
чем
отдельная
компиля
ция
шаблона
и
сопоставление
с
ним
с помощью
методов,
определяемых
в
классе
Matcher, как пояснялось ранее.
Сопоставление с шаблоном
можно
также
выполнить
с
помощью
метода
matches
(),реализуемого
в
классе
String.
Ниже
приведена
общая
форма
это
го
метода.
Если
вызывающая
строка
совпадает
с
регулярным
выражением,
обо
значаемым
параметром
шаблон,
то
метод
matches
()
возвращает
логическое
значение
true,
а
иначе
-
логическое
значение
false.
boolean
matches(String
шаблон)
1164
Часть
11.
Библиотека
Java
В
приведенном
ниже
примере
прикладной
программы
демонстрируется
про
стой
вариант
применения
свойств
рефлексии
в |
Java. |
Эта
программа
выводит
на
экран
конструкторы,
поля и методы
из
класса
j
ava.
awt.
Dimens
ion.
Сначала
в
этой
программе
вызывается
метод
forName
()
из
класса
Class
для
получения
объекта
класса
j
ava.
awt.
Dimens
ion.
Как
только
он
будет
получен,
вызывают
ся
методы
getConstructors
(),
getFileds
()
и
getMethods
()
для
анали
за объекта |
этого класса. Они возвращают массивы |
и Method, |
содержащие сведения об этом объекте. |
типа
Constructor,
Field
В
классах
Constructor,
Field
и
Method
определяется
ряд
методов,
которые
можно
использовать
для
получения
сведений
об
объекте.
Вам
придется
изучить
эти
классы
самостоятельно,
но
в
каждом
из
них
поддерживается
метод
toString ().
Как
показано
в
данной
программе,
указывать
объекты
типа
Constructor,
Field
и
Method
в
качестве
параметров
метода
pr
in
t
ln
( )
совсем
не
трудно.
11
Продемонстрировать
применение
рефлексии
import
java.lang.reflect.*;
puЫic class ReflectionDemol puЬlic static void main(String
args[])
{
try { Class<?>
с
=
Class.forName("java.awt.Dimension");
System.out.println("Koнcтpyктopы:"); |
|
|
|||||||||
Constructor |
constructors[] |
= c.getConstructors(); |
|||||||||
for(int |
i |
= |
О; |
i |
< |
constructors.length; |
i++) |
{ |
|||
System.out.println(" |
" + |
constructors[i] ); |
|
||||||||
System.out.println("Пoля:"); |
|
|
|
||||||||
Field fields[J |
= |
c.getFields(); |
|
|
|
||||||
for(int |
i |
= |
О; |
i |
< |
fields.length; |
i++) |
|
|
||
System.out.println(" |
" + |
fields[i]); |
|
|
|||||||
System.out.println("Meтoды:"); |
|
|
|
||||||||
Method |
methods[J |
= |
c.getMethods(); |
|
|
|
|||||
for(int |
i |
= |
О; |
i |
< |
methods.length; |
i++) |
|
|
||
System.out.println(" |
"+ |
methods(i]); |
|
|
catch(Exception е) |
{ |
System.out.println("Иcключeниe: |
"
+
е);
Ниже приведен примерный
может оказаться иным).
результат,
выводимый
данной
программой
(у
вас
он
Конструкторы:
puЬlic puЬlic puЬlic
java.awt.Dimension(int, java.awt.Dimension() java.awt.Dimension(java
int) .awt.Dimension)
Поля:
Глава
30.
Регулярные
выражения
и
другие
пакеты
1165
puЬlic puЫic Методы: puЬlic puЬlic puЫic puЬlic puЬlic puЬlic puЫic puЬlic puЬlic puЬlic puЫic
puЬlic puЫic puЬlic
puЫic throws puЬlic puЬlic
int |
java.awt.Dimension.width |
int |
java.awt.Dimension.height |
int |
java.awt.Dimension.hashCode() |
boolean java.awt.Dimension.equals(java.lang.Object) |
||||
java.lang.String |
java.awt.Dimension.toString() |
|||
java.awt.Dimension java.awt.Dimension.getSize() |
||||
void |
java.awt.Dimension.setSize(douЫe, douЬle) |
|||
void |
java.awt.Dimension.setSize(java.awt.Dimension) |
|||
void |
java.awt.Dimension.setSize(int, int) |
|||
douЫe |
java.awt.Dimension.getHeight() |
|||
douЫe |
java.awt.Dimension.getWidth() |
|||
java.lang.Object |
java.awt.geom.Dimension2D.clone() |
|||
void |
java.awt.geom.Dimension2D.setSize( |
|||
java.awt.geom.Dimension2D) |
||||
final |
|
native |
java.lang.Class java.lang |
|
.Object.getClass() |
||||
final |
|
native |
void |
java.lang.Object.wait(long) |
throws |
java.lang.InterruptedException |
|||
final |
|
void java.lang.Object.wait() |
||
throws |
java.lang.InterruptedException |
|||
final |
|
void java.lang.Object.wait(long, int) |
||
java.lang.InterruptedException |
||||
final |
|
native |
void |
java.lang.Object.notify() |
final |
|
native |
void |
java.lang.Object.notifyAll() |
В
следующем
примере
программы
возможности
рефлексии
в
Java
используют
ся
для
получения
открытых
методов
класса.
Сначала
в этой
программе
реализу
ется
класс
А.
Метод
getClass
()
вызывается
по
ссылке
на
объект
этого
класса
и
возвращает
объект
типа
Class
для
описания
класса
А.
Метод
getDeclared
Methods
()
возвращает
массив
объектов
типа
Method,
описывающий
только
ме
тоды,
объявленные
в
классе
А.
В
этот
массив
не
включаются
методы,
унаследован
ные от суперклассов, например от класса Obj ect. |
|
После этого обрабатывается каждый элемент |
массива |
methods.
В
частности,
метод
getModi
f
iers
()
возвращает
значение
типа
int,
содержащее
признаки,
описывающие
модификаторы
доступа,
применяемые
к
этому
элементу.
В
классе
Modi
f |
i |
er
предоставляется
ряд
методов
типа
i |
sX, |
перечисленных
в
табл.
30.3
и
предназначенных
для
проверки
заданного
значения.
Например,
статический
метод
isPuЬlic
()
возвращает
логическое
значение
true,
если в
его
аргумент
включается
модификатор
доступа
puЫic,
а
иначе
-
логическое
значение
false.
Табnица
30.3.
Методы из кnасса Modifier,
модификатор доступа
опредеnяющие
Методы
static boolean isAЬstract(int энаvвнив)
static boolean isFinal(int энаvвнив)
Описание
Возвращает логическое значение true, если заданное энаvвнив имеет установленный признак abstract, а иначе - логическое значение false
Возвращает логическое значение true, если заданное
энаvвнив имеет установленный признак final, а иначе -
логическое значение false
1166
Часть
11.
Библиотека
Java
Методы
static boolean isinterface(int значение)
static boolean isNative(int значение)
static boolean isPrivate(int значение)
static boolean isProtected(int значение)
static boolean isPuЬlic(int значение)
static boolean isStatic(int значение)
static boolean isStrict(int значение)
static boolean isSynchronized(int значение)
static boolean isTransient(int значение)
static boolean isVolatile(int значение)
Окончание табл. 30.З
Описание |
|
|
Возвращает логическое значение true, если заданное |
|
|
значение имеет установленный признак interface, |
|
|
а иначе - логическое значение false |
|
|
Возвращает логическое значение true, если заданное |
- |
|
значение имеет установленный признак nati ve, а иначе |
|
|
логическое значение false |
|
|
Возвращает логическое значение true, если заданное |
|
- |
значение имеет установленный признак private, а иначе |
||
логическое значение false |
|
|
Возвращает логическое значение true, если заданное |
|
|
значение имеет установленный признак protected, |
|
|
а иначе - логическое значение false |
|
|
Возвращает логическое значение true, если заданное |
- |
|
значение имеет установленный признак puЬlic, а иначе |
|
|
логическое значение false |
|
|
Возвращает логическое значение true, если заданное |
- |
|
значение имеет установленный признак static, а иначе |
|
|
логическое значение false |
|
|
Возвращает логическое значение true, если заданное |
- |
|
значение имеет установленный признак strict, а иначе |
|
|
логическое значение false |
|
|
Возвращает логическое значение true, если заданное |
|
|
значение имеет установленный признак synchronized, |
|
|
а иначе - логическое значение false |
|
|
Возвращает логическое значение true, если заданное |
|
|
значение имеет установленный признак transient, |
|
|
а иначе - логическое значение false |
|
|
Возвращает логическое значение true, если заданное |
|
|
значение имеет установленный признак volatile, |
|
|
а иначе - логическое значение false |
|
|
Если
метод
оказывается
открытым,
то
его
имя
получается
с
помощью
метода
getName
()
и
затем
выводится
на
экран.
Ниже
приведен
исходный
код
из
данного
примера
программы.
11
Показать
открытые
методы
import java.lang.reflect.*;
puЬlic |
class |
ReflectionDemo2 |
||||
puЬlic |
|
static |
void |
main(String |
||
try |
|
{ |
|
|
|
|
А |
|
а |
= |
new |
А(); |
|
args[])
{
Class<?>
с
=
a.getClass();
System.out.println("Oткpытыe
методы:");
Method |
methods(] |
= c.getDeclaredМethods(); |
||||
for ( int |
i = О; |
i |
< |
methods. length; |
i ++) |
{ |
int modifiers |
|
= |
methods[i] .getModifiers(); |
|||
if(Modifier.isPuЬlic(modifiers)) |
{ |
|
1176
Часть
11.
Библиотека
Java
System.out.println(sdf.format(date)); |
|
|
|
sdf = |
new SimpleDateFormat("dd МММ уууу |
hh:mm:ss |
|
System.out.println(sdf.format(date)); |
|
|
|
sdf = |
new SimpleDateFormat("E МММ dd |
уууу"); |
|
System.out.println(sdf.format(date)); |
|
|
zzz");
Ниже
приведен
примерный
результат,
выводимый
данной
программой.
01:30:51 |
||
01 |
Jan |
2017 |
Sun |
Jan |
01 |
01:30:51 2017
CST
Пакеты
из
прикладного
интерфейса
API
даты
и
времени
В
главе
20
был
представлен
давно
устоявшийся
в
Java
подход
к
обработке
даты
и
времени
средствами
классов
Calendar
и
GregorianCalendar.
На
момент
на
писания
данной
книги
этот
традиционный
подход
был
по-прежнему
широко
рас
пространен
и,
скорее
всего,
останется
таковым
еще
некоторое
время,
а
следова
тельно,
он
должен
быть
известен
программирующим
на
Java.
Но
в
версии
JDK
8
в
Java
был
предложен
другой
подход
к
обработке
даты
и времени,
который
опреде
лен
в
пакетах,
перечисленных
в
табл.
30.5.
Таблица
30.S.
Пакеты
из
прикладноrо
интерфейса
API
даты
и
времени
java.time
java.time.chrono java.time.format j ava. time. temporal
j ava. time. zone
Предоставляет классы верхнего уровня для поддержки даты
и времени
Померживает другие календари, кроме григорианского
Померживает форматирование даты и времени
Померживает расширенные функциональные возможности
обработки даты и времени
Померживает часовые пояса
и
В этих новых |
пакетах определяется большое |
количество |
классов, интерфейсов |
перечислений, |
обеспечивающих обширную и |
подробную |
помержку операций |
обработки
даты
и
времени.
Такое
большое
количество
элементов,
составляющих
прикладной
интерфейс
API
даты
и
времени,
поначалу
выглядит
немного
пугающе.
Но
этот
прикладной
интерфейс
хорошо
организован
и
логически
структурирован.
Его
размеры
отражают
степень
детализации
и
гибкость
управления,
предостав
ляемые
для
обработки
даты и
времени.
В
рамках
данной
книги
просто
невозмож
но
описать
каждый
элемент
этого
обширного
прикладного
интерфейса,
поэтому
ниже
будут
рассмотрены
лишь
самые
основные
его классы.
В
ходе обсуждения
этих
классов
станет
ясно,
что
их
достаточно
для
применения
во
многих
случаях.
Начиная
с
версии
JDK
9,
пакеты,
перечисленные
в
табл.
30.5,
входят
в
состав
моду
ля
j
ava.
base.
1178
Часть
11.
Библиотека
Java
class DateTimeDemo { puЬlic static void
main(String
args[])
LocalDate |
curDate |
= |
LocalDate.now(); |
System.out.println(curDate); |
|||
LocalTime |
curTime |
= |
LocalTime.now(); |
System.out.println(curTime); |
Ниже |
приведен |
примерный |
Полученный результат отражает |
результат, |
выводимый данной |
программой. |
стандартный формат, который |
получают дата |
и
время.
(В
следующем
разделе
будет
показано,
как
указать
другой
формат.)
2017-01-01 14:03:41.436
В
предыдущем
примере
программы
отображаются
текущие
дата
и
время,
но
это
было
бы
проще
сделать
средствами
класса
LocalDateTime.
В
этом
случае
по
требовалось
бы
создать
единственный
экземпляр
данного
класса
и
сделать
един
ственный
вызов
его
метода
now
( ) ,
как
показано
ниже.
LocalDateTime curDateTime = LocalDateTime System.out.println(curDateTime);
.now();
При таком подходе дата и
веден пример такого вывода.
время
выводятся
по
умолчанию
вместе.
Ниже
при
2017-0l-01T14:04:56.799
Следует
также
заметить,
что
из
экземпляра
класса
LocalDateTime
можно
также
получить
ссылку
на
составляющую
даты
или
времени,
вызвав
метод
toLo
-
calDate
()
или
toLocalTime
()
соответственно.
Ниже
приведены
общие
фор
мы
этих
методов.
Каждый
из
них
возвращает
ссылку
на
указанную
составляющую.
LocalDate
LocalTime
toLocalDate() toLocalTime()
Форматирование даты
и
времени
Стандартные
форматы даты
и
времени,
продемонстрированные
в
предыдущих
примерах,
оказываются
пригодными лишь
в
некоторых
случаях,
а
зачастую
тре
буется
указывать
другой
формат.
Правда,
сделать
это
совсем
не
трудно,
поскольку
в
классах
LocalDate,
Local
Time
и
LocalDateT
ime
для
этой
цели
предоставля
ется
метод
format
().Ниже
приведена
общая
форма
этого
метода,
где
параметр
форматирующий_объект обозначает предоставляющий требуемый формат.
экземпляр
класса
DateTimeFormat
ter,
String
format(DateTimeFormatter
форматирующий_объект)
Класс
DateTimeFormat
ter
входит
в
состав
пакета
j
ava.
time.
format.
Для
получения
экземпляра
класса
DateTimeFormatter,
как
правило,
вызывается
один
из
фабричных
методов.
Ниже
приведены
общие
формы
трех таких
методов.
1180
Часть
11.
Библиотека
Java
или
ISO_TIME
из
класса
DateTimeFormatter.
А
с
другой
стороны,
можно
соз
дать
специальный
формат,
указав
шаблон.
Для
этого
достаточно
вызвать
фабрич
ный метод of Pattern () из |
класса |
из общих форм этого метода. |
|
DateTimeFormatter.
Ниже
приведена
одна
static
DateTimeFormatter
ofPattern(String
шаблон_форматирования)
Здесь
параметр
шаблон_форматирования
обозначает
символьную
строку,
содержащую шаблон, требующийся для форматирования метод возвращает объект типа DateTimeFormat ter для
даты и времени. форматирования
Этот по за
данному
шаблону
с
учетом
региональных
настроек
по
умолчанию.
В |
общем, шаблон состоит из |
спецификаторов формата, |
называемых |
иначе |
|
буквами шаблона. Каждая |
буква |
шаблона заменяется той |
составляющей |
даты |
|
или |
времени, которую она |
обозначает. Полный перечень букв шаблона приведен |
в
описании
метода
of
Pat
tern
()
из
документации
на
прикладной
интерфейс
API
даты
и
времени,
а
в
табл.
30.6
перечислены
лишь
некоторые
их
них.
Следует
иметь
в
виду,
что
буквы
шаблона
указываются
с
учетом
регистра.
Таблица
30.б.
Избранные
буквы
шаблона
&уква шаблона а d Е h н м m s у
Назначение Обозначает время до полудня
День месяца День недели
Час в 12-часовом формате
Час в 24-часовом формате Месяц Минуты Секунды Год
(АМ)
или
после
полудня
(РМ)
В
общем,
конкретный
выводимый
результат
зависит
от
количества
повторений
буквы
в
шаблоне.
(Следовательно,
класс
Da
tет
imeForma
t
t
er
действует в
какой
то
степени
аналогично
классу
SimpleDateFormat
из
пакета
j
ava.
text,
как
пояснялось
ранее
в
этой
главе.)
Например,
следующий
шаблон
для
вывода
даты
в
апреле
месяце:
м мм
ммм
мммм
позволяет вывести отформатированную воря, чтобы уяснить назначение каждой
дату, как показано ниже. Откровенно го буквы шаблона и воздействие различных
повторений
на
вывод,
лучше
всего
поэкспериментировать
с
ними.
4
04
Apr
April
Если
букву шаблона
требуется
вывести
как
текст,
ее следует
заключить
води
нарные
кавычки.
Таким
образом,
все
символы,
не
относящиеся
к
шаблону,
реко
мендуется
заключать в
одинарные
кавычки,
чтобы
избежать
осложнений
при
из
менении
букв шаблона в
последующих
версиях
Java.
Глава
30.
Регулярные
выражения
и
другие
пакеты
1181
В
следующем
примере
программы
демонстрируется
применение
шаблона даты
и
времени:
11
Создание
специального
формата
даты
и
времени
import |
java.time.*; |
|
|
import |
java.time.format.*; |
|
|
class |
DateTimeDemoЗ |
{ |
|
puЫic static void |
main(String |
args[]) |
{
LocalDateTime curDateTime = LocalDateTime System.out.println(curDateTime.format( DateTimeFormatter.ofPattern(
.now();
"ММММ
d','уууу
h':'mm
а")));
Ниже
приведен
примерный
результат, выводимый
данной
программой.
January
1,
2017
2:22
РМ
В
отношении
создания
специального
формата
вывода
даты
и
времени
следует
также
заметить
следующее:
в
классах
LocalDate,
Local
Time
и
LocalDateTime
определяются
методы,
позволяющие
получать
различные
составляющие
даты
и
времени.
Например,
метод
getHour
()
возвращает
час
в
виде
целочисленного
значения
типа
int,
метод
getMonth
() |
- |
месяц
в
виде
значения
перечислимого
типа
Month,
а
метод
getYear
()
-
год
в
виде
целочисленного
значения
типа
int.
Используя
эти
и
другие методы,
можно
сформировать
вывод
даты
и
времени
вруч
ную.
Получаемыми
в
итоге
значениями
можно
воспользоваться
и
в
других
целях,
например
при
создании
специальных
таймеров.
Синтаксический анализ
символьных строк даты
и
времени
В
классах
LocalDate,
Local
Time
и
LocalDateT
ime
предоставляются
сред
ства
для
синтаксического
анализа
символьных
строк
даты
и/или
времени.
С
этой
целью
вызывается
метод
parse
()
для
экземпляра
одного
из
упомянутых
клас
сов.
У
этого
метода
имеются две
формы.
В
первой
форме
применяется
выбираемое
по
умолчанию
средство
форматирования
и
выполняется
синтаксический
анализ
даты
и/или
времени,
отформатированных
по
стандарту
ISO,
например,
времени
в
формате
О
3
:
31
и
даты
в
формате
2
О
2
О
-
О
8 -
О
2.
Ниже
приведена общая
форма
метода
parse
()
для
класса
LocalDateTime.
(Его
общие
формы
для
других
клас
сов
аналогичны,
за
исключением
типа
возвращаемого
объекта.)
static
LocalDateTime
CharSequence
parse( строка_даты_времени)
Здесь
параметр
строка_даты_времени
обозначает
символьную
строку,
со
держащую дату и время в надлежащем
формат, возникнет ошибка.
формате.
Если
же
указан
недействительный
1192
Часть
111.
Введение
в
программирование
ГПИ
средствами
Swing
Простое
Swi
ng-n
риложение
Swing-приложения
отличаются
и
от
консольных
программ
и
АWТ-приложений,
демонстрировавшихся
ранее
в
данной
книге.
Например,
в
них
используются
компо
ненты
и
иерархии
контейнеров
не
из
библиотеки
АWT.
Кроме
того,
Swing-приложения
предъявляют
особые
требования,
связанные
с
многопоточной
обработкой.
Уяснить
структуру
Swing-приложения
лучше
всего
на
конкретном
примере.
Имеются
две
раз
новидности
программ
на
Java,
в
которых
обычно
применяется
библиотека
Swing:
на
стольные
приложения
и
аплеты.
В
этом
разделе
будет
рассмотрен
пример
создания
Swing-приложения.
А
об
аплетах,
в
том
числе
и
на
основе Swing,
речь
вкратце
пойдет
в
приложении
Г
к
данной
книге,
поскольку
они
еще
встречаются
в унаследованном
коде,
хотя
и
не
рекомендуются
больше
к
употреблению
в
новом
коде.
Несмотря
на
всю
краткость
рассматриваемого
здесь
примера
программы,
он
наглядно демонстрирует
один
из
способов
разработки
Swing-приложения,
а
также
основные
средства
библиотеки
Swing.
В
данном
примере
используются
два
компо
нента
Swing:
JFrame
и
JLabel.
Класс
JFrame
представляет
контейнер
верхнего
уровня,
который
обычно
применяется
в
Swing-приложениях,
а
класс
JLabe
1 |
- |
компонент
Swing,
создающий
метку
для
отображения информации.
Метка
явля
ется
самым
простым
компонентом
Swing,
поскольку
это
пассивный
компонент.
Это
означает,
что
метка
не
реагирует
на
действия
пользователя.
Она
служит
лишь
для
отображения
выводимых
данных.
В
данном
примере
контейнер
типа JFrame
служит
для хранения
метки
в
виде
экземпляра
класса
JLabel.
Метка
отображает
краткое
текстовое
сообщение.
11
Пример
простого
Swing-приложения
import
javax.swing.*;
class
SwingDemo
SwingDemo() |
{ |
11 |
создать |
новый |
контейнер |
типа JFrame |
JFrame jfrm |
= new |
JFrame("A |
Simple Swing |
|
11 |
Простое |
Swing-приложение |
|
Application");
11 j f
задать rm. s е t Si
исходные |
l |
z е (27 5 , |
размеры О О ) ;
фрейма
11 11
завершить закрывает
работу, |
если |
приложение |
пользователь
jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
11 |
создать |
метку с |
текстом |
сообщения |
|
JLabel jlab = new |
JLabel("Swing means |
||||
11 |
Swing - |
это |
мощные ГПИ |
|
|
11 |
ввести |
метку |
на |
панели |
содержимого |
j frm. add ( j |
lab); |
|
|
|
powerful
GUis.");
11
отобразить
фрейм
1210
Часть
111.
Введение
в
программирование
ГПИ
средствами
Swing
компонент
позволяет
отредактировать
одну
строку
текста.
Класс
JText
F i
е
l d
яв
ляется
производным
от
класса
JTextComponent,
наделяющего
функциональны
ми
возможностями
текстовые
компоненты
Swing.
В
качестве
своей
модели
класс
JTextF
i
е
l d
использует
интерфейс
Documen
t.
Ниже
приведены
три
конструкто
ра
класса
JTextField.
JTextField(int столбцы} |
|
JTextField(String |
строка, |
JTextField(String |
строка} |
int
цвета}
Здесь
параметр
строка
обозначает
первоначально
предоставляемую
символь
ную
строку,
а
параметр
столбцы
-
количество
столбцов
в
текстовом
поле. Если
параметр
строка
не
задан,
то
текстовое
поле
оказывается
исходно
пустым.
А
если
не
задан
параметр
столбцы,
то
размеры
текстового
поля
выбираются
таким
об
разом, чтобы оно могло уместиться в указанной символьной строке.
Компонент типа JTextField генерирует события в ответ на действия
поль
зователя.
Например,
событие
типа
ActionEvent
наступает
при
нажатии
пользо
вателем
клавиши
<Enter>,
а
событие
типа
CaretEvent
-
при
каждом
изменении
позиции
каретки
(т.е.
курсора).
(Событие
типа
CaretEven
t
определяется
в
пакете
j
avax.
swing.
event.)
Возможны
и
другие события.
Как
правило,
эти
события
не
нужно
обрабатывать
в
прикладной
программе.
Вместо
этого
достаточно
получить
символьную
строку,
находящуюся
в
данный
момент
в
текстовом
поле.
Для
ее
полу
чения
следует
вызвать
метод
getText
().
В
приведенном
ниже
примере
прикладной
программы демонстрируется
при
менение
компонента типа
JTextField.
В
данной
программе
сначала
создается
компонент
типа
JTextField,
который
затем
вводится
на
панели
содержимого.
Когда
пользователь
нажимает
клавишу
<Enter>,
наступает
соответствующее
собы
тие
действия.
В
результате
обработки
этого
события
отображается
текст
в
окне
состояния,
как
показана
рис.
32.2.
//Продемонстрировать 11 типа JTextField
применение
компонента
import import import
java.awt.*; java.awt.event javax.swing.*;
.*;
puЬlic
class
JTextFieldDemo
puЬlic
JTextFieldDemo()
{
//установить
фрейм
средствами
класса
JFrame
JFrame jfrm = new |
JFrame("JTextFieldDemo"); |
jfrm.setLayout(new |
FlowLayout()); |
jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); |
|
jfrm.setSize(260, |
120); |
// ввести |
текстовое |
|
JTextField |
jtf |
= new |
jfrm.add(jtf); |
|
поле на панели содержимого JTextField(l5);
1212
Часть
111.
Введение
в
программирование
ГПИ
средствами
Swing
void void void void
setDisaЬledicon(Icon |
di) |
setPressedicon(Icon |
pi) |
setSelectedicon(Icon |
si) |
setRollovericon(Icon |
ri) |
Параметры
di,
pi,
si
и
ri
определяют
значки,
используемые
для
обозначе
ния
различных
состояний
экранной
кнопки.
Текст,
связанный
с
экранной
кнопкой,
можно прочитать и записать с помощью приведенных ниже
строка обозначает текст надписи на экранной кнопке.
методов,
где
параметр
String getText() |
|
void setText(String |
строка) |
Модель,
применяемая
во
всех
экранных
кнопках,
определяется
в
интерфейсе
But
tonModel.
Экранная
кнопка
генерирует
событие
действия,
когда
ее
нажимает
пользователь.
Возможны
и
другие события.
В
последующих
разделах
будут
под
робнее
рассмотрены
классы
отдельных экранных
кнопок.
Класс
JButton
В
классе
JBu
t
ton
определяются
функциональные
возможности
экранной
кнопки.
Простая
форма
конструктора
этого
класса
была
представлена
в
предыду
щей
главе.
Компонент
типа
JBut
ton
позволяет
связать
с
экранной
кнопкой
зна
чок,
символьную
строку
или
же
и
то
и
другое.
Ниже
приведены
три конструктора
класса
JBu
t ton,
где
параметры
значок
и
строка
обозначают
соответственно
значок
и строку,
используемые
для
представления
экранной
кнопки.
JButton(Icon значок) |
|
JButton(String |
строка) |
JButton(String |
строка, |
Icon
значок)
Когда
пользователь
нажимает
экранную
кнопку,
наступает
событие
типа
ActionEvent.
Используя
объект типа
ActionEvent,
передаваемый
мето
ду
actionPerformed
()
зарегистрированного
приемника
действий
типа
ActionListener,
можно
получить
символьную
строку
с
командой
действия,
связанной
с
данной
кнопкой.
По
умолчанию
эта
символьная
строка
отображается
в
пределах
экранной
кнопки.
Но
команду
действия
можно
также
задать,
вызвав ме
тод
setAct
ionCommand
()
для
экранной
кнопки.
А
получить
команду
действия
можно, вызвав метод getActionCommand объявляется следующим образом:
()
для
объекта
события.
Этот
метод
String
getActionCommand()
Команда
действия
обозначает
экранную
кнопку.
Так,
если
в
одном
приложении
используются
две
или
больше
экранных
кнопок,
команда
действия
позволяет
лег
ко
определить, какая именно кнопка была нажата. В предыдущей главе был представлен пример
применения
текстовой
кнопки.
А
в
приведенном
ниже
примере
прикладной
программы
демонстрируется
экран
ная
кнопка
в
виде
значка.
В
данном
примере
отображаются
четыре
экранные кноп
ки
и
одна
метка.
Каждая
кнопка
отображает
значок,
представляющий
разновид-
1228
Часть
111.
Введение
в
программирование
ГПИ
средствами
Swing
В
приведенном
ниже
примере
прикладной
программы
демонстрируется
приме
нение
простого
компонента
типа
JLi
s
t,
содержащего
список
городов.
Всякий
раз,
когда
из
этого
списка
выбирается
город,
наступает
событие
типа
ListSelection
Event, обрабатываемое методом
val
ueChanged
(),
определяемым
в
интерфей
се
ListSelectionListener.
Этот
метод
получает
индекс
выбранного
элемента
и
отображает
имя
выбранного
города
на
месте
метки.
На
рис.
32.9
показано,
как
город
выбирается
из
списка
в
окне
прикладной
программы
из
данного
примера.
11
Продемонстрировать
применение
компонента
типа
JList
import import import import
. |
. |
* |
; |
J avax. swing. |
|
||
javax.swing.event |
|||
java.awt.*; |
|
|
|
java.awt.event.*; |
.*;
puЬlic
class
JListDemo
11 создать массив |
|
String Cities [] |
= |
из
названий |
городов |
|
|
|
|
|
"New York", |
"Chicago", |
"Houston", |
||||
"Denver", |
"Los Angeles", |
"Seattle", |
||||
"London", |
"Paris", |
"New |
Delhi", |
|
||
"Hong Kong" , |
"Tokyo" , |
"Sydney" |
} ; |
puЬlic
JListDemo()
11
установить
фрейм
средствами
класса
JFrame
JFrame jfrm = new |
JFrame("JListDemo"); |
jfrm.setLayout(new |
FlowLayout()); |
jfrm.setDefaultCloseOperation(JFrame.EXIT |
|
jfrm.setSize(200, |
200); |
_ON_CLOSE);
11 создать список |
на |
JList<String> jlst |
= |
основе компонента типа JList
new JList<String>(Cities);
11
задать
режим
выбора единственного
элемента
из
списка
jlst.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
11
ввести список
на
панели
с
полосами
прокрутки
JScrollPane
jscrlp
=
new
JScrollPane(jlst);
11 |
задать предпочтительные |
размеры панели |
|
11 |
с полосами прокрутки |
|
Dimension(120, |
jscrlp.setPreferredSize(new |
90)
);
11 создать метку |
для отображения |
JLabel jlab = new |
JLabel("Choose |
выбранного а City");
города.
11
ввести
приемник
событий выбора
элементов
из
списка
jlst.addListSelectionListener(new ListSelectionListener() |
|
puЬlic void valueChanged(ListSelectionEvent le) |
{ |
11
получить
индекс
измененного
элемента
int
idx
=
jlst.getSelectedindex();
11
отобразить
сделанный
выбор,
если
элемент
Глава
33.
Введение
в
меню
Swing
1261
нять, что мещается
в данном случае по центру.)
применяется
граничная
компоновка,
а
метка
j
lab
раз
Далее введите Debug (Отладка):
следующий
фрагмент
кода
для
создания
панели
инструментов
11
создать
панель
инструментов
Debug
JToolBar
jtb
=
new
JToolBar("Debug");
11
загрузить
изображения
значков
экранных
кнопок
Imageicon
Imageicon
Imageicon
set = clear resume
new Imageicon("setBP.gif"); |
|
= new |
Imageicon("clearBP.gif"); |
= new |
Imageicon("resume.gif"); |
//
создать
кнопки
для
панели
инструментов
JButton jbtnSet = new JButton(set);
jbtnSet.setActionCommand("Set Breakpoint"); jbtnSet.setToolTipText("Set Breakpoint");
11
Установить
точку
прерывания
JButton jbtnClear = new JButton(clear); jbtnClear.setActionCommand("Clear Breakpoint");
jbtnClear.setтoolTipText("Clear
Breakpoint");
11
Очистить
точку
прерывания
JButton
jbtnResume
=
new
JButton(resume);
jbtnResume.setActionCommand("Resume"); jbtnResume.setToolTipText("Resume");
11
Возобновить
выполнение
программы
/! ввести экранные |
кнопки |
jtb.add(jbtnSet); |
|
jtb.add(jbtnClear); |
|
jtb.add(jbtnResume); |
на
панели
инструментов
/! ввести панель инструментов |
в северном |
|
//на панели |
содержимого |
|
jfrm.add(jtb, |
BorderLayout.NORTH); |
расположении
Рассмотрим
подробнее
приведенный
выше
фрагмент
кода.
Сначала
в
нем
соз
дается
панель
инструментов
в
виде
объекта
типа
JToolBar,
и
ей
присваивается
заголовок
"Debug".
Затем
создается
ряд
объектов типа
Image
I
con
для
хранения
изображений
значков
экранных
кнопок
на
панели
инструментов.
Далее
создаются
три
экранные
кнопки
для
панели
инструментов,
причем
у
каждой
из
них
имеется
свой
значок
вместо
текстовой
надписи.
Кроме
того,
для
каждой
экранной
кнопки
явным
образом
задается
команда
действия
и
всплывающая
подсказка.
Команды
действия
задаются
потому,
что
экранным
кнопкам
не
присваиваются
имена при
их
создании.
Всплывающие
подсказки
особенно
удобны
для
компонентов,
пред
ставленных
только
значками
на
панели
инструментов,
поскольку
не
всегда
удается
оформить
такие
значки,
которые
интуитивно
понятны
всем
пользователям.
После
этого
экранные
кнопки
вводятся
на
панели
инструментов,
а
сама
панель
-
на
се
верной
стороне
граничной
компоновки
фрейма.
Глава
33.
Введение
в
меню
Swing
1265
Продемонстрируем
преимущества
действий
на
примере
управления
созданной
ранее
панелью
инструментов
Debug
в
рассматриваемом
здесь
примере
программы
MenuDemo.
Для
этого
меню
Options
будет
дополнено
подменю
Debug
со
следующими
пунктами,
аналогичными
кнопкам
выбора
режимов
отладки
на
панели
инструмен
тов
Debug:
Set
Breakpoint
(Установить
точку
прерывания),
Clear
Breakpoint
(Очистить
точку
прерывания)
и
Resume
(Возобновить
выполнение).
Одни
и
те
же
действия
бу
дут
померживать
как
пункты
в
подменю
Debug,
так и
кнопки
на
одноименной
па
нели
инструментов.
Следовательно,
вместо
того
чтобы
писать
дублирующийся
код
управления
подменю
и
панелью
инструментов
Debug
по
отдельности,
достаточно
организовать
действия,
которые
будут
управлять
обоими
этими
элементами
ГПИ.
Итак,
создайте
сначала
внутренний
класс
DebugAct
ion,
расширяющий
класс
AbstractAction
и
приведенный
ниже.
11 Класс действий
class DebugAction
для подменю и панели инструментов extends AЬstractAction {
Debug
puЬlic DebugAction(String name, |
Icon |
image, |
int |
mnem, |
int accel, String |
tTip) |
{ |
|
|
super(name, image); |
|
|
|
|
putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke( |
accel,
InputEvent.CTRL_DOWN_МASK));
putValue(МNEMONIC_KEY, new putValue(SHORT_DESCRIPTION,
Integer(mnem));
tTip);
11 11
обработать события как так и в подменю Debug
на
панели
инструментов,
puЬlic void actionPerformed(ActionEvent String comStr = ae.getActionCommand();
ае)
jlab.setText(comStr
+"
Selected");
11
Выбрано
указанное
11 11
изменить |
разрешенное |
состояние вариантов выбора |
режимов |
установки и |
очистки точек прерывания |
i |
f |
(
comStr.
equals
(
"Set
Breakpoint")
) |
{ |
clearAct.setEnaЫed(true); setAct.setEnaЫed(false);
else
if(comStr.equals("Clear Breakpoint")) |
{ |
clearAct.setEnaЫed(false); setAct.setEnaЫed(true);
В
Приведенный выше класс DebugAction расширяет класс AbstractAction.
итоге получается класс действия, предназначенный для определения свойств,
связанных
с
подменю
и
панелью
инструментов
Debug.
Его
конструктор
принимает
пять
параметров,
позволяющих
указать
следующие
элементы.
• • •
Имя. Значок. Мнемоника.
ГЛАВА 34
Введение
в
JavaFX
Как
и
все
удачно
разработанные
языки
программирования,
Java
продолжает
раз
виваться
и
совершенствоваться.
И
это
относится
к
его
библиотекам.
Характерным
примером
такого
развития
служат
библиотеки
(или
так
называемые
каркасы)
для
по
строения
ГПИ.
Как
пояснялось
ранее
в
данной
книге,
первоначально
для
построе
ния
ГПИ
была
разработана
библиотека
AWT.
Но
в
силу
ряда
присущих
ей
ограниче
ний
вскоре
была
разработана
библиотека
Swing,
предлагавшая
более
совершенный
подход
к
построению
ГПИ
.
Эта
библиотека
оказалась
настолько
удачной,
что
до
сих
пор
остается
основной
в
Java
для
построения
ГПИ
.
И
скорее
всего,
она
таковой
оста
нется
еще
долго,
несмотря
на
быстро
меняющую
ситуацию
в
области
программиро
вания!
Тем
не
менее
библиотека
Swing
была
создана
в
то
время,
когда
в
разработке
программного
обеспечения
господствующее
положение
занимали
корпоративные
приложения.
А
ныне
особое
значение
приобрели
потребительские
приложения,
особенно
для
мобильных
устройств.
И
от
таких
приложений
зачастую
требуется
ви
зуальная привлекательность. |
Более того, наметилась общая тенденция |
к наделению |
приложений, независимо от |
их типа, захватывающими визуальными |
эффектами. |
Поэтому с учетом этой тенденции потребовался новый подход к построению ГПИ, |
||
что и привело к разработке библиотеки JavaFX. Она стала новым поколением плат |
формы
и
библиотеки
для
построения
ГПИ
клиентских приложений
в
Java.
JavaFX
служит
эффективным,
рациональным,
удобным
каркасом
для
построе
ния
современных
визуально
привлекательных
ГПИ,
а
следовательно,
это
довольно
крупная
система,
которую,
как
и
Swing,
просто
невозможно
описать
полностью
в
рамках
данной книги.
Поэтому в
этой
и двух
последующих
главах
представлены
лишь
основные средства
и
способы
построения
ГПИ
на
основе
JavaFX.
Овладев
этими
основами,
вы
сможете
без
особого
труда
самостоятельно
изучить
осталь
ные |
особенности JavaFX. |
В |
связи с появлением |
JavaFX
возникает
следующий
вполне
резонный
вопрос:
служит
ли
JavaFX
в
качестве
замены
Swing?
Определенно
служит.
Но,
принимая
во
внимание
немалый
объем
унаследованного
кода,
а
также
огромную
армию
специа
листов,
умеющих
разрабатывать
приложения
на
основе
библиотеки
Swing,
она
еще
нескоро
выйдет
из
употребления.
И
это
особенно
касается
корпоративных
прило
жений.
Тем
не
менее
JavaFX
была
ясно определена
как
перспективная
платформа.
Ожидается,
что
через
несколько
лет
JavaFX
полностью
вытеснит
Swing
для
раз-
Глава
34.
Введение
в
JavaFX
1295
типа
GraphicsContext.
Полученным
в
итоге
графическим
контекстом
типа
GraphicsContext
можно
затем
воспользоваться
для
рисования
выводимых
гра
фических
данных
на
холсте.
Класс
Canvas
является
производным
от
класса
Node,
а
следовательно,
им
можно
пользоваться
как
узлом
в
графе
сцены.
В
классе
Canvas
определяются
два
конструктора.
Одним
из
них
является
конструктор
по
умолчанию,
а
другой
при
веден
ниже,
где
параметры
ширина
и
высота
обозначают
соответствующие
раз
меры
холста.
Canvas(douЫe |
ширина, |
douЫe
высота)
Чтобы
получить
графический
контекст
типа
GraphicsContext,
ссылающий
ся
на
холст,
следует вызвать
метод
getGraphicsContext2D
().Ниже
приведена
общая
форма
данного метода.
Он
возвращает
графический
контекст
для
холста.
GraphicsContext
getGraphicsContext2D()
В
классе
GraphicsContext
определяется
немало
методов
для
рисования
форм,
воспроизведения
текста
и
изображений,
а
также
для
поддержки
визуаль
ных
эффектов
и
графических
преобразований.
Если
вы
связываете
свое
будущее
с
программированием
сложной
графики,
вам
определенно
следует
внимательно
изучить
возможности
этого
класса.
В
целях
демонстрации
далее
будут
использова
ны
лишь
некоторые
методы
из этого
класса,
хотя
и
они
дают
ясное
представления
об его огромном потенциале. Эти методы вкратце описываются далее.
Вызвав метод strokeLine (),можно нарисовать линию. Ниже приведена
об
щая
форма
этого
метода.
void
strokeLine(douЫe douЫe
начало_Х, |
douЫe |
начало_У, |
конец_Х, |
douЫe |
конец_У) |
Этот
метод
рисует
линию
от
точки
с
указанными
координатами
начало_Х,
начало_
У
к
точке
с
указанными
координатами
конец_Х,
конец_У,
используя
те
кущую
обводку,
которая
может
быть
выполнена
сплошным
цветом
или
оформлена
в более сложном стиле.
Чтобы нарисовать прямоугольник, необходимо или fillRect ().Ниже приведены общие формы
вызвать метод этих методов.
strokeRect
()
void void
strokeRect (douЫe |
верх_Х, |
douЫe |
верх_ У, |
|||
douЫe |
ширина, |
douЫe |
высота) |
|||
fillRect(douЫe |
верх_Х, |
douЫe |
верх_У, |
|||
douЫe |
ширина, |
douЫe |
высота) |
Параметры
координат
верх_Х,
верх_У
обозначают
левый
верхний
угол
ри
суемого
прямоугольника,
параметры
ширина
и
высота -
его
ширину
и высоту
соответственно.
Метод
strokeRect
()
рисует
контур
прямоугольника,
исполь
зуя
текущую
обводку,
а
метод
fillRect
()
заполняет
площадь
прямоугольника
текущей заливкой: сплошным |
цветом или более сложным рисунком. |
Чтобы нарисовать эллипс, |
следует вызвать метод strokeOval |
()
или
fill
Ov
а
l
( ) .
Ниже
приведены
общие
формы
этих
методов.
ГЛАВА 35
Элементы управленияJаvаFХ
к
В предыдущей главе были рассмотрены основные понятия, имеющие отношение построению ГПИ средствами JavaFX. По ходу их описания были представлены два
элемента
управления
:
метка
и
экранная
кнопка
.
А
в
этой
главе
будет
продолжено
рассмотрение
элементов
управления
JavaFX.
В
начале
главы
поясняется,
каким
обра
зом
метка
и
экранная
кнопка
снабжаются
изображениями.
Затем
дается
краткий
об
зор
некоторых
других
элементов
управления
JavaFX,
в
том
числе
флажков,
списков
и
деревьев
.
Следует,
однако,
иметь
в
виду,
что
JavaFX -
насыщенный
функциональ
ными
возможностями
и
довольно
мощный
каркас.
Поэтому
основное
назначение
этой
главы
-
представить
наиболее
употребительные
элементы
управления
JavaFX
и
описать
некоторые
общие
приемы
их
применения.
Овладев
основами,
вы
сможете
без
особого
труда
самостоятельно
изучить
остальные
элементы
управления
JavaFX.
Ниже
перечислены
классы
элементов
управления JavaFX,
обсуждаемые
в этой
главе.
Классы
этих
и
других
элементов
управления
JavaFX
входят
в
состав
пакета
j
ava
f
x.
s
c
e
ne.
cont
r
ol
.
Button
CheckBox
Label
ListView
RadioButton
ScrollPane
TextField
ToggleButton
Treeview
В этой главе обсуждаются также классы I mage
ющие изображения в элементах управления; класс
и ImageVi ew, поддержива
Тоо l t ip, предназначенный
для ввода всплывающих подсказок в элементы
зуальные эффекты и преобразования.
управления;
а
также
различные
ви
Классы
Image и
ImageView
Изображениями
можно
снабдить
целый
ряд
элементов
управления
JavaFX.
Так
,
помимо
текстовой
надписи
,
изображением
можно
снабдить
метку
или
экранную
кнопку.
Более
того,
изображения
можно
встраивать
непосредственно
в
сцену
как
автономные
графические
объекты.
Основу
поддержки
изображений
в
JavaFX
со
ставляют
два
класса:
Im
age
и
Ima
geView
.
В
частности,
класс
Ima ge
инкапсули
рует
само
изображение,
а
класс
ImageView
управляет
его
воспроизведением.
Оба
эти
класса
входят
в
состав пакета
j
avaf x.
sce
n e
.
imag
e .
|
|
|
|
|
|
Глава 35. Элементы управления JavaFX |
||||
// |
создать сцену |
|
|
|
|
|
|
|
|
|
Scene myS c ene |
= new |
Scene(rootNode, |
220 , 120); |
|||||||
//установить |
сцену |
на |
подмостках |
|
|
|
||||
myStage.setScene(myScene); |
|
|
|
|
|
|||||
// |
создать метку |
|
|
|
|
|
|
|
|
|
response = new |
Labe l |
("Push |
the |
Button . |
" ); |
|||||
|
11 |
Нажать |
кнопку |
|
|
|
|
|
||
// |
создать переключатель |
|
|
|
|
|
||||
tbOnOff = new |
ToggleButton( |
"On/Off"); |
|
|||||||
|
/! Включить / |
Выключить |
|
|
|
|
||||
//обработать |
события |
действия |
от |
переключателя |
||||||
tbOnOff . setOnAction(new Event Handle r |
<ActionEvent>() |
|||||||||
|
puЬlic v o id |
handle(ActionEvent |
ае) |
{ |
|
|||||
|
if(tbOnOff.isSelected()) |
|
|
|
|
|||||
|
response.setText("Button |
is |
on |
. "); |
||||||
|
|
// |
Переключатель |
нажат |
|
|
||||
|
else |
|
|
|
|
|
is |
off. |
" ); |
|
|
response.setText("Button |
|||||||||
|
|
// |
Переключатель |
отпущен |
|
|||||
|
} |
|
|
|
|
|
|
|
|
|
} ) |
; |
|
|
|
|
|
|
|
|
|
// |
ввести метку и |
переключатель |
в |
граф |
сцены |
|||||
rootNode.getChi l dren() |
.addAll(tbOnOff, |
response); |
||||||||
11 |
показ ать подмо |
с тки |
и сцену на |
них |
|
|
||||
myStage. show () |
; |
|
|
|
|
|
|
|
|
1311
На
рис.
35.6
по
казан
вид
нажатого
переключателя
в
окне
JаvаFХ-приложения
из
данного
примера
.
1
Oemonstr~te
~
.•
Button
is
on.
в
Рис. 35.б. Вид нажатого переключателя окне JаvаFХ-приложения ToggleBut tonDemo
Обр
а
тите
в
данном
пример
е
внимание
на
определение
состояния
нажатого
или
отпущенного
пере
ключат
е
ля
.
Это
дела
е
тся
в
следующи
х
строках
кода
из
обработ
чика
событий
действия
от
перек
л
юч
а
теля
:
if(tbOnOff.isSelected()) response.setText("Button else response. setText ( " Butt o n
is
is
on off
. .
" ); ");
Глава
35.
Элементы
управления
JavaFX
1317
Эта
версия
JаvаFХ-приложения
действует
таким
же образом,
как
и
предыду
щая.
Всякий
раз,
когда
выбирается
кнопка-переключатель,
обновляется
метка
re-
sponse.
Но
в
данном
случае
в
группу
кнопок-переключателей
требуется
ввести
лишь
один
обработчик
событий
вместо
трех
для
каждой
кнопки-переключателя
в
отдельности.
А
теперь
рассмотрим
подробнее
приведенный
выше
фрагмент
кода.
Сначала
в
этом
фрагменте
кода
регистрируется
приемник событий
изменения
в
группе
кнопок-переключателей.
Чтобы
принимать
события
изменения,
следует
реализовать
интерфейс
ChangeListener.
С этой
целью
вызывается
метод
ad-
dListener ()
для
объекта,
возвращаемого
методом
selectedTogglePro-
perty
().
В
интерфейсе
ChangeListener
определяется
единственный
метод
changed
().Ниже
приведена
его
общая
форма.
void
changed(ObservaЬleValue<? extends Т> изменение,
т прежнее_значение, Т новое_значение)
Здесь
параметр
изменение
обозначает
экземпляр
интерфейса ObservaЬle
Value<T>,
инкапсулирующего
объект,
в
котором
наблюдаются изменения,
а
па
раметры
прежнее_значение
и
новое_значение
-
предыдущее
и
следующее
значения
соответственно.
Таким
образом,
параметр
новое_значение
содержит
ссылку на только что выбранную кнопку-переключатель.
В данном примере для установки первоначально выбираемой
кнопки-переклю
чателя
вызывается
метод
setSelected
(),а
не
f
ire
().А
поскольку
такая
уста
новка
вызывает
изменение
в
группе
кнопок-переключателей,
то
когда
приложение
из
данного
примера
начинает
выполняться,
генерируется
событие
изменения.
Для
установки первоначально
выбираемой
кнопки-переключателя
можно
было
бы
вы
звать
и
метод
f
ire
(),но
вместо
него
был
выбран
метод
setSelected
(),чтобы
продемонстрировать
то
обстоятельство,
что
при
любом
изменении
в
группе
кно
пок-переключателей
генерируется
событие
изменения.
Другой
способ
управления
кнопками-переключателями
Несмотря
на
всю
пользу
от
обработки
событий,
генерируемых
кнопками-пере
ключателями,
иногда
удобнее
просто
проигнорировать
события
от
них
и
получить
выбранную
в
настоящий
момент
кнопку-переключатель,
когда
такая
информация
потребуется.
Именно
такой
способ
демонстрируется
в
приведенном
ниже
приме
ре.
Это
переделанный
вариант
предыдущего
примера,
где
дополнительно
введена
кнопка
Confirm
Transport Selection
(Подтвердить
выбор
транспортного
средства).
После
щелчка
на
этой
кнопке
сначала
получается
выбранная
в
настоящий
момент
кнопка-переключатель,
а
затем
на
месте
метки
отображается
подтвержденный
результат
выбора
транспортного
средства.
Опробуя
JаvаFХ-приложение
из дан
ного
примера,
обратите
внимание
на
то,
что
изменение
в
выбираемой
кнопке-пе
реключателе
не
влечет
за
собой
изменение
подтвержденного
результата
выбора
транспортного
средства
до
тех
пор,
пока
не
будет
нажата
кнопка
Confirm
Transport
Selection.
11 11
В этом примере |
применения |
демонстрируется |
получение |
кнопок-переключателей кнопки-переключателя,
1318
Часть
IV.
Введение
в
программирование
ГПИ
средствами
JavaFX
//
выбранной |
в |
текущий
момент
из
группы,
под
управлением
//программы, когда |
в этом |
возникает |
потребность, |
//реагирования на |
события |
действия |
или изменения. |
11 |
|
|
11 В данном примере события, |
связанные с |
|
//кнопками-переключателями, |
не обрабатываются. |
|
//Вместо этого просто получается выбранная |
в |
вместо
//
данный
момент
кнопка-переключатель,
когда
//нажимается
экранная
кнопка
Confirm
Transport Selection
import import import import import import import
javafx.application.*; javafx.scene.*; javafx.stage.*; javafx.scene.layout.*; javafx.scene.control.*; javafx.event.*; javafx.geometry.*;
puЬlic
class
RadioButtonDemo2
extends
Application
{
Label response; ToggleGroup tg;
puЬlic
static
void
main(String[]
args)
// запустить launch(args);
JаvаFХ-приложение,
вызвав
метод
launch()
11 переопределить метод
puЫic void start(Stage
start() myStage)
//присвоить заголовок подмосткам
myStage.setTitle("Demonstrate Radio
Buttons");
11
Продемонстрировать
кнопки-переключатели
//Использовать
панель
поточной
компоновки
11 типа FlowPane в
//В данном случае
качестве корневого |
узла. |
|
- |
с промежутками 10 |
|
11 по вертикали и
FlowPane rootNode
по |
горизонтали |
= |
new FlowPane(lO, |
10);
// выровнять элементы управления по rootNode.setAlignment(Pos.CENTER);
центру
сцены
//создать сцену |
|
|
Scene myScene |
= new |
Scene(rootNode, |
//установить |
сцену |
на подмостках |
myStage.setScene(myScene); |
200,
140);
// создать |
две |
метки |
|||
Label |
choose = |
new |
|
Label( |
|
|
|
Select |
а |
Transport |
Туре |
"); |
//Выбор
транспортного
средства
Глава
35.
Элементы
управления
JavaFX
1327
final
MultipleSelectionModel<T>
getSelectionModel()
Этот
метод
возвращает
ссылку
на
модель.
В
классе
Mu
l |
t |
ip
l
eSe
l
е
с
t
i
onMode
l
определяется
модель,
применяемая
для
одновременного
выбора
нескольких
эле
ментов
из
списка.
Этот
класс
наследует
от
класса
SelectionModel.
Но
одновре
менно
выбирать
несколько
элементов
из списка,
представленного
объектом
типа
ListView,
можно
только
в
том
случае,
если
активизирована
модель,
поддержива
ющая
такой
режим
выбора.
Используя
модель,
возвращаемую
методом
getSelectionModel
(),можно
по
лучить
ссылку
на
свойство
элемента,
выбранного
из
списка.
Это
свойство
определя
ет
событие,
происходящее
при
выборе
элемента
из
списка.
С
этой
целью
вызывается
метод
selecteditemProperty
(),общая
форма
которого
приведена
ниже.
К
по
лученному
в
итоге
свойству
присоединяется
приемник
событий
изменения.
final ReadOnlyObjectProperty<T>
selecteditemProperty()
Все
сказанное
выше
о
представлении
списка
демонстрируется
в
приведенном
ниже
примере.
В
частности,
в
этом
примере
создается
представление
списка, ото
бражающее различные виды транспортных средств, которые пользователь выбрать из списка. Результат выбора отображается на месте метки.
может
//Продемонстрировать
применение
представления
списка
import import import import import import import import
javafx.application.*; javafx.scene.*; javafx.stage.*; javafx.scene.layout.*; javafx.scene.control.*; javafx.geometry.*; javafx.beans.value.*; javafx.collections.*;
puЬlic
class
ListViewDemo
extends
Application
{
Label |
response; |
|
|
|
puЬlic |
static |
void |
main(String[] |
args) |
11 запустить |
JаvаFХ-приложение, |
вызвав |
||
launch (args) |
; |
|
|
метод
launch()
11 переопределить метод
puЬlic void start(Stage
start() myStage)
11 |
присвоить заголовок |
подмосткам |
myStage.setTitle("ListView Demo"); |
||
|
11 Демонстрация |
представления |
списка
11
Использовать
панель поточной
компоновки
//типа
FlowPane
в
качестве
корневого
узла.
11
В
данном
случае
-
с
промежутками 10
// по вертикали и
FlowPane rootNode
по горизонтали
= new FlowPane(lO,
10);
1350
Часть
IV.
Введение
в
программирование ГПИ
средствами
JavaFX
центре
можно,
вызвав
метод
setRotate
()
и
передав
ему
требуемое значение
угла;
задать
масштаб,
-
вызвав
методы
setScaleX
()
и
setScaleY
(),
а
пере
местить
узел,
-
вызвав
методы
setTranslateX
()
и
setTranslateY
().Но
на
много
удобнее
пользоваться
списком
преобразований,
как
будет
продемонстриро
вано
далее.
На
заметку! Любые преобразования, указанные для после всех преобразований из списка.
узла
непосредственно,
будут
выполняться
только
и
Для демонстрации преобразований далее будут использованы классы Rotate Scale. Аналогичным образом выполняются и остальные преобразования. В клас
се
Rotate
поддерживается
вращение
узла
вокруг
указанной
точки.
У
этого
класса
имеется
несколько конструкторов.
Ниже
в
качестве
примера
приведен
один
из
них.
Rotate(douЫe
угол,
douЫe
х,
douЫe
у)
Здесь
параметр
угол
обозначает
количество
градусов,
на
которое
следует
повер
нуть
узел,
а
центр
вращения,
иначе
называемый
точкой
вращения,
определяется па
раметрами
х
и
у.
Все
эти
параметры
вращения
можно
установить
и
после
создания
объекта
типа
Rota
te
с
помощью
конструктора
по
умолчанию,
как
демонстрируется
в
приведенном
далее
примере.
Для
этой
цели
достаточно
вызвать
методы
setAn-
gle
(),
setPi
votX
()
и
setPi
votY
(),
общие
формы
которых
приведены
ниже.
Как и
прежде,
параметр
угол
обозначает
количество
градусов,
на
которое
следует
повернуть
узел,
а
центр
вращения
определяется
параметрами
х
и
у.
final final final
void void void
setAngle(douЫe |
угол) |
setPivotX(douЫe |
х) |
setPivotY(douЫe |
у) |
В
классе
Scale
поддерживается
масштабирование
узла
по
указанному
мас
штабному
коэффициенту.
В
этом
классе
определяется
несколько
конструкторов.
Ниже
приведен
применяемый
далее
конструктор.
Scale(douЫe
масштаб_по_ширине,
douЫe
масштаб_по_высоте)
Здесь
параметр
масштаб_по_ширине
обозначает
коэффициент
для
масшта
бирования
узла
по
ширине,
а
параметр
масштаб_по_высоте
-
коэффициент
для
его
масштабирования
по
высоте.
Эти
масштабные
коэффициенты
можно
изме
нить
после
создания
экземпляра
класса
Scale,
вызвав
методы
setX
()
и
setY
(),
общие
формы
которых
приведены
ниже.
Как
и
прежде,
параметр
масштаб_по_
ширине
обозначает
коэффициент
для
масштабирования
узла
по
ширине,
а
пара
метр
масштаб_по_высоте
-
коэффициент
для
его
масштабирования
по
высоте.
final final
void void
setX(douЫe setY(douЫe
масштаб_по_ширине) масштаб_по_высоте)
Демонстрация
эффектов
и
преобразований
В
приведенном
ниже примере демонстрируется
применение
эффектов
и
вы
полнение
преобразований.
С
этой
целью
создаются
четыре
экранные
кнопки: