Переключатели и флажки

В

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

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

В конце главы находится краткое описание того, как добавить в язык Java аналог перечислимого типа. Эта техника несколько сложна для понимания, но ее легко ис­пользовать в программах. Я включил ее в эту главу, потому что считаю, что она осо­бенно полезна при работе с переключателями.

Это первая из последовательности глав, содержащих большое количество прак­тической работы в конструкторе JBuilder. Если вы только начинаете работать в Java или JBuilder, то я настоятельно рекомендую воссоздавать описываемые мною про­граммы по памяти. Я понимаю, что такая работа приносит мало удовольствия, од­нако если вы сможете создать некоторые из этих программ без периодического загля­дывания в книгу, то список ваших профессиональных качеств заметно увеличится.

Я специально стараюсь показать вам возможности, которые будут нужны вам чаще всего. Если вы дойдете до того, что выполнение многих из этих вещей станет у вас рефлекторным, то эти привычки еще не раз пригодятся вам в дальнейшем. Я по­нимаю, что чаще всего перед вами стоит конкретная задача, которую вы пытаетесь решить. Но если вы потратите время на глубокое освоение основных компонентов Java, то будете получать от программирования на Java с помощью JBuilder гораздо больше удовольствия, нежели в том случае, когда будете постоянно обдумывать или разыскивать в справочниках каждый свой шаг.

Создание приложений с переключателями и флажками

Начнем с построения простого приложения, показанного на рис. 16.1. Этот про­ект ознакомит вас с основными приемами работы с флажками и переключателями Флажки и переключатели, применяемые в программе, позволяют пользователю из­менять цвет управляющих элементов в графическом интерфейсе.

Программа, к созданию которой мы сейчас приступим, называется ColorChooser. Вы можете найти ее копию сопровождающих книгу материалах.

Сначала с помощью подхода, описанного в главе 3, создайте стандартное прило­жение JBuilder. После создания приложения в панели содержимого выделите

Frame1 .java. Щелкните на закладке Design внизу панели содержимого, чтобы переключиться в режим конст­руирования.

Щелкните на закладке Swing Containers в палитре компонентов.

Выберите компонент JPaneI и щелк­ните в центре конструктора. C помо­щью инспектора установите цвет JPaneI в Black (черный), а свойство layout — в null Свойство constraints должно быть установлено в Center, как показано на рис. 16.2.

рис. 16.1. простое приложение, демонстрирующее применение флажков и переключателейпримечаниеВообще говоря, компо­новка Null очень полезна при конструировании GUI-интерфейсов. Но после завершения конструирования, перед созданием инсталляции вашего приложения или аплета, необхо­димо переключиться на другую компоновку. Как это сделать, описано в главах 12 и 13. В нашем случае, после того как вы с помощью пустой компоновки создадите базовый вид Приложения, потребуется переключиться на компоновку GridBagLayout.

Палитра компонентов должна быть все еще открыта на странице Swing Containers. Выберите компонент JColorChooser (слева от пиктограммы с изображе­нием папки), щелкнув на нем. Затем щелкните на папке Ul в панели структуры. Если компонент JColorChooser появится в конструкторе, удалите его и повторите все снова. Панель структуры должна содержать пунктирную линию от папки Ul к компоненту JColorChooser, как показано на рис. 16.3.

⅛⅜j∣!∣f∣j⅛Hwιuιjmm⅛ι∣’∣

