Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
92
Добавлен:
30.03.2021
Размер:
42.12 Mб
Скачать

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

= р;

 

email

=

е;

 

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

масштаб_по_ширине) масштаб_по_высоте)

Демонстрация

эффектов

и

преобразований

В

приведенном

ниже примере демонстрируется

применение

эффектов

и

вы­

полнение

преобразований.

С

этой

целью

создаются

четыре

экранные

кнопки:

Соседние файлы в папке Лабораторные работы (Объектно-ориентированное программирование (ООП))