Графические интерфейсы пользователя Java - Тимур Сергеевич Машнин
Шрифт:
Интервал:
Закладка:
Компоновка GridLayout разделяет окно на прямоугольники равного размера на основе количества указанных строк и столбцов.
Элементы размещаются в ячейки слева направо, сверху вниз.
Эта компоновка игнорирует предпочтительный размер компонента, и каждый компонент изменяется в соответствии с его ячейкой.
Слишком мало компонентов приводит к пустым ячейкам, и слишком много компонентов приводит к дополнительным столбцам.
При создании компоновки указывается количество строк и столбцов.
По умолчанию создается одна строка с одним столбцом.
Компоновка устанавливается для контейнера методом setLayout и затем компоненты добавляются в контейнер методом add.
Компоновка CardLayout работает как стек, помещая компоненты друг поверх друга, и связывает имя с каждым компонентом в окне.
Эта компоновка хорошо подходит для размещения единственного компонента в окне.
Компоновка GridBagLayout разделяет окно на ячейки сетки, не требуя, чтобы компоненты были одного размера.
При этом каждый компонент, управляемый компоновкой, ассоциируется с экземпляром GridBagConstraints.
GridBagConstraints указывает как компонент располагается в области отображения, в какой ячейке начинается и заканчивается компонент, как компонент растягивается, когда имеется дополнительная ячейка, а также определяет выравнивание в ячейке.
Для использования этой компоновки сначала создается экземпляр GridBagLayout, который устанавливается для контейнера методом setLayout.
Затем создается экземпляр GridBagConstraints, параметры которого изменяются для каждого компонента.
gridx и gridy указывают номер ячейки для компонента.
gridwidth и gridheight указывают количество столбцов и строк, которые компонент занимает.
fill указывает что делать с компонентом, который меньше, чем размер ячейки.
ipady и ipadx указывают отступ.
Обратите внимание, что в конце мы используем метод pack для окна, который подгоняет размер окна под его содержимое.
Добавлять компоненты в окно можно и без менеджера компоновки, установив его в нуль.
Для этого нужно точно указывать координаты компонента и его размеры, например, с помощью метода setBounds.
До сих пор мы рассматривали окно Frame.
Однако помимо окна Frame, библиотека AWT позволяет создавать диалоговые окна с помощью класса Dialog.
Для создания диалогового окна, которое открывается из окна Frame, нужно создать экземпляр класса Dialog, указав в его конструкторе родительское окно, из которого будет открываться данное диалоговое окно.
Также можно указать заголовок окна и будет ли окно модальным, то есть будет ли оно блокировать все входные данные для окон верхнего уровня.
Далее можно наполнить диалоговое окно содержимым, напомним, что по умолчанию компоновка диалогового окна – это BorderLayout.
Для закрытия окна, к его компоненту нужно присоединить слушателя, в обработчике которого нужно вызвать метод setVisible (false) окна, сделав его невидимым.
Далее в основном окне, к его компоненту нужно присоединить слушателя, в обработчике которого нужно вызвать метод setVisible (true) диалогового окна, сделав его видимым.
И наконец, методом add нужно добавить диалоговое окно в основное окно, как обычный компонент.
Модель событий AWT
Мы уже несколько раз сталкивались со слушателями событий и обработчиками событий.
В отличие от процедурных программ, для программ с графическим интерфейсом пользователя требуется управляемая событиями модель, в которой низлежащее окружение сообщает вашей программе, когда что-то происходит.
Например, когда пользователь нажимает на мышь, низлежащая среда выполнения генерирует событие, которое оно отправляет в программу.
Затем программа должна выяснить, что означает щелчок мыши и действовать соответствующим образом.
Процедурное программирование, которое рассматривается как традиционное программирование, определяет процесс программирования как разработку процедур, которые прямо управляют потоком данных и элементами контроля.
Программирование, управляемое событиями, определяет процесс программирования как разработку процедур, которые реагируют на поток данных и элементы контроля в соответствии с действиями пользователя, программы или операционной системы.
Эти модели программирования отличаются потоком выполнения и структурой.
В AWT существуют две разные модели событий или способы обработки событий.
В Java 1.0 и ранее события отправлялись непосредственно соответствующим компонентам.
Сами события были инкапсулированы в один класс Event.
Для обработки таких событий нужно было переопределить метод action или handleEvent компонента, который вызывался при получении события компонентом.
Таким образом, в этой ранней модели обработчики событий, такие как action и handleEvent, были реализованы классом Component.
И версии этих методов по умолчанию ничего не делали и возвращали false.
Эта модель событий была заменена моделью Java 1.1.
Java 1.1 реализует модель делегирования, в которой события передаются только объектам, зарегистрированным для получения события.
Эта модель позволяет любому объекту получать события, генерируемые компонентом.
И это означает, что вы можете отделить сам пользовательский интерфейс от кода обработки событий, в отличие от ранней модели, где вы должны были для обработки события переопределять метод самого компонента пользовательского интерфейса.
В модели событий Java 1.1 вся функциональность обработки событий содержится в пакете java.awt. event.
Внутри этого пакета подклассы абстрактного класса AWTEvent представляют собой различные виды событий.
Класс AWTEvent и его подклассы заменяют Event предыдущей модели событий.
Пакет также включает в себя ряд интерфейсов EventListener, которые реализуются классами, которые хотят получать различные виды событий.
Эти интерфейсы определяют методы, вызываемые при возникновении событий соответствующего типа.
Пакет также содержит ряд классов адаптеров.
Они реализуют интерфейсы EventListener и являются абстрактными классами, которые предоставляют нулевые реализации методов соответствующего прослушивателя.
Эти классы удобны для создания объектов-слушателей.
Вместо того, чтобы объявлять, что ваш класс реализует определенный интерфейс EventListener, вы можете объявить, что ваш класс расширяет соответствующий адаптер.
Эта модель требует, чтобы объекты регистрировались для получения событий.
Затем, когда происходит событие, об этом уведомляются только те объекты, которые были зарегистрированы.
Эта модель называется «делегирование».
Она реализует шаблон проектирования Observer.
Таким образом, эта модель обеспечивает четкое разделение между компонентами GUI и обработкой событий.
Важно, чтобы любой объект, а не только компонент, мог получать события.
Таким образом, вы можете отделить свой код обработки событий от вашего графического интерфейса.
Один набор классов может реализовать пользовательский интерфейс, а другой набор классов может реагировать на события, генерируемые интерфейсом.
Это означает, что, если вы разработали хороший интерфейс, вы можете повторно использовать его в разных приложениях, изменив обработку событий.
Модель делегирования важна для JavaBeans, которые позволяют взаимодействовать между Java и другими платформами.
Чтобы обеспечить такое взаимодействие, необходимо было отделить источник события от получателя.
В модели делегирования события могут передаваться нескольким получателям; любое количество классов может быть зарегистрировано для получения события.
В старой модели обработчик событий мог заявить, что он полностью не обработал событие, передавая событие контейнеру, или обработчик событий мог сгенерировать новое событие и доставить его другому компоненту.
В любом случае разработчику приходилось планировать, как передавать события другим получателям.
В Java 1.1 это не требуется.
Событие будет передано каждому объекту, зарегистрированному в качестве слушателя для этого события, независимо от того, что другие объекты делают с событием.
Наконец, эта модель событий представляет идею очереди событий.
Вместо того, чтобы переопределять handleEvent для просмотра всех событий, вы можете заглянуть в очередь событий системы, используя класс EventQueue.
В Java 1.1 каждый компонент является источником