FHe Idll (Search Jflew ProHstf Run Team Wjwde Teow Jjflneow метр.

О α S- % В E⅛ — * — √- » ¾ »I ».*>• j > •» — <* — ~

KiiSiFramei

⅛je⅛⅛
■ ⅛ s3 ■■■
∙.λ., ∙i 
"р colorchooserjpx j s3 ⅛l «project source»
:j ⅛ θl colorchooser ∙∙r 4» colorchooserjava

к 9n⅛⅞ swingcortainer* (imeeqjreesjaswtrb | ifciredbswire | skswinemodrtj ihormtbwm i xkljjj * лпавгатп. rɪ-. _ - ., 4ssn≈1 s ι

,p⅜neι

colorchooserframei i ⅛i lj ui j eqthis
j i⅛ pi contentpane ( «г borderlay
border _ , ,,
debugorephit
(joubiebuthed
enabled
font
*ββfttm>λ⅛
3⅛~~~-~
jmenu j dataaccess j other
fflslfflffil.*1,properties)[evens
,’а
sourc⅝ umt doelhistory
design
jpanβιtк.206 у 253

A)⅛Br⅝rn⅛πiγ

Рис. 16.2. B Панели структуры видно, что JPanelРасположена на ContentPane.
Используется пустая компоновка

рис. 16.3. компонент jcolorchooser должен быть помещен не на contentpane, а на узел ul он будет использоваться как невизуальный компонент f⅛e ξd; geerejɪ yw* β⅛)gcl run tegm 4te⅛ ħ i
« ⅛ в it
,йк,j cotorchooserjpk ; ф «project source*
; ф cotorchooser a colorchoosbrlava
abbtff¾b⅞j

Следующим шагом будет размещение на JPaneI четырех переключателей. Пере­ключатели находятся на странице Swing палитры компонентов Щелкните на ком­поненте JRadioButton, удерживая нажатой клавишу Shift. После этого щелкните на конструкторе. Каждый раз после щелчка на конструкторе будет добавляться новый переключатель. Между щелчками сдвигайте курсор вниз, чтобы кнопки выстраивались в колонку Щелкните на стрелке выбора (белая стрелка в левой части палитры компо­нентов), чтобы закончить эту операцию. Назовите компоненты jRadioButtonBlue, jRadioButtonGreen, JRadioButtonRed и JRadioButtonAII Заголовки (свойство text) этих четы­рех кнопок должны принять значения Синий, Зеленый, Красный и Все цвета.

Для выстраивания переключателей в колонку щелкните на всех них по очереди, удерживая нажатой клавишу Ctrl. Маркеры растяжки переключателей изменят свой цвет, указывая, что они выбраны. Щелкните правой кнопкой мыши на переключа­телях и в появившемся контекстном меню выберите пункты Align Left (Выровнять влево) и Even Space Vertical (Равные промежутки по вертикали). Результат должен по­лучиться похожим на показанный на рис. 16.4.

На обоих концах палитры компонентов есть стрелки, пользуясь которыми, ее можно прокручивать влево или вправо. Если необходимо, с помощью такой стрелки сдвиньте палитру компонентов вправо, пока не увидите пиктограмму группы пере­ключателей. Щелкните на этой пиктограмме, а затем на конструкторе. Группа пере­ключателей не является визуальным компонентом, так что вы не увидите ее в пане­ли конструктора, но она появится в панели структуры под именем buttonGroup1. После добавления группы переключателей в выпадающем списке инспектора рядом со свойством buttonGroup появится строка buttonGroup1. Установите свойство buttonGroup каждого переключателя в buttonGroup1, как показано на рис. 16.5.

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

В данной программе не стоит делать один из переключателей выбранным по умолчанию. Но вообще это можно сделать, установив в инспекторе свойство selected одного из них равным True Пример такого выбора приведен в демонстра­ционной программе в конце этой главы.

c' j aujw<tf 7,file edll search view proiect run team wizards iools window help d $£$♦ ¾h ð '4fr <>'⅛ ⅛ ft jt⅜f0>eβ∣neame
⅛*⅜tr⅛ *■. ⅜i* ∙ . .4 ...... 
,lpj & & й ⅛p unwed.. ’ ×⅛ coiorchoosf kj⅛ framat ∣
t t⅛ 5w*1β ,swhecontahm* iomteexprwte i obswho i mbeobswha i obswhomodtj jjjj
,= ;£ ■» «project source* ⅛ o colorchooser ■ =& cnloohooserjava & ,colorchooserframel sjs-=jjui 4 = s elthls j i ∙ β «null*
j ■ ∙ *5iil
■j i ■ ⅛⅛ jradiobuttonaii
-j i .∙ * jradiobuttonred
* *⅛ jradiobuttongreen j i - =.,i menu .i j--jdataaccess
i ■ _l other
,£ ∏⅛r 4fe,umvi dot,rr∙∙∙j o⅛=, - ■
name
kmthlaftli jradiobuttonbiue null 
buttongroiv 5∏pne* 
action 
actioncommanr, blue
acflonmap 
alignment×
ailgnmenty ос
0.5
background-
border o 217.2t7.233 . qθfhp.9uh0 border

,properties if □nts
рис. 16.4.
переключатели выстроены в колонку

Следующим шагом будет помещение еще трех компонентов JTextField. Они находятся на странице Swmg палитры компонентов. Выровняйте в конструкторе

Ft.∙π Refactorlng completed

,RadioBuflonBlue к 88 ⅛r 46

Л Guilder 7 G:.’src/ьп KJV∂∕<j, kιnt⅛lcd5∕CoiorChoυs’cr4r<∕cQtorchθOl>’*r∕FrAΠjei j>∙.

Me EtM Jgearoh View Project Run Tegm Wfterds Tools Window fctelp s Lfe—r.

Dtf^<s∙¾bβ√∣^ * ‰β^У………………………….. ,. ⅛∙4⅛f>∙*

x .& framei i

ɪl ColorChooserjpx = 8? ) «Project Source* colorchooser

рис. 16.5.
установка
свойства
buttongroup
irat (button! ∣<nδncp,j<none>
colorchooserframei
jui
jratobuttortf
∙fp conlentpane (boi = « porijerlayoui= s (3 jpaneh ∣ й «null* jradiobu-
jredlobytton?
iradiobuttom
uujmwrgt4w⅛ ιΓ¾∣ag
obntwflareafhl.. iτrue ietiujfgreohic «default*
raoiobu
> ⅛⅛ jcolorchooseri j menu
vj data access • l,i other
• butlongroup1 .jtl l
,iκ239y263
» " pt^wt⅛sj events'
doe history
source= dbsion

I. *fe ColorChooser iava

Текстовые поля по переключателям, как показано на рис. 16.1. Для этого с помощью комбинации Ctrl+щелчок выберите переключатель и текстовое поле и затем щелк­ните правой кнопкой мыши для вызова всплывающего меню. Опция Align bottom (Выровнять по низу) этого меню выровняет компоненты по горизонтали, по первому компоненту, на котором был произведен щелчок.

примечаниеПосле завершения позиционирования компонентов измените их свойства text. Установите его для первого компонента JTextField равным Первый, для второго — Второй и для третьего — Третий. И не забудьте установить свойства text четырех пере­ключателей в Синий, Зеленый, Красный и Все цвета.

Вот совет, который может пригодиться в некоторых случаях: при одно­временном выборе и переключателя, и текстового поля, вы можете сразу поменять оба их свойства text. В общем случае вы можете выбрать несколько компонентов и одним Махом изменить у всех одно и то же свойство.

Компоненты JCheckBox также находятся на странице Swing. Поместите в конст­руктор два таких компонента ниже остальных компонентов и выровняйте их. Изме­ните свойство text верхнего флажка на Задать цвет текста, а нижнего — на Задать цвет панели. Чтобы отображался весь текст, нужно увеличить размеры флажков. По­скольку вы имеете дело с пустой компоновкой, можно просто воспользоваться мар­керами растяжки. Имена этих компонентов следует изменить на jCheckBoxTextColor и jCheckBoxPanelColor.

Интерфейс вашей программы практически готов. В качестве последнего штриха выберите с помощью комбинации Ctrl+щелчок все переключатели и оба флажка и установите их цвет в Blue (синий). Это еще один пример использования множе­ственного выбора компонентов для одновременного изменения их свойств.

примечаниеТеперь начинается более хитрая часть. Смените компоновку панели на GridBagLayout. Надеюсь, что все компоненты останутся выстроенными, как было ра­нее. При необходимости вы можете немного поколдовать с настройками GridBagLayout, чтобы выстроить кнопки так, как требуется. Вы можете также обра­титься к листингу 16.1, в котором можно увидеть, как установлены свойства GridBagConstraints В моей версии программы. Теперь интерфейс должен выгля­деть похожим на показанный на рис. 16.1.

При работе с GridBagLayout до начала создания объектов GridBagConstraints в программе должна присутствовать следующая строка:

JPanell. SetLayoutIgridBagLayoutl);

Листинг 16.1. Свойства GridBagConstraints компонентов программы ColorChooser

JPanell. setLayoutCgridBagLayoutl); JPanell. addCjRadioButtonGreen,

New GridBagConstraints Clr 1, 1, 1, 0.0, 0.0,

GridBacrConstraints. CENTER, GridBagConstraints. HORIZONTAL,

New Insets(O, O, O, O), O, O));

JPanell. add CjRadioButtonRed, new GridBagConstraintsCl, 2, 1, 1, 0.0, 0 0,

GridBagConstraints. CENTER, GridBagConstraints. HORIZONTAL,

New Insets(O, O, O, O), O, O));

JPanell. add(JRadioButtonBlue,

New GridBagConstraints (1, O, 1, 1, 0.0, 0.0,

GridBagCons traints. CENTER, GridBagConstraints. HORIZONTAL,

New Insets(O, O, O, O), O, O));

JPanell. add(jTextField3,

New GridBagConstraints(2, 2, 1, 1, 0.0, 0.0,

GridBagConstraints. SOUTHWEST, GridBagConstraints. HORIZONTAL,

New Insets(O, O, O, O), O, O));

JPanell. add(jTextField2,

New GridBagConstr^ints(2, 1, 1, 1, 0.0, 0.0,

GridBagConstraints. SOUTHWEST, GridBagCons traints. HORIZONTAL,

New Insets(O, O, O, O), O, 0)>;

JPanell. add(jTextFieldl,

New GridBagConstraints (2, O, 1, 1, 1.0, 0.0,

GridBagConstraints. SOUTHWEST, GridBagConstraints. HORIZONTAL,

New Insets(O, O, O, O), O, O)) ;

JPanell. add(jCheckBoxTextColor,

New GridBagConstraints (1, 5, 1, 1, 0.0, 0.0,

GridBagConstraints. CENTER, GridBagConstraints. HORIZONTAL,

New Insets(O, O, O, O), O, O)) ;

JPanell. add(jCheckBoxPanelColor,

New GridBagConstraints (1, 6, 1, 1, 0.0, 0.0,

GridBagConstraints. CENTER, GridBagConstraints. HORIZONTAL,

New Insets(O, O, O, O), O, O));

JPanβll. add(JRadioButtonAll,

New GridBagConstraints (1, 4, 1, 1, 0.0, 0.0,

GridBagConstraints. CENTER, GridBagConstraints. HORIZONTAL,

New Insets(O, O, O, O), O, 0));

Этот листинг с объектами GridBagConstraints довольно-таки длинный. Одна — ко визуальные эффекты, которые достигаются с его помощью, очевидны. Поэтому вряд ли у вас возникнут затруднения при выстраивании элементов управления.

В данном случае почти вся работа сделана с помощью параметров gridχ и gridy свойства GridBagConstraints. Единственный другой важный параметр GridBagConstraints — это аргумент anchor, установленный для компонентов JTextField равным GridBagConstraints. SOUTHWEST.

Добавление меню

Теперь вам нужно добавить в программу меню. C его помощью можно будет лег­ко выйти из программы и изменить цвета, приписанные по умолчанию каждому компоненту.

Как вы помните из главы 13, меню можно создать, вначале поместив компонент JMenuBar в панель структуры. Этот компонент находится на странице Swing Containers палитры компонентов. Чтобы меню можно было видеть во время выпол­нения программы, добавьте в конец метода jbinit следующую строку:

примечаниеThis. SetJMenuBar(jMenuBarl);

Я уже не упоминаю о том, что лучше всего не забывать добавлять в программу строку меню во время первого запуска мастера создания приложения. Чес­тно говоря, лично я редко вспоминаю в это время о меню. Поэтому я обычно добавляю меню, следуя приведенным выше инструкциям. Но у тех, кто может планировать свою ра­Боту наперед, к этому времени все будет полностью готово.

Когда JMenuBar будет добавлен в программу и соответствующим образом иници­ализирован, щелкните на нем в панели структуры, чтобы вызвать конструктор меню. Добавьте пункт File ∣ Exit, а затем еще пять пунктов, в соответствие с рис. 16.6. Пункты меню, показанные здесь, позволяют пользователю задавать цвет текста про­граммы, его панели и трех компонентов JTextFieId.

Добавление событий

Теперь, после создания интерфейса, необходимо добавить обработчики собы­тий. Но перед этим взгляните на код, который втихаря сгенерировал JBuilder на ос­нове ваших действий в среде визуальной разработки. В редакторе исходного текста вы увидите стандартный Java-код, объявляющий и создающий компоненты, кото­рые вы разместили в конструкторе, и определяющий значения их свойств. Если вы только-только изучаете Java, этот код будет хорошим образцом.

В самом начале класса вам необходимо добавить несколько полей данных со зна­чениями по умолчанию, которые будут использоваться во всей программе-

Private Color textColor = Color. magenta; private Color panelColor = Color. cyan; private Color textFieldColorl = Color. blue; private Color textFieldColor2 = Color. green; private Color textFieldColor3 = Color. red;

Назначение данной программы состоит в том, чтобы предоставить пользователю возможность менять цвета различных компонентов на главной форме. Вышеприве­денные приватные переменные объявляют цвета по умолчанию для каждого компо­нента. Каждый экземпляр класса Color Инициализируется с помощью одной из констант, объявленных в самом классе Color. Например, Textcolor Установлен в Color. magenta.

source; p⅛flhjgj,bdlencomm options,alignments q.5 bl⅛ment* os,border custom wtderpetntee fats» contentafeaf true i t∣ebugθraphl. *fip⅛uh*,oisaotetiicon,properties fsventsf,∏) jbuilder 7 - & srr/srcjava/abunbtled&; f o∣nrf ħooser∕⅜tr√r^dr<hooser/freme∣4βv⅛,team v*⅛ards loots wmdow hetp,¾e ⅛,⅛a-.-a a⅜vt,x&ftamdtj
k s**β ∣ swhgccrtatare i oetaexprm ∣ dbswrtg i uareilismig ∣ d r∣>l
x(ssχ--efrt*r τ '⅛">
,h &- is t∙q 2p coiorcnooser,⅛1 ⅞∣l> «project source* ⅛ * colorchooser '■ & colorchooserjava,■ira
textcolor penei color
,-- к jcheckboxpaneicoio,* £ jcoiorchooserl limenu s⅛-∣e jmenubah ft∙ft∣ jmenut ' - -ci «separator*
- h imenultemi
,cdorone c)l0Γ-rw0 cpiorthree
lΓ~∙-n
,mjmenuitemtextcolor ⅛ и jmenu.iempanelcoior o <separatop “• jmenuitemcolorone m jmerultemcoiortwo ! m jmenuitemcoiorthree i data access l
∣ li other ¼
⅛læ
,260,⅜⅛r⅛b⅛i⅜⅜y
рис. 16.6. создание меню для программы colorchooser

File EdR Search View Prolect gun

,b4S3H%βd⅛Γ

> .∙ ⅛ ’

……. ÷⅛

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

примечаниеВернувшись в режим конструирования, выберите jRadιoButtonBlue, щелкнув на этом компоненте. В инспекторе выберите страницу Events и щелкните на колонке рядом с событием actionPerformed. В этой колонке появится автоматически сгене­рированное имя для этого действия, вроде jRadioButtonBlue_actionPerformed. При желании вы можете изменить это имя на что-нибудь более осмысленное, но можете и оставить имя по умолчанию.

Преимущество изменения имени обработчика события состоит в том, что в этом случае код будет несколько более читабельным. Преимущество оставления имени по умолчанию состоит в том, что если однажды ваш код будет запорчен, то вы сможете легко воссоздать его снова. Такая необходимость возникает нечасто, но иногда бывает нужно снова создать классы-адаптеры, применяемые для вызова метода. Это мо­жет случиться, если вы нечаянно удалите часть кода или проведете изменения, от которых потом захотите отказаться. Если вы оставите имена по умолчанию, восстановить ваши Обработчики событий и вызывающие их адаптеры будет очень легко.

В редакторе свойств дважды щелкните на слове jRadioButtonBlue_actionPerformed, и JBuilder вернет вас в редактор исходного кода. Причем курсор будет уста­новлен между фигурными скобками заготовки метода ActionPerformed Для JRadioButtonBiue. То есть JBuilder уже создал код обработчика событий для этого переключателя с пустым методом, который вам необходимо заполнить:

Void jRadioButtonBlue_actionPerformed(ActionEvent Е)

{

1

Создайте новый метод с именем SetTextFields И вызовите его из только что со­зданного метода ActionPerformed:

Void SetTextFields(Color color)

{

JTextFieldl. SetBackground(color); jTextField2.SetBackground(color); jTextFιeld3.SetBackground(color);

)

Void jRadioButtonBlue-actionPerformed(ActionEvent e)

(

SetTextFields(textFieldColorl) ;

)

Этот код устанавливает цвет всех полей JTextField в цвет, присвоенный на дан­ный момент полю данных teχtAreaColorl.

Вернитесь в режим конструирования и дважды щелкните в конструкторе на ком­поненте TadioButtonGreen. JBuilder переведет вас опять в редактор исходного кода, где уже будет создан метод ActionPerformed ДЛЯ Компонента RadioButtonGreen. Всякий раз, когда вы в JBuilder хотите воспользоваться простым методом ActionPerformed. Вы можете просто дважды щелкнуть на компоненте в конструкто­ре. В методе ActionPerformed Для XadioButtonGreen Необходимо добавить не­сколько измененную версию кода, который был вписан для JRadioButtonBiue:

Void jRadioButtonGreen_actionPerformed(ActionEvent Е)

{

SetTextFields(textFieldColor2,;

)

Вернитесь в режим конструирования, дважды щелкните на TadioButtonRed и впи­шите в его обработчик события следующий код:

Void jRadioButtonRed_actionPerformed(ActionEvent Е)

{

SetTextFields(textFieldColor3);

}

И, наконец, необходимо создать обработчик события для JRadioButtonAll:

Void JRadioButtonAll-SCtionPerformed(ActionEvent Е)

{

JTextFieldl. SetBackground(textFieIdColorl); JTextField2.SetBackground(textFieldColor2); JTextField3.SetBackground(textFieldColor3);

}

Этот метод слегка отличается от остальных тем, что он присваивает каждому JTextField Различный Цвет.

Сейчас вы, возможно, уже хотите протестировать введенный вами код, скомпилиро­вав и запустив приложение. Щелкните на пиктограмме с зеленым треугольником в па­нели инструментов, который обычно расположен чуть ниже и правее пункта меню Help.

Обработка событий флажков

Теперь нужно добавить обработчики событий для флажков На этот раз мы не бу­дем использовать обобщенный метод ActionPerformed, Потому что нам нужны раз­личные установки для отмеченного и неотмеченного состояния флажка, а мы не мо­жем получить информацию об ЭТОМ СОСТОЯНИИ ИЗ ActionEvent. Вместо него мы воспользуемся событием ItemStateChanged.

Вернитесь в режим конструирования, выберите jCheckBoxTextColor и перейдите в инспекторе на страницу Events. События на ней отсортированы в алфавитном по­рядке. Щелкните на колонке справа от KemStateChanged, как показано на рис. 16.7.

Дважды щелкните в инспекторе на jCheckBoxTextColor_itemStateChanged в колон­ке рядом с методом KemStateChanged. Вы вернетесь в редактор исходного текста, в метод ItemStateChanged Этого компонента. (Нажатие клавиши Enter дает такой же эффект, что и двойной щелчок.) Введите в метод обработчика следующий код:

Void jCheckBoxTextColor_ItemStateChanged(ItemEvent Е)

{

If . getStateChange () =ItemEvent. DESELECTED)

{

J TextFieldl. SetForeground(Color. black); jTextField2.SetForeground(Color. black); jTextField3.SetForeground(Color. black);

)

Else

{

JTextFieldl. SetForeground(textColor);

JTextField2.SetForeground(textСоlor);

JTextField3.SetForegroundftextColor);

}

}

Этот код задает, что если флажок не выбран, цвет текста будет черным. Если фла­жок выбран, то цвет станет равным значению, присвоенному textColor. Ясно, что самой главной строкой кода является первая:

If(е. getStateChange()==ItemEvent. DESELECTED)

Главное, что здесь следует понять — что ItemEvent содержит некоторые поля, которые недоступны в ActionEvent. В частности, с его помощью можно узнать, от­мечен ЛИ текущий компонент. Если ОН отмечен, ТО ItemEvent. getStateChange равно ItemEvent. SELECTED, а если Не отмечен, ТО ItemEvent. DESELECTED.

Вернитесь в режим конструирования, выберите jCheckBoxPanelColor и создайте для него заготовку метода itemstatechanged, точно так же, как и для jCheckBoxTextCoior. Код этой заготовки метода выглядит следующим образом:

If(е. getStateChange()==ItemEvent. DESELECTED)

{

JPanell. SetBackground(Color. black);

)

Else

{

JPanell. SetBackground(panelColor);

}

Вот и все. Теперь вы знаете, как работать с флажками. Запустите свое приложе­ние еще раз, чтобы посмотреть, как оно работает.

t g:zsrcj⅛v<⅜∕∣bt>cowfundatfraftjdisfoolprchaobarzbftzr httfthuommjrmw!.java,file gdii seareh view project run team woards tooje window help
d tf β - % β ∙ 4 ∙«• 7'- ⅛ « * i*f
tlutfif l⅛j 2p coiorchodsarl ∙5i' e «project sc » φ colorchoos ⅛ colorchoo 4 frameijwi
,"3 ⅜ ¼ ⅜ - ⅛ ∙ s 33 > ∙ s? * ’ *∙ **,ipanelt (oridbagcayouo,x ⅛5∣ coiorchooser ×.∙⅛ framel ∣ x>⅜ jcoiorctraoeer;
swng i swtig cartasiers i drenwere i detaexcress : aswng ∣ more aswina i aswfrg moaie i memetseens i xml ! ejb ’ ae _
,-∙ lsej ⅛-,•*«> c=i j j i t j,33 ∈ "c5 saιc ɪ '»,ɪ- fcj
•7 tolorchoosι* *-jυι
s othis ʃ i
рис. 16.7. событие uemstatechanged на странице events инспектора

Обработчики событий для пунктов меню

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

Теперь нам требуется создать обработчики событий для каждого созданного пун­кта меню. Выделите в редакторе Frame1 .java и перейдите в режим конструирования. Щелкните правой кнопкой мыши на узле меню в панели структуры и выберите Activate Designer (Запустить конструктор). Выберите первый пункт меню, для которо­го вы хотите создать обработчик события. Перейдите на страницу Events инспекто­ра JBuilder. Выберите метод actionPerformed и дважды щелкните или нажмите кла­вишу Enter, чтобы создать обработчик события. Если вам нужна информация о ра­боте с меню, обратитесь к главе 13.

Код для этих методов приведен в листинге 16.2. Обратите внимание, что в нача­ле этого фрагмента кода находится набор объектов класса Java. awt. Color, Объяв­ленных в виде членов данных класса Framel.

Листинг 16.2. Обработчики событий для пунктов меню вашей программы,

Устанавливающие цвета компонентов

Private Color textColor = Color. magenta;

Private Color panelColor = Color. cyan;

Private Color textFieldColorl = Color. blue;

Private Color textFieldColor2 = Color. green;

Private Color textFieldColor3 = Color. red;

Void jMenuItemTextColor_actionPer£ormed(ActionEvent e)

{

TextColor = jColorChooserl. ShowDialog(this, "Цвет текста", TextColor);

}

Void jMenuItemPanelColor_actionPerformed(ActionEvent e)

{

PanelColor = jColorChooserl. ShowDialog(this, "Цвет панели", PanelColor);

)

Void jMenuItemColorOne_actionPerformed(ActionEvent e)

