Графические интерфейсы пользователя Java

Text
Leseprobe
Als gelesen kennzeichnen
Wie Sie das Buch nach dem Kauf lesen
Schriftart:Kleiner AaGrößer Aa

Библиотека Swing

Графическая библиотека Swing была создана на основе библиотеки AWT для решения таких проблем AWT как недостаточный выбор графических компонентов и зависимость внешнего вида и поведения AWT графического интерфейса пользователя от конкретной операционной системы.



Эти проблемы были решены созданием классов и интерфейсов библиотеки Swing с использованием одного только языка Java.

Компоненты AWT являются тяжеловесными, в то время как компоненты Swing являются легковесными.

Библиотека AWT использует нативный код (код, специфичный для конкретной операционной системы) для отображения компонентов.

Каждая реализация среды выполнения Jave Runtime Environment должна обеспечивать собственные реализации кнопок, меток, панелей и всех других компонентов AWT.

Всякий раз, когда используется компонент AWT, все запросы на рисование пересылаются нативному коду.

Это позволяет использовать кнопку AWT в приложении, но кнопка отображается как кнопка Windows, или кнопка Mac или другая кнопка конкретной платформы, на которой работает приложение.

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

Прежде чем AWT компонент будет сначала нарисован на экране, будет создан его пир.



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

Например, когда Java рисует метку, она не просто рисует строку в нужном месте на экране.

Она создает пир и помещает его на экран.

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

Во-первых, Swing компоненты JFrame, JWindow, JDialog и JApplet расширяют свои AWT-аналоги.

И все они используют пиры для отображения фактической области рисования на экране.

Другие компоненты Swing легковесные; у них нет пиров.

Эти компоненты отрисовывают себя поверх существующих JFrame, JWindow, JDialog или JApplet.

И поэтому на самом деле они также неявно используют пиры.

В AWT библиотеке использование пиров значительно затрудняло создавать подклассы этих компонентов для изменения их поведения.

Потому что их поведение исходит от нативного пира и поэтому не может быть легко переопределено или расширено.

Далее, наличие нативного кода значительно затрудняет перенос Java на новую платформу.

Проще говоря, хотя сам язык Java был кросс-платформенным, библиотека AWT была его ахиллесовой пятой.

Наконец, нативные пиры потребляют много ресурсов.

Можно было бы ожидать, что использование нативного кода будет намного более эффективным, чем создание компонентов на Java.

Тем не менее, для создания большого количества элементов GUI может потребоваться много времени, когда для каждого из них требуется создание его пира.

Решением было создание легковесных компонентов библиотеки Swing, которые полностью написаны на Java, и поэтому не требуют прямого использования нативного кода.

Легковесный компонент – это просто компонент, полностью реализованный на Java.

Для создания легковесного компонента достаточно расширить AWT класс Component или Container напрямую, реализуя внешний вид компонента на Java, а не делегируя внешний вид пиру.

Легковесные компоненты могут быть прозрачными, и они не должны быть прямоугольными, что является ограничением при работе с компонентами, имеющими пиры.

Вы реализуете весь внешний вид, используя методы paint и update, и вы реализуете поведение компонента, улавливая пользовательские события и, возможно, генерируя новые события.

В библиотеке AWT для создания совершенно нового компонента вам нужно было бы расширять класс Canvas.

Легковесному компоненту достаточно расширить класс Component или Container.

Когда легковесный компонент помещается в контейнер, он не получает нативный пир.

Вместо этого Toolkit создает для компонента объект LightweightPeer, который служит как указатель и идентифицирует компонент как легковесный.

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

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

Контейнер принимает события перемещения мыши, нажатия клавиш, запросы на рисование и т. д. для легковесного компонента и отправляет их ему.

Метод setBackground легковесного компонента, просто расширяющего класс Component, не работает, так как всю работу по изображению кнопки на экране выполняет не peer-двойник компонента, а тяжеловесный контейнер, в котором расположен компонент.

Контейнер ничего не знает о том, что надо обратиться к методу setBackground, он рисует только то, что записано в методе paint.

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

Тогда рисованием займется тяжеловесный суперкласс-контейнер. Он нарисует и лежащий в нем легковесный контейнер, и размещенные в контейнере легковесные компоненты.

Предпочтительный размер тяжеловесного компонента устанавливается peer-объектом, поэтому для легковесных компонентов его надо задать явно, переопределив метод getPreferredSize, иначе некоторые менеджеры компоновки, например FlowLayout (), установят нулевой размер, и компонент не будет виден на экране.

Легковесные компоненты изначально рисуются прозрачными, и незакрашенная часть прямоугольного объекта не будет видна. Это позволяет создать компонент любой видимой формы.

Таким образом, на основе библиотеки AWT, появилась библиотека Swing – Java-библиотека классов и интерфейсов, представляющих такие стандартные графические компоненты интерфейса пользователя как кнопки, таблицы, поля ввода и др., а также методы для работы с ними.

Библиотека Swing составляет основную часть библиотеки JFC (Java Foundation Classes), которая объединяет классы и интерфейсы, обеспечивающие интерфейс пользователя Swing-компонентами, выбор внешнего вида и поведения интерфейса, поддержку технологий для людей с ограниченными возможностями, работу с высококачественной двухмерной графикой, текстом и изображениями, а также интернационализацию графического интерфейса пользователя.

В настоящее время библиотека Swing входит в набор настольных Java-технологий.



Все классы Swing-компонентов являются наследниками базового класса JComponent пакета javax. swing.



При конструировании Swing-интерфейса компоненты помещаются в контейнеры, образующие иерархию, которая берет свое начало от контейнеров верхнего уровня, представленных классами JApplet, который уже запрещен, JDialog, JFrame и JWindow.

Основные свойства графической библиотеки Swing можно суммировать как:

Кроссплатформенность.

Механизм сменного внешнего вида и поведения компонентов (pluggable look and feel).

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

Расширяемость за счет возможности расширения классов и интерфейсов библиотеки.

Архитектура Swing-компонентов основана на технологии Java Beans.

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

Легковесность.

Так как AWT-компоненты непосредственно взаимодействуют с операционной системой и представляют собой каждый маленькое индивидуальное окно, то их называют тяжеловесными.

Компоненты Swing представляют собой области в окне, характеризующиеся координатами и размером, при этом они не работают напрямую с операционной системой, их отображение основывается на реализации Java 2D API, поэтому их называют легковесными.

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

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

Использование библиотеки Swing не является потоково-безопасной.

Доступ к Swing-компонентам должен осуществляться в специальном потоке Event Dispatch Thread (EDT).

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

Снабжение компонентов всплывающими подсказками и механизмом управления клавиатурой.

Возможность настройки текста, отображаемого Swing-компонентами с помощью HTML-тэгов.

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

 

Чтобы отобразить форматированный текст, нужно просто указать строку текста HTML, которая начинается с тега <HTML>.

Возможность отображения иконок Swing-компонентами.

Реализация модели MVC (Model-View-Controller) – модели отделения данных от внешнего вида и поведения интерфейса.

Многие Swing-компоненты имеют связанные с ними интерфейсы (Model), которые отвечают за доступ к данным и генерацию событий, связанных с изменением данных.



Архитектура MVC (модель – вид – контроллер) – это объектно-ориентированная архитектура пользовательских интерфейсов, состоящая из трех частей.

Модель предназначена для хранения, изменения и получения данных графического компонента.

Вид представляет данные на экране.

Контроллер обеспечивает реакцию модели и вида в ответ на действия пользователя.

Архитектура MVC реализована в библиотеке Swing в виде архитектуры с разделенной моделью, состоящей из двух, а не из трех частей.

Вид и контроллер, в архитектуре Swing, объединены вместе в один элемент – представителя пользовательского интерфейса (delegate UI).



Класс графического компонента связывает модель и представителя с помощью менеджера пользовательского интерфейса (UIManager), который определяет внешний вид и поведение интерфейса (Look and Feel).

Именно поэтому библиотека Swing имеет подключаемую архитектуру look-and-feel.

Таким образом, для реализации модели MVC библиотека Swing использует делегирование (delegation) полномочий, назначая в качестве модели данных представителя (delegate) – экземпляр класса с именем вида xxxModel.

Класс библиотеки Swing содержит защищенное или даже закрытое поле model – объект этого класса-модели, и метод getModel, предоставляющий разработчику доступ к полю model.

Для обеспечения внешнего вида и поведения Swing компонента также используется делегирование полномочий.

Swing класс JComponent содержит защищенное поле ui – экземпляр класса-представителя ComponentUI из пакета javax.swing.plaf, непосредственно отвечающего за вывод изображения на экран в нужном виде.

Класс-представитель содержит методы paint и update, формирующие и обновляющие графику компонента.

Такие представители образуют целую иерархию с общим суперклассом ComponentUI.

Они собраны в пакет javax.swing.plaf и его подпакеты.

В их именах есть буквы UI (User Interface), например, ButtonUI.

Представители класса тоже являются полями класса Swing компонента, и доступ к ним осуществляется методами вида getUI.

При построении графического интерфейса пользователя редко приходится обращаться к моделям и представителям компонента.

В большинстве случаев достаточно обращаться к методам самого класса компонента.

Если есть желание поменять модель, принятую по умолчанию, можно заменить ее другой моделью, реализовав подходящий интерфейс или расширив существующий класс xxxModel.

Новая модель данных устанавливается методом setModel (xxxModel).

Для создания графического интерфейса пользователя с использованием библиотеки Swing в среде разработки IntelliJ IDEA, нужно нажать правой кнопкой мышки на пакете приложения и выбрать New – GUI Form.



Ввести имя класса и нажать OK.



В результате будет создан Java класс и его XML описание с расширением. form, которое открывается в визуальном редакторе, позволяя визуально создавать и редактировать GUI интерфейс.



Первоначально форма состоит только из контейнера JPanel.



Для дальнейшей работы с GUI интерфейсом, нужно в поле field name ввести имя этого компонента.

При желании можно изменить компоновку компонента.

Далее нужно открыть связанный с формой Java класс и в коде класса нажать правой кнопкой мыши и выбрать Generate – Form main ().



В результате будет сгенерирован код запуска формы.



А именно, будет сгенерирован метод main, в котором будет создано окно верхнего уровня JFrame.

И в это окно будет добавлена панель формы.

Теперь можно вернуться в визуальный редактор и добавлять компоненты в форму.



При этом по умолчанию в Java класс будут добавляться только соответствующие поля.

Весь остальной код будет генерироваться сразу в байт-код при компиляции на основании XML файла описания формы.

Изменить это можно в настройках File | Settings | Editor | GUI Designer, выбрав опцию Java source code.



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



Для добавления слушателя к компоненту, нужно нажать правой кнопкой мыши на компоненте и выбрать Create Listener.



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



Если у вас есть поля в Swing компоненте, которые вы хотите связать с данными класса JavaBean, нужно нажать правой кнопкой мыши на компоненте и выбрать Data Binding Wizard.



Дальше следовать подсказкам.

В результате будет сгенерирован Plain Old Java Object класс.



И будет сгенерирован код, связывающий Plain класс с GUI компонентом.

В GUI компонент можно добавить пользовательское свойство, которое отобразится в визуальном редакторе.



Для этого нужно нажать на поле Client Properties.



И открыть окно свойств.

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

С выбранным классом в левой панели нажмите кнопку + на правой панели.

И добавьте свойство.

JButton и JLabel


Палитра компонентов позволяет добавить кнопку JButton.



Для кнопки можно изменить цвет фона, шрифт, цвет надписи, выравнивание надписи, саму надпись, текст подсказки при наведении курсора мыши на кнопку, добавить слушателя действий пользователя.



Также можно добавить значок в кнопку.

Компонент JLabel может отображать либо текст, либо изображение, либо и то, и другое.



Содержимое метки может выравниваться, с помощью установки вертикального и горизонтального выравнивания в области отображения.

Компонент JLabel используется для отображения одной строки только для чтения.

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

С помощью разметки HTML можно создавать многострочную метку, комбинируя шрифты и цвета.

JColorChooser


Компонент JColorChooser используется для создания диалогового окна выбора цвета.



Использовать компонент JColorChooser очень просто.

Вызываем статический метод showDialog, который отображает модальное диалоговое окно выбора цвета.

Это диалоговое окно блокирует приложение до тех пор, пока оно не будет закрыто.

В метод showDialog передается цвет выбора по умолчанию.

Пользователь может в диалоге изменить этот цвет выбора.

После закрытия диалогового окна метод showDialog возвращает цвет выбора, который далее может быть использован в приложении.

JCheckBox, JRadioButton, JToogleButton


Компонент JCheckBox используется для создания флажка.



Щелчок мыши на флажке изменяет его состояние с «on» на «off» и наоборот.

Методом setMnemonic можно определить горячие клавиши для этой кнопки.

А флажок является кнопкой, так как наследует от класса AbstractButton.

Компонент JRadioButton используется для создания переключателя.



Он используется для выбора только одной опции из нескольких вариантов.

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

Для того чтобы выбор кнопки был единственным, кнопки нужно объединить в группу ButtonGroup.

Если это не сделать, выбор будет множественным.

Компонент JToggleButton реализует функции переключения, которые наследуются компонентами JCheckBox и JRadioButton.



Компонент JToggleButton используется для создания кнопок с двумя состояниями – включен и выключен.

Компонент JToggleButton создается с помощью конструктора класса, в котором можно указать надпись кнопки, иконку и состояние.

Проверить нажата ли кнопка, можно с помощью метода isSelected.

JComboBox


Компонент JComboBox объединяет кнопку или редактируемое поле и раскрывающийся список.



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

Создать экземпляр раскрывающегося списка можно конструктором по умолчанию JComboBox, а затем вносить в него элементы методами addItem (Object) и insertItemAt (Object, int).

Однако удобнее предварительно создать массив или вектор, содержащий элементы, и внести его в список сразу же при его создании конструктором JComboBox (Object []) или JComboBox (Vector).

Получить элемент списка, который выбрал пользователь, можно с помощью метода getSelectedIndex или getSelectedItem.

Вместо строк, список можно составить из изображений, или других объектов.



Список становится редактируемым с помощью вызова метода setEditable (true).

 


Здесь показан пример, в котором пользователь может отредактировать выбранное поле, и оно будет сохранено в списке.

Редактирование выбранного элемента списка не приводит к изменению этого элемента в списке, а влияет только на объект, возвращаемый методом getSelectedItem.

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

Здесь нужно учитывать, что слушатель ActionListener получает событие ActionEvent, когда был сделан выбор.

И если поле со списком доступно для редактирования, тогда событие ActionEvent также будет сгенерировано, когда закончится редактирование.

Таким образом, обработчик ActionListener вызывается два раза.

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

Для изображения элементов списка используется объект, реализующий интерфейс ListCellRenderer.



Этот объект последовательно выводит элементы, переходя от одного элемента к другому.

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

Метод getListCellRendererComponent интерфейса ListCellRenderer отвечает за формирование компонента и размещения в нем текущего элемента списка value, имеющего порядковый номер index.

Полученный таким образом компонент затем выводится на экран своим методом paint.

В библиотеке Swing интерфейс ListCellRenderer реализован классами BasicComboBoxRenderer и DefaultListCellRenderer, расширяющими класс JLabel.

Именно потому, что выводом элементов фактически занимается класс JLabel, можно использовать в элементах списка текст или изображение.

Здесь показана пользовательская реализация интерфейса ListCellRenderer, которая выводит флажки в качестве элементов списка.

JScrollPane

Компонент JScrollPane является контейнером, который может содержать только один компонент и используется для создания прокручиваемого представления компонента.




Когда размер экрана ограничен, используется панель прокрутки для отображения большого компонента или компонента, размер которого может изменяться динамически.

Полосы прокрутки могут всегда отображаться на экране, отображаться при необходимости или не отображаться вообще. Это определяется методами setVerticalScrollBarPolicy и setHorizontalScrollBarPolicy.

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

Эти компоненты устанавливаются методами setColumnHeaderView, setRowHeaderView и setCorner соответственно.

Компонент помещается на панель прокрутки сразу же при ее создании конструктором класса JScrollPane или позднее методом setViewportView.

На самом деле компонент отображается в панели прокрутки в окне содержимого JViewport, которое содержит панель JScrollPane.



Это окно можно получить методом getViewport класса JScrollPane, а затем можно добавить в него компонент обычным методом add.