(

TextFieldColorl — jColorChooserl. ShowDialog( this, "Первый цвет", TextFieldColorl);

1

Void jMenuItemColorTwo_actionPer£ormed(ActionEvent e)

(

TextFieldColor2 = jColorChooserl. ShowDialog( this, "Второй цвет”, TextFieldColor2);

)

Void jMenuItemColorThree_actionPerformed (ActionEvent e)

(

TextFieldColor3 ≈ jColorChooserl. ShowDialog(
this,
"Третий цвет”, TextFieldColor3);

}

Void jMenuItemExit_actionPerformed(ActionEvent e)

{

System. exit(O);

1

Приведенный здесь код достаточно прост. В большинстве случаев он просто присваивает новые цвета переменным, объявленным в начале программы. Обратите внимание на последний метод, который вызывает завершение программы при вы­боре пользователем пункта File ∣ Exit.

При вызове метода ShowDiaiog Класса JcoiorChoosec Ему передаются три пара­метра. Первый — это экземпляр базового класса диалогового окна. Этот базовый класс определяет, где будет отображаться диалог. В нашем случае это модальный ди­алог. Модальный диалог {modal dialog) возникает поверх окна, указанного программи­стом. Окно, над которым появляется модальный диалог, называется Родительским окном (parent window). Модальность диалога заключается в том, что пользователь не может вернуться в родительское окно, пока не щелкнет на кнопке OK или Cancel (Отмена) этого диалога. Вопрос состоит в том, как узнать, какое конкретно окно бу­дет находиться под диалоговым, а ответ находится в этой переменной, задающей родителя и передаваемой методу ShowDiaiog В его первом параметре.

Второй параметр метода ShowDiaiog Определяет заголовок диалогового окна JcolorChooser. Пример диалога JcolorChooser Показан на рис. 16.8. Обратите внимание, что его заголовок берется из обработчика выбора пункта меню "Цвет па­нели”:

Void jMenuItemPanelColor_actionPerformed(ActionEvent Е)

{

PanelColor = jColorChooserl. ShowDialog(this, "Цвет панели" , panelColor) ;

1

Последний параметр, передаваемый методу ShowDiaiog, Это цвет по умолча­нию, который необходимо выбрать при появлении диалога. Он всегда должен быть одним из членов данных Color, Объявленных в начале класса Framel.

Panel ( olor

LUJJZI

IIIll

1 J—I

H±hH

Illll

JJ I I I

recent:ROB

Рис. Диалог JColorChooser Во всей его красе. Обратите внимание на заголовок окна, заданный в программе

Preview

SampIeText SampIeText

OK

Cancel

Reset

Последнее, на что нужно обратить внимание в этом коде, — это способ инициа­лизации объекта JcolorChooser. Как вы, должно быть, помните, он был помещен с палитры компонентов на панель структуры. Оказывается, нетрудно создать экземп­ляр диалога JcolorChooser И Вручную:

JColorChooser j = new JColorChooser();

Если все это так легко, то зачем было выбирать JcolorChooser В палитре компо­нентов? Что дает в этом случае JBuiIder?

Ответов на этот вопрос существует целых два:

1. Помещая управляющий элемент с палитры компонентов, вы создаете один экземпляр этого элемента, который может глобально использоваться во всей программе. Да, это можно сделать и вручную, но все же удобнее, если JBuilder объявит этот экземпляр за вас. Используя все время одну и ту же переменную, вы избавляете сборщик мусора от огромной лишней работы и, следовательно, экономите время.

2. Более важно то, что еще на этапе конструирования вы можете увидеть объект JcolorChooser И просматривать в инспекторе его свойства. При желании вы можете легко настроить эти свойства. Это особенно удобно при работе с од­ним ИЗ Диалогов выбора файла FileChooser.

Здесь заканчивается раздел, посвященный использованию переключателей и флажков. Я надеюсь, теперь вы понимаете, как заставить эти компоненты работать и в собственных программах. Кроме того, вы узнали несколько больше о том, как с помощью визуальных средств JBuilder строить интерфейсы программ.

Переключатели и перечислимые типы

Переключатели хорошо сочетаются с перечислимыми типами. Если у вас есть три переключателя — соответствующие красному, синему и зеленому цветам — то вместе с ними было бы удобно использовать перечислимый тип с элементами red, BLUE И GREEN.

примечаниеК сожалению, Java не поддерживает перечислимые типы. Но эту проблему мож­но обойти. В данном разделе вы ознакомитесь с этим решением.

Многие из тех, кто программирует на Java, вместо перечислимых типов применяют целочисленные константы. Такое решение достаточно эффективно. Но при этом могут возникнуть ошибки, связанные с безопасностью типов. После того как вы позна­комитесь с представленным здесь решением, я еще вернусь к этому вопросу и покажу, по­Чему применение целых констант не так надежно, как приведенное ниже решение.

Код, который вы сейчас увидите, легок и для реализации, и для использования. Но его будет трудно понять тем, кто недостаточно хорошо разобрался в объектно — ориентированном программировании вообще и в объектной модели языка Java в ча­стности. Если не весь этот код будет понятен, попытайтесь хотя бы понять, о чем идет речь. Я надеюсь, что вы сможете уловить достаточно много, чтобы скопировать и даже слегка модифицировать этот код для использования в своих программах. Вы сможете сделать это, даже если и не все поймете. Если и это не поможет, не огор­
чайтесь. Это полезная техника, если вы понимаете ее, но ее совсем не обязательно знать, если вы применяете в своих программах переключатели.

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

Программа RadioButtonApplet, Которую можно найти в сопровождающих книгу материалах, отображает для каждого из четырех переключателей, присутствующих в интерфейсе программы, собственное изображение. Как видно на рис. 16.9, с помо­щью переключателей можно выбрать изображение маяка, скал, горной гряды и го­ристого берега Вест-Клифф.

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

Private final static class PictureChoice {

Private final String name; private PictureChoice(String name)

{

This. name = name ;

1

Public String toString()

{

Return name;

1

Static final PictureChoice LIGHT HOUSE = new

PictureChoice("LIGHT_HOUSE");

Static final PictureChoice ROCKS = new PictureChoice("ROCKS"); static final PictureChoice WEST_CLIFF = new

PictureChoice("WEST_CLIFF");

Static final PictureChoice MOUNTAINS = new

PictureChoice("MOUNTAINS");

1

рис. 16.9. c помощью radiobuttonapplet
пользователь может увидеть четыре различных изображения берегов калифорнии
>plet started.,applet viownt: mdiocbcckbuttondenws.rad>obuttonapptei class 
аден 
• l⅛tehθuse ? ftork* 
suite cmmountsins s,,8. .r∙¾⅛*αff j. 
ltflhthouse

Это приватный статический терминальный внутренний класс, являющийся час­тью класса самого аплета. Кроме приватного конструктора и метода tostring, этот класс содержит еще четыре статических метода, с помощью которых только и мож­но создавать экземпляры этого класса. Поскольку конструктор приватен, вы не мо­жете использовать его для создания экземпляров класса. Вместо этого вы должны вызвать один из четырех статических методов, расположенных в конце кода класса.

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

Наша конечная цель состоит в том, чтобы пользоваться этим классом примерно так же, как и перечислимым типом. Вот синтаксически правильный код, использу­ющий этот класс:

PictureChoice pictureChoice = PictureChoice. LIGHT_HOUSE;

Это объявление переменной типа PictureChoice, Которой присвоено значение PictureChoice. LIGHT_HOUSE. Это Очень ПОХОЖе Ha ТО, Как если бы PictureChoice Была не экземпляром класса, а перечислимым типом наподобие тех, которые име­ются в Object Pascal или С/С++.

Более того, вы можете написать вот такой код:

If (pictureChoice == PictureChoice. LIGHT_HOUSE)

{

Picture = IightHouse;

}

Else if(pictureChoice ≈ PictureChoice. MOUNTAINS)

{

Picture = mountains;

1

Else if (pictureChoice == PictureChoice. WEST_CLIFF)

{

Picture = westCliff;

J

Else if (pictureChoice == PictureChoice-ROCKS)

{

Picture = rock;

)

И опять-таки, это очень похоже на код, который бы использовался, если бы пе­ременная PictureChoice Имела перечислимый тип. Если вы захотите изменить тип PictureChoice, Вы можете сделать это так:

PictureChoice = PictureChoice. ROCKS;

Этот КОД меняет ТИП PictureChoice C LIGHT_HOUSE На ROCKS.

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

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

Класс также объявлен как статический и терминальный, т. к. классы, объявлен­ные таким образом, могут быть сильно оптимизированы виртуальной машиной Java. Далее, от этого класса не нужно создавать потомков или изменять члены дан­ных класса после его создания. Кроме того, ваша программа будет содержать лишь один экземпляр этого класса. Поэтому возможно объявить класс терминальным и статическим. Слово final в объявлении означает, что класс не может быть расши­рен, а слово static — что его члены не могут быть изменены после его создания,

И, наконец, вам необходимо понять, что выполняют операторы, находяшиеся в конце класса:

Static final PictureChoice LIGHTeHOUSE = new

PictureChoice("LIGHTeHOUSE");

Light_house является переменной, членом данных, класса PictureChoice. Ей присваивается экземпляр класса PictureChoice, содержащий строку со своим име­нем "LIGHTeHOUSE".

Единственный экземпляр класса PictureChoice создается при запуске аплета. При создании класса автоматически инициализируются его члены данных. Это просто одно из правил Java. В результате будут вызваны по очереди все четыре ста­тических метода доступа:

Static final PictureChoice LIGHT_HOUSE = new

PictureChoice("LIGHTeHOUSE");

Static final PictureChoice ROCKS = new PictureChoice("ROCKS"); static final PictureChoice WESTeCLIFF = new PictureChoice("WESTeCLIFF");

Static final PictureChoice MOUNTAINS = new PictureChoice("MOUNTAINS");

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

После инициализации класс уже не будет создаваться во время выполнения про­граммы. Все уже сделано. Взгляните еще раз на этот код:

PictureChoice = PictureChoice-ROCKS;

Во время выполнения, после инициализации, подобное присваивание не приво­дит к вызову конструктора класса PictureChoice. Оно просто присваивает пере­менной PictureChoice ссылку на ОДИН ИЗ Членов данных класса PictureChoice.

Безопасность типов и невозможность неправильного употребления

Достоинство этой системы состоит в ее полной безопасности типов (typesafe). Подумайте, что могло бы случиться, если бы light_house, rocks, west_cliff и mountains были объявлены как переменные обычного целого типа:

LIGHTeHOUSE=O;

ROCKS=I;

WEST_CLIFF=2;

MOUNTAINS=3; pictureChoice = ROCKS;

Тогда в программе для проверки на равенство mountains можно было бы напи­сать такой код:

If (pictureChoice == 3) doThis();

Проблема здесь заключается в том, что этот код не полностью безопасен. Автор программы в дальнейшем может изменить значение переменной mountains, и код перестанет работать. Но если вы объявите эти переменные как экземпляры класса PictureChoice, то вы не сможете сравнить переменную pictureChoice ни с чем, кроме экземпляра класса PictureChoice:

If (pictureChoice ≈ Picturechoice-MOUNTAINS) doThis();

примечаниеТо есть вы полностью исключите из своей программы один потенциальный ис­точник ошибок.

Если вы хорошо знакомы с JDK, то вам будет нетрудно найти немало примеров таких случаев, когда Sun пользуется целым типом вместо "перечислимого" класса, показанного здесь. Если эта техника так хороша, то почему же тогда Sun не при­меняет ее чаще? Хороший вопрос, и отчасти ответ на него дан в моем введении в данную тему: это просто удобная техника, и вы не обязаны применять ее, если не хотите или не понимаете ее. Но я хотел бы добавить, что в команде разработчиков Java компании Sun есть ведущие специалисты, которые считают, что перечислимые типы, наподобие приве­денных выше, не только помогают хорошему стилю программирования, но и действи­тельно лучше всего подходят в ситуациях, где могут пригодиться перечислимые типы. См., например, элемент 21 в книге Джошуа Блоха (Joshua Bloch) "Effective Java". На вре­мя публикации эту великолепную книгу можно было найти в Internet по адресу http:// Java. sun. com/docs/books/effective/.

Как сделать перечислимый тип открытым

Последнее, о чем я хотел бы сказать в связи с этим кодом, состоит в том, что у вас будет МНОГО Случаев, когда вам понадобится объявить класс PictureChoice от­крытым (public), чтобы им могли пользоваться и другие разработчики. Распростра­нение подобного класса будет полезным, если другие захотят воспользоваться ва­шим объектом, а для этого нужен доступ к этому перечислимому типу.

В этом случае я предлагаю объявить PictureChoice не как приватный внутрен­ний класс, а как открытый класс, который находится в своем собственном исходном файле. Он все равно должен быть объявлен как final и static, и у него так же дол­жен быть приватный конструктор, но сам класс уже не будет объявлен приватным. Теперь вы сможете экспортировать свой перечислимый тип, чтобы пользователи ва­шего класса могли им пользоваться. В нашем примере это не нужно, поэтому я объявил PictureChoice приватным внутренним классом. Но если вы поставляете компонент или класс для других и хотите открыть им свой перечислимый тип, вам потребуется использовать открытый экземпляр одного из "перечислимых" классов.

Исходный код для примера RadioButtonAppIet

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

Листинг 16.3. Программа RadioButtonAppIet является примером применения

imageicon
imageicon
imageicon
"перечислимого класса" в программе

// Инициализация аплета Public void init()

{

Try

{

Jblnit () ;

}

Catch(Exception e)

(

E. printStackTrace();

}

∕∕ Инициализация компонентов

Private void jblnit() throws Exception

{

JPanel pane = (JPanel) this. getContentPane(); j Panel2.setLayout(gridLayout2) ;

DefaultHandler defaultHandler = new DefaultHandler(this); JRadioButtonLightHouse. addActionListener(defaultHandler); JRadioButtonRocks. addActionListener(defaultHandler); JRadioButtonMountains. addActionListener(defaultHandler); JRadioButtonWestCliff. SddActionListener(defaultHandler); gridLayout2.setRows(2);

GridLayout2.setColumns(2);

JRadioButtonLightHouse. SetSelected(true);

JRadioButtonLightHouse. setText("Light House");

JRadioButtonMountains. setText("Santa Cruz Mountains"); JRadioButtonWestCliff. setText("West Cliff");

JRadioButtonRocks. setText("Rocks”);

Pane. setLayout(borderLayoutl); jPanell. setLayout(gridBagLayoutl); j Panel3.SetBackground(Color. yellow),

JPanell. add(jPanel3,

New GridBagConstraints (0, 1, 1, 1, 1.0, 1.0,

GridBagConstraints. CENTER, GridBagConstraints. BOTH,

New Insets(O, O, O, O), 123, 123));

ButtonGroupl. add (JRadioButtonLightHouse); buttonGroupl. add(jRadioButtonRocks); buttonGroupl. add (JRadioButtonMountains) ; buttonGroupl Sdd(JRadioButtonWestCliff); jPanell. add(JTextFieldl,

New GridBagConstraints (O, O, 1, 1, 1.0, 0.0,

GridBagConstraints-CENTER, GridBagConstraints. HORIZONTAL,

New Insets(O, O, O, O), O, O));

J Panel2.add(JRadioButtonLightHouse, null);

J Panel2.add(JRadioButtonRocks, null);

J Panel2.add(JRadioButtonMountains, null);

JPanel2.add(JRadioButtonWestCliff, null);

JTextFieldl. setText("JTextFieldl"); pane. add(j Pane11, BorderLayout. CENTER) ;

Pane. add(j Panel2, BorderLayout. NORTH);

IightHouse = new IinageIcon (

This. getClass().getResource("light-house. png")); rock = new ImageIcon(this. getClass().getResource("rocks. png")); mountains = new IroageIcon(

This. getClass () .getResource("santa-cruz-mountains. png”));

WestCliff = new ImageIcon(

This. getClass().getResource("west-cliff. png"));

}

∕ ∕ Получение информации об аплете

Public String getAppletlnfo()

{

Return "Информация об аплете"

}

11 Получение содержимого параметров

Public String[] [] getParameterlnfo()

{

Return null;

}

∕∕ Главный метод

Public static void main(String[] args)

{

RadioButtonApplet applet = new RadioButtonAppletO; applet. IsStandalone = true;

Frame frame;

Frame = new Frame ()

{

Protected void procesSWindowEvent(WindowEvent e)

{

Super. processWindowEvent(e);

If (e. getID() == WindowEvent. WINDOW_CLOSING)

{

System. exit(O);

}

}

Public synchronized void setTitle(String title)

{

Super. SetTitle(title),

EnableEvents(AWTEvent. WINDOW_EVENT_MASK);

}

) ;

Frame. setTitle("Фрейм аплета");

Frame. add(applet, BorderLayout. CENTER);

Applet. init () ;

Applet. start() ;

Frame. setSize(62 0,540) ;

Dimension d = Toolkit. getDefaultToolkit().getScreenSize(); frame SetLocation((d. width — frame. getSize().width) ∕ 2,

(d. height — frame. getSize().height) ∕ 2); frame. SetVisible(true);

Void jRadioButtonMountains_itemStateChanged(ActionEvent e) {

JTextFieldl. setText("Горы");

PictureChoice = FictureChoice. MOUNTAINS; repaint () ;

)

Void JRadioButtonRockS-JLtemStateChanged (ActionEvent e)

{

JTextFieldl. SetText("Скалы");

PictureChoice = PictureChoice-ROCKS; repaint();

Void jRadioButtonLightHouse_itemStateChanged(ActionEvent e)

{

JTextFieldl. SetText("Маяк"); pictureChoice = PictureChoice. LIGHT_HOUSE; repaint () ;

}

Void JRadioButtonWestClif f_itemStateChanged (ActionEvent e)

{

JTextFieldl. setText("Вест-Клифф"); pictureChoice = PictureChoice. WEST__CLIFF; repaint();

)

Public void paint(Graphics g)

(

Super. paint(g);

XmageIcon picture = IightHouse;

If (pictureChoice = PictureChoice. LIGHT_HOUSE)

{

Picture = IightHouse;

}

Else if(pictureChoice == Picturechoice-MOUNTAINS)

{

Picture = mountains;

}

Else if (pictureChoice == PictureChoice. WEST_CLIFF)

{

Picture = westCliff;

)

Else if (pictureChoice == PictureChoice-ROCKS)

{

Picture = rock ;

)

Graphics g3 = jPanel3.getGraphics(); int width = jPanel3.getWidth(); int height = jPanel3.getHeight();

G3 .drawlmage(picture. getlmage () , O, O, width, height, O, O, 620, 465, this);

}

Private final static class PictureChoice

{

Private final String name ; private PictureChoice(String name)

{

This. name = name;

}

Public String toString()

{

Return name ;

)

Static final PictureChoice LIGHT_HOUSE = new PictureChoice("LIGHT_HOUSE");

Static final PictureChoice ROCKS = new PictureChoice("ROCKS"); static final PictureChoice WEST_CLIFF =

New PictureChoice("WEST_CLIFF");

Static final PictureChoice MOUNTAINS =

New PictureChoice("MOUNTAINS");

Class DefaultiHandler implements java. awt. event. ActionListener {

RadioButtonApplet adaptee;

DefaultHandler(RadioButtonApplet adaptee)

{

This. adaptee = adaptee;

}

Public void actionPerformed(ActionEvent e)

{

If (e. getSource() == adaptee. jRadioButtonLightHouse)

{

Systern. out. println("Маяк");

Adaptee. jRadioButtonLightHouse_itemStateChanged(e);

}

Else if (e. getSource() == adaptee. jRadioButtonMountains)

{

System. out. println("Горы");

Adaptee. jRadioButtonMountains__itemStateChanged(e);

)

Else if (e. getSource() == adaptee. JRadioButtonWestCliff) {

System. out. println("Вест-Клифф");

Adaptee. JRadioButtonWestCliff_itemStateChanged(e);

}

Else if (e. getSource() == adaptee. JRadioButtonRocks)

{

System. out. println("Скалы");

Adaptee. jRadioButtonRocks_itemStateChanged(e);

примечание}

∣u*auhsι*∣∣∣ ■ я уже упоминал в данной главе, что в этой программе имеется переклю­чатель, выбранный по умолчанию. В тексте метода jblnit вы сможете найти следующий код: JRadioButtonLightHouse. SetSelected(true). Именно в силу наличия этой строки Верхний левый переключатель оказывается выбранным при запуске программы.

Обработчики событий

Кроме самого перечислимого типа, вы можете заметить, что в приведенном здесь коде используется не такой вид обработчика события, как обычно применяется в программах, разработанных в JBuilder. Я уже упоминал о подобном механизме обра­ботки событий в главе 14. Но я пройдусь по этой теме еще раз, дабы напомнить, как работает этот механизм. Я воспользовался им здесь потому, что он требует меньше­го кода, чем механизм обработки событий, используемый в JBuilder по умолчанию. Я хотел показать вам всю программу, но при этом занять как можно меньше места в данной книге.

В методе jbinit вы можете увидеть следующий код:

DefaultAdapter defaultAdapter = new DefaultAdapter(this);

JRadicButtonl. addltemListener(defaultAdapter); JRadicButton2.addltemListener(defaultAdapter); JRadioButton3.addltemListener(defaultAdapter); JRadioButton4.addltemListener(defaultAdapter);

Здесь создается экземпляр класса DefaultAdapter, который затем применяется в качестве обработчика для каждого переключателя в данной программе:

Class DefaultHandler implements java. awt. event. ActionListener

{

RadioButtonApplet adaptee;

DefaultHandler(RadioButtonApplet adaptee)

{

This. adaptee = adaptee;

}

Public void actionPerformed(ActionEvent e)

{

If (e. getSource () == adaptee. JRadioButtonLightHouse)

{

System. out. println("Маяк");

Adaptee. jRadioButtonLightHouse_itemStateChanged(e);

}

Else if (e. getSource() ≈ adaptee. JRadioButtonMountains)

{

System, out. println ("Горы") ;

Adaptee. jRadioButtonMountains_itemStateChanged(e);

)

Else if (e. getSource() == adaptee. JRadioButtonWestCliff)

{

System. out. println("Вест-Клифф");

Adaptee. JRadioButtonWestCliff_itemStateChanged(e);

}

Else if (e. getSource() ≈ adaptee. JRadioButtonRocks)

Systern. out. println("Скалы");

Adaptee. jRadioButtonRocks_itemStateChanged(e);

}

)

}

Этот код будет обрабатывать события всех переключателей, присутствующих в программе. В нем для определения переключателя, вызвавшего адаптер, использу­ется метод GetSource Класса ActionEvent. После определения автора вызова адап­тер может использовать эту информацию и знание французского слова Adaptee Для соответствующего обратного вызова метода, находящегося в англоязычной главной программе.

Вам потребуется ввести этот код вручную, поскольку JBuilder не генерирует его автоматически. Однако он занимает немного меньше места, нежели код, генерируе­мый JBuilder. Как я уже упоминал в главе 14, в большинстве случаев от такого кода больше хлопот, чем пользы. Здесь я воспользовался им только для того, чтобы сэко­номить в книге место и, возможно, в качестве напоминания, что при желании вы можете применять и такой прием.

Резюме

В данной главе вы узнали, как применять переключатели и флажки. При первом знакомстве с этими управляющими элементами они могут показаться немного муд­реными. Но когда вы узнаете их "секретное" устройство, пользоваться ими станет очень просто. В частности, вы узнали, что при использовании компонентов JRadioButton ОЧеНЬ ВЭЖНЫ События ActionEvent, А ДЛЯ Компонентов JCheckBox События ItemStateChanged.

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

Марджи и Чарли Калверт

Глава 17

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *