Java — Не могу поставить скролл в свинге.


Содержание

Java Swing — использование JScrollPane и его прокрутка вверх

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

Кто-нибудь знает, как это сделать?

Вызов setCaretPosition (0) вашего текстового компонента приведет к его прокрутке вверх.

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

Их решение состоит в том, чтобы открутить поток через invokeLater

Менеджеры расположения Layout

Менеджер расположения (layout manager) определяет, каким образом на форме будут располагаться компоненты. Независимо от платформы, виртуальной машины, разрешения и размеров экрана менеджер расположения гарантирует, что компоненты будут иметь предпочтительный или близкий к нему размер и располагаться в том порядке, который был указан программистом при создании программы.

На странице представлено описание следующих менеджеров расположения и примеров :

  • Полярное расположение BorderLayout
  • Последовательное расположение FlowLayout
  • Табличное расположение GridLayout
  • Менеджер расположения GridBagLayout
  • Менеджер расположения CardLayout
  • Менеджер расположения BoxLayout
  • Менеджер расположения GroupLayout
  • Менеджер расположения SpringLayout
  • Пример диалогового окна авторизации
  • Пример собственного менеджера расположения

Исходные коды примеров различных менеджеров расположения, рассмотренных на странице можно скачать здесь (13.4 Кб).

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

Поддержка менеджеров расположения встроена в базовый класс контейнеров java.awt.Container. Все компоненты библиотеки Swing унаследованы от базового класса JComponent, который, в свою очередь, унаследован от класса Container. Таким образом, для любого компонента Swing можно установить менеджер расположения или узнать, какой менеджер им используется в данный момент. Для этого предназначены методы setLayout() и getLayout().

Конечно, изменять расположение желательно только в контейнерах, которые предназначены для размещения в них компонентов пользовательского интерфейса, то есть в панелях (JPanel) и окнах (унаследованных от класса Window). Не стоит менять расположение в кнопках или флажках, хотя такая возможность имеется. В стандартной библиотеке Java существует несколько готовых менеджеров расположения, и с их помощью можно реализовать абсолютно любое расположение.

Вызов менджера расположения, revalidate

Контейнер окна вызывает методы менеджера расположения каждый раз при изменении своих размеров или при первом появлении на экране. Кроме этого, можно программно запросить менеджер расположения заново расположить компоненты в контейнере: для этого служит так называемая проверка корректности (валидация) контейнера и содержащихся в нем компонентов. Проверка корректности очень полезна, если интерфейс приложения меняется динамически. Например, если динамически меняются размеры компонентов (во время выполнения программы изменяется текст надписи или количество столбцов таблицы — все это приведет к изменению размеров компонентов). После изменений компонентам может не хватать прежних размеров или наоборот, прежний размер будет для них слишком велик. Для этого и предназначена проверка корректности. Выполнить проверку корректности для любого компонента Swing, будь это контейнер или отдельный компонент, позволяет метод revalidate(), определенный в базовом классе библиотеки JComponent.

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

  • Предпочтительный размер. Размер, который идеально подходит компоненту. По умолчанию все размеры компонентов устанавливаются текущим менеджером внешнего вида и поведения (look and feel manager), но можно их изменить. Предпочтительный размер можно изменить с помощью метода setPrefferedSize().
  • Минимальный размер. Параметр определения минимального размера компонента. После достижения минимального размера всех компонентов контейнер больше не сможет уменьшить свой размер. Минимальный размер также можно изменить, для этого предназначен метод setMinimumSize().
  • Максимальный размер. Параметр определения максимального размера компонента при увеличении размеров контейнера. Например, максимальный размер текстового поля JTextField не ограничен. Чаще всего оно должно сохранять свой предпочтительный размер. Это можно исправить с помощью метода setMaximumSize(), устанавливающего максимальный размер. Большая часть менеджеров расположения игнорирует максимальный размер, работая в основном с предпочтительным и минимальным размерами.
  • Выравнивание по осям X и Y. Данные параметры нужны только менеджеру BoxLayout, причем для него они играют важнейшую роль.
  • Границы контейнера. Эти параметры контейнера определяют размеры отступов от границ контейнера. Значения границ контейнера позволяет получить метод getInsets(). Иногда менеджеру расположения приходится их учитывать.

Описание бизнес-логики работы менеджера расположения

Логика работы менеджера расположения происходит следующим образом : он ждет прихода сигнала от контейнера окна, требующего расположить в нем компоненты. Этому соответствует вызов метода layoutContainer() интерфейса LayoutManager. В методе layoutContainer() и происходит основная работа по расположению компонентов в контейнере.

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

Ниже представлен пример разработки менеджера вертикального расположения компонентов VerticalLayout. Он располагает компоненты вертикально с расстоянием между ними в 5 пикселов и использует для всех компонентов предпочтительный размер.

Менеджер расположения VerticalLayout реализует интерфейс LayoutManager. Самым важным методом является layoutContainer(), который определяет расположения всех компонентов, содержащиеся в контейнере. Алгоритм функционирования менеджера расположения не сложный : размещение компонентов по вертикали, отделяя их друг от друга расстоянием в 5 пикселов; все компоненты имеют предпочтительный размер. Чтобы реализовать алгоритм выполняются следующие шаги :

  1. Получение массива компонентов — метод контейнера getComponents().
  2. Организация цикла перебора компонентов.
  3. Определение предпочтительного размера для каждого из компонентов — метод getPreferredSize().
  4. Определение позиции компонента на экране методом setBounds().
  5. Смещение текущей вертикальной координаты Y, увеличением ее значения на высоту очередного компонента с учетом «декоративного» расстояния в 5 пикселов.

Таким образом, менеджер VerticalLayout разместит все компоненты контейнера друг над другом на расстоянии в 5 пикселов. Следует обратить внимание, что компоненты отделены и от левой границы контейнера.

Метод addLayoutComponent() предназначен для добавления компонентов в список менеджера расположения, а метод removeLayoutComponent() для удаления компонентов из списка. addLayoutComponent() позволяет ассоциировать с компонентом строку, которая может быть использована менеджером расположения как рекомендация относительно того, где именно необходимо разместить данный компонент. Наш пример менеджера расположения в отличие от BorderLayout не поддерживает подобных рекомендаций.

Две функции менеджера (предпочтительный preferredLayoutSize() и минимальный minimumLayoutSize()) сообщают размеры контейнера. Для нашего простого менеджера расположения минимальный и предпочтительный размеры контейнера совпадают, их вычисляет метод calculateBestSize(). Для вычисления оптимального размера контейнера в цикле выполняется поиск компонента с самой большой длиной. К найденной длине добавляется 5 пикселов в качестве отступа от левой границы контейнера и получаем оптимальную длину контейнера. Для высоты вычисления чуть сложнее : необходимо сложить высоты всех находящихся в контейнере компонентов, а также прибавлять к ним расстояние в 5 пикселов между всеми компонентами. Полученная сумма и является оптимальной высотой контейнера.

Для тестирования менеджера вертикального расположения в методе main() создаем небольшое окно с рамкой JFrame. Создаем панель с устанавленным менеджером расположения VerticalLayout. В панель добавляется пара кнопок и текстовое поле. Созданную панель размещаем в панели содержимого, после чего окно выводится на экран. На следующем скриншоте представлен интерфейс окна примера использования вертикального менеджера расположения компонентов.

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

Полярное расположение BorderLayout

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

Менеджер расположения BorderLayout иммет отличия от остальных. Чтобы добавить с его помощью компонент в методе add() необходимо использовать дополнительный параметр, который определяет область контейнера для размещения компонента. В таблице перечислены допустимые значения этого параметра.

Значение Строка Описание
BorderLayout.NORTH North Компонент располагается вдоль верхней границы окна и растягивается на всю его ширину. Обычно в этом месте размещается панель инструментов.
BorderLayout.SOUTH South Компонент располагается вдоль нижней границы и растягивается на всю ширину окна. Такое положение характерно для строки состояния.
BorderLayout.WEST West Компонент располагается вдоль левой границы окна и растягивается на всю его высоту; при этом учитываются размеры северных и южных компонентов, имеющих приоритет.
BorderLayout.EAST East Компонент располагается вдоль правой границы окна. В остальном его расположение аналогично западному компоненту.
BorderLayout.CENTER Center Компонент помещается в центр окна, занимая максимально возможное пространство.

Рекомендации : на север помещайте панель инструментов вашего приложения. На юг помещайте строку состояния. Оставляйте западные и восточные зоны окна свободными — только в этом случае панель инструментов можно будет перетаскивать. Для главного окна вашего приложения всегда используйте расположение BorderLayout.

Рассмотрим простой BorderLayout пример. В примере создается окно JFrame, в котором менеджер BorderLayout используется по умолчанию. Во все доступные зоны добавляются компоненты :

В примере метод установки менеджера расположения setLayout() не вызывался. В окнах JFrame (также в окнах JWindow и JDialog) расположение BorderLayout применяется автоматически c принимаемой по умолчанию константой Center. При использовании строк в качестве параметров метода add() надо быть внимательным. Со строкой легко сделать трудно обнаруживаемую ошибку, в то время как ошибку при использовании констант сразу же обнаружит компилятор.

Интерфейс примера BorderLayout представлен на следующем скриншоте.

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

Последовательное расположение FlowLayout

Менеджер последовательного расположение FlowLayout размещает компоненты в контейнере слева направо, сверху вниз. При полном заполнении компонентами строки контейнера FlowLayout переходит на следующую строку вниз. Данное расположение устанавливается по умолчанию в панелях JPanel. Основным свойством FlowLayout является определение предпочтительного размера компонентов. Например, размер метки с текстом JLabel соответствует размеру текста. Рассмотрим простой пример FlowLayout :

Конструктор класса FlowLayout имеет три перегруженные версии: без параметров, с параметрами выравнивания компонентов, с параметрами выравнивания компонентов и расстояний между ними. В примере использована вторая версия, устанавливающая последовательное расположение по центру.

На следующем скриншоте показан интерфейс программы для двух разных размеров окна по горизонтали.

На правом скриншоте размер окна не позволил менеджеру FlowLayout разместить компоненты в одной строке, и один компонент сместился в следующую строку.

При последовательном расположении менеджер FlowLayout всегда сохраняет предпочтительный размер компонентов. Если места в контейнере становится мало, то FlowLayout просто прячет «лишние» компоненты, а не уменьшает их размеры.

Также к важным свойствам менеджера расположения FlowLayout следует отнести то, что при вызове метода preferredLayoutSize() или minimumLayoutSize(), позволяющего узнать предпочтительный и минимальный размеры контейнера, в котором этот менеджер действует, метод возвращает размер, соответствующий ситуации расположения всех компонентов в одну строку. Это особенно важно при совмещении последовательного расположения с другими вариантами расположения. Вследствие этого свойства менеджеры других вариантов расположения будут стараться найти достаточно места для размещения компонентов в одну строку.

Поэтому использовать последовательное расположение следует только в контейнере, где достаточно места, или там, где контейнеру некуда будет «прятать» свои компоненты. Пример совмещении последовательного расположения с табличным представлен на этой странице здесь. Тем не менее, этот простотой менеджер расположения FlowLayout очень хорош при организации несложных вариантов расположения.

Табличное расположение GridLayout

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

Пример табличного расположения компонентов — GridLayout :

В примере задается произвольное количество столбцов. Для этого в конструкторе вместо конкретного числа столбцов указывается ноль. Аналогично можно задать и произвольное количество строк в таблице.

Интерфейс работы программы представлен на следующем скриншоте.

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

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

Чаще всего совмещают панели с различными менеджерами расположения для получения необходимого интерфейса окна. В следующем примере совмещаем менеджер табличного расположения компонентов GridLayout с менеджером последовательного расположения FlowLayout, которое никогда не делает содержащиеся в нем компоненты больше их предпочтительного размера. Для этого создадим элемент пользовательского интерфейса, встречающийся практически в любом диалоговом окне, а именно строку кнопок (кнопки ОК и Отмена). Табличное расположение придаст кнопкам одинаковый размер, а последовательное расположение не даст им «расплыться» и заодно выровняет их по правому краю.

Пример совмещения табличного Gr >

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

Менеджер расположения GridBagLayout

Менеджер расположения GridBagLayout подобно табличному менеджеру устанавливает компоненты в таблицу. Но он дает возможность определять для компонентов разную ширину и высоту колонок и строк таблицы. Фактически GridBagLayout позволяет получить абсолютно любое расположение компонентов.

Пример менеджера расположения Gr >

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

Пользовательский интерфейс примера GridBagLayout представлен на следующих скриншотах. На нижнем скриншоте представлен интерфейс для уменьшенного размера окна.

Менеджер расположения CardLayout

Менеджер CardLayout можно использовать для создания так называемых вкладок (tabs), выбирая которые будут избранно открываться разные панели, занимающие одно и то же место в интерфейсе окна. В библиотеке Swing данную задачу можно решить с использованием класса JTabbedPane, организовывающего управление панелями с вкладками.

Пример менеджера расположения CardLayout

Пользовательский интерфейс примера менеджера расположения CardLayout представлен на следующих скриншотах. На верхних скриншотах представлен интерфейс окна для разных размеров. На нижнем скриншоте представлен интерфейс окна для вкладки с тестовым полем.

Менеджер расположения BoxLayout

Менеджер расположения BoxLayout позволяет управлять размещением компонентов либо в вертикальном, либо в горизонтальном направлениях и управлять пространством между компонентами, используя вставки. Для размещения компонентов в вертикальной плоскости необходимо конструктору передать константу BoxLayout.Y_AXIS, для размещения в горизонтальной — BoxLayout.X_AXIS.

Пример менеджера расположения BoxLayout

Пользовательский интерфейс примера менеджера расположения BoxLayout представлен на следующих скриншотах. На верхнем скриншоте представлен интерфейс окна с вертикальным расположением компонентов. На нижнем скриншоте компоненты размещены в горизонтальной плоскости.

Менеджер расположения GroupLayout

Менеджер расположения компонентов GroupLayout появился только в Java 6. Он раскладывает компоненты по группам. Группы имеют горизонтальное и вертикальное направление и могут быть параллельными и последовательными. В последовательной группе у каждого следующего компонента координата вдоль оси на единицу больше (имеется в виду координата в сетке), в параллельной – компоненты имеют одну и ту же координату.

Пример менеджера расположения GroupLayout

Интерфейс окна примера менеджера расположения GroupLayout представлен на следующем скриншоте.

Менеджер расположения SpringLayout

Несмотря на универсальность менеджера расположения SpringLayout, действие его весьма специфично и не похоже на действие ни одного из уже рассмотренных выше менеджеров расположения.

С каждым компонентом ассоциируется особый информационный объект SpringLayout, который позволяет задать расстояние (в пикселах) между парой границ различных компонентов. Границ у компонента четыре — это его северная, восточная, западная и южная стороны. Можно задавать расстояние и между границами одного и того же компонента: к примеру, задав расстояние между северной и южной сторонами одного компонента, вы укажете его высоту. По умолчанию все компоненты имеют предпочтительный размер, однако SpringLayout учитывает и два остальных размера, не делая компоненты меньше минимального и больше максимального размеров.

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

Пример менеджера расположения SpringLayout

Интерфейс окна примера менеджера расположения SpringLayout представлен на следующем скриншоте.

Интерфейс диалогового окна авторизации

Интерфейс примера диалогового окна авторизации LoginDialog представлен на следующем скриншоте.

Исходный код примера LoginDialog в виду его большого размера не приводится. Но его можно скачать вместе с остальными примерами.

Занятие 8

Введение в библиотеку Swing

Библиотека Swing

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

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

В Java есть три библиотеки визуальных компонентов для создания графического интерфейса пользователя. Самая ранняя из них называется AWT. Считается, что при ее проектировании был допущен ряд недочетов, вследствие которых с ней довольно сложно работать. Библиотека Swing разработана на базе AWT и заменяет большинство ее компонентов своими, спроектированными более тщательно и удобно. Третья, самая новая библиотека, называется SWT.

Каждая библиотека предоставляет набор классов для работы с кнопками, списками, окнами, меню и т.д., но эти классы спроектированы по-разному: они имеют различный набор методов с разными параметрами, поэтому «перевести» программу с одной библиотеки на другую (например, с целью увеличения быстродействия) не так-то просто. Это почти как перейти с одного языка программирования на другой: все языки умеют делать одно и то же, но у каждого из них свой синтаксис, своя программная структура и свои многочисленные хитрости.

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

Окно JFrame

Каждая GUI-программа запускается в окне и по ходу работы может открывать несколько дополнительных окон.

В библиотеке Swing описан класс JFrame , представляющий собой окно с рамкой и строкой заголовка (с кнопками «Свернуть», «Во весь экран» и «Закрыть»). Оно может изменять размеры и перемещаться по экрану.

В Swing есть еще несколько классов окон. Например, JWindow — простейшее окно, без рамки и без строки заголовка. Обычно с его помощью делается заставка к программе, которая перед запуском должна выполнить несколько продолжительных действий (например, загрузить информацию из БД).

Конструктор JFrame() без параметров создает пустое окно. Конструктор JFrame(String title) создает пустое окно с заголовком title .

Чтобы написать простейшую программу, выводящую на экран пустое окно, нам потребуется еще три метода:

setSize(int width, int height) — устанавливает размеры окна. Если не задать размеры, окно будет иметь нулевую высоту независимо от того, что в нем находится и пользователю после запуска придется растягивать окно вручную. Размеры окна включают не только «рабочую» область, но и границы и строку заголовка.

setDefaultCloseOperation(int operation) — позволяет указать действие, которое необходимо выполнить, когда пользователь закрывает окно нажатием на крестик. Обычно в программе есть одно или несколько окон при закрытии которых программа прекращает работу. Для того, чтобы запрограммировать это поведение, следует в качестве параметра operation передать константу EXIT_ON_CLOSE , описанную в классе JFrame .

setVisible(boolean visible) — когда окно создается, оно по умолчанию невидимо. Чтобы отобразить окно на экране, вызывается данный метод с параметром true . Если вызвать его с параметром false , окно снова станет невидимым.

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

Обратите внимание, для работы с большинством классов библиотеки Swing понадобится импортировать пакет java.swing. *

Как правило, перед отображением окна, необходимо совершить гораздо больше действий, чем в этой простой программке. Необходимо создать множество элементов управления, настроить их внешний вид, разместить в нужных местах окна. Кроме того, в программе может быть много окон и настраивать их все в методе main() неудобно и неправильно, поскольку нарушает принцип инкапсуляции: держать вместе данные и команды, которые их обрабатывают. Логичнее было бы, чтобы каждое окно занималось своими размерами и содержимым самостоятельно. Поэтому классическая структура программы с окнами выглядит следующим образом:

В файле SimpleWindow.java:

В файле Program.java:

Из примера видно, что окно описывается в отдельном классе, являющемся наследником JFrame и настраивающее свой внешний вид и поведение в конструкторе (первой командой вызывается конструктор суперкласса). Метод main() содержится в другом классе, ответственном за управление ходом программы. Каждый из этих классов очень прост, каждый занимается своим делом, поэтому в них легко разбираться и легко сопровождать (т.е. совершенствовать при необходимости).

Обратите внимание, что метод setVisible() не вызывается в классе SimpleWindow , что вполне логично: за тем, где какая кнопка расположена и какие размеры оно должно иметь, следит само окно, а вот принимать решение о том, какое окно в какой момент выводится на экран — прерогатива управляющего класса программы.

Панель содержимого

Напрямую в окне элементы управления не размещаются. Для этого служит панель содержимого, занимающая все пространство окна * . Обратиться к этой панели можно методом getContentPane() класса JFrame . С помощью метода add(Component component) можно добавить на нее любой элемент управления.

В примерах этого занятия мы будем использовать только один элемент управления — кнопку (не вдаваясь в подробности ее устройства). Кнопка описывается классом JButton и создается конструктором с параметром типа String — надписью.

Добавим кнопку в панель содержимого нашего окна командами:

JButton newButton = new JButton(); getContentPane().add(newButton);

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

Класс Container (контейнер)

Элементы, которые содержат другие элементы, называются контейнерами. Все они являются потомками класса Container и наследуют от него ряд полезных методов:

add(Component component) — добавляет в контейнер элемент component ;

remove(Component component) — удаляет из контейнера элемент component ;

removeAll() — удаляет все элементы контейнера;

getComponentCount() — возвращает число элементов контейнера.

Кроме перечисленных в классе Container определено около двух десятков методов для управления набором компонентов, содержащихся в контейнере. Как видно, они похожи на методы класса-коллекции. Это неудивительно, ведь по сути контейнер и является коллекцией, но коллекцией особого рода — визуальной. Кроме хранения элементов контейнер занимается их пространственным расположением и прорисовкой. В частности, он имеет метод getComponentAt(int x, int y) , возвращающий компонент, в который попадает точка с заданными координатами (координаты отсчитываются от левого верхнего угла компонента) и ряд других. Мы не будем подробно рассматривать абстрактный контейнер, а сразу перейдем к его наиболее часто используемому потомку — классу JPanel .

Класс JPanel (панель)

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

В примере с кнопкой мы наблюдали, как добавленная на панель содержимого кнопка заняла все ее пространство. Это происходит не всегда. На самом деле у каждой панели есть так называемый менеджер размещения, который определяет стратегию взаимного расположения элементов, добавляемых на панель. Его можно изменить методом setLayout(LayoutManager manager) . Но чтобы передать в этот метод нужный параметр, необходимо знать, какими бывают менеджеры.


Менеджер последовательного размещения FlowLayout

Самый простой менеджер размещения — FlowLayout . Он размещает добавляемые на панель компоненты строго по очереди, строка за строкой, в зависимости от размеров панели. Как только очередной элемент не помещается в текущей строке, он переносится на следующую. Лучше всего пронаблюдать это на примере. Изменим конструктор класса SimpleWindow следующим образом:

Менеджеры расположения описаны в пакете java.awt. Не забывайте импортировать нужные классы.

Пронаблюдайте за поведением окна, появляющегося после запуска программы. Четыре кнопки в нем расположены как слова в текстовом редакторе (при выравнивании по центру). Эффект будет лучше заметен, если изменять размеры окна во время работы программы.

Проанализируем текст примера. Новый менеджер расположения FlowLayout создается конструктором без параметров. Обратите внимание, в программе не используется промежуточная переменная. То есть вместо двух команд:

FlowLayout newLayout = new FlowLayout(); panel.setLayout(newLayout);

Мы используем одну:

panel.setLayout( new FlowLayout());

Это вполне допустимо в тех случаях, когда в дальнейшем нам не потребуется обращаться к создаваемому объекту (что справедливо для данного примера). Мы создаем менеджер расположения, тут же привязываем его к панели — и все. Теперь панель и менеджер сами найдут друг с другом общий язык.

Панель хранит ссылку на своего менеджера и сама обращается к нему каждый раз, когда нужно рассчитать координаты элементов (это происходит при их добавлении, удалении, изменении размеров, а также при изменении размеров окна). В принципе, мы можем даже получить этого менеджера методом getLayout() класса JPanel , но, как правило, в этом вообще нет необходимости.

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

JPanel panel = new JPanel(); panel.setLayout( new FlowLayout());

Цукерберг рекомендует:  19 впечатляющих примеров использования текста в веб дизайне

JPanel panel = new JPanel( new FlowLayout());

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

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

Метод setContentPane(JPanel panel) позволяет заменить панель содержимого окна.

Менеджер граничного размещения BorderLayout

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

При добавлении элемента на панель с менеджером размещения BorderLayout , необходимо дополнительно указывать в методе add() , какая из областей имеется в виду. Для этого служат строки с названиями сторон света: «North» , «South» , «East» , «West» и «Center» . Но вместо них рекомендуется использовать константы, определенные в классе BorderLayout : NORTH , SOUTH , EAST , WEST и CENTER (поскольку в строке можно допустить ошибку и не заметить этого, а при попытке написать неправильно имя константы компилятор выдаст предупреждение). Если же использовать метод add() как обычно, с одним параметром, элемент будет добавлен в центр.

Панель содержимого имеет именно такое расположение, именно поэтому кнопка и занимала все окно целиком (она была добавлена в центральную область). Чтобы пронаблюдать эффект BorderLayout , добавим кнопки во все пять областей:

Эффект будет хорошо наблюдаться, если изменять размеры окна.

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

Менеджер табличного размещения GridLayout

GridLayout разбивает панель на ячейки одинаковой ширины и высоты (таким образом окно становится похожим на таблицу). Каждый элемент, добавляемый на панель с таким расположением, целиком занимает одну ячейку. Ячейки заполняются элементами по очереди, начиная с левой верхней.

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

Менеджер блочного размещения BoxLayout и класс Box

Менеджер BoxLayout размещает элементы на панели в строку или в столбец.

Обычно для работы с этим менеджером используют вспомогательный класс Box , представляющий собой панель, для которой уже настроено блочное размещение. Создается такая панель не конструктором, а одним из двух статических методов, определенных в классе Box : createHorizontalBox() и createVerticalBox() .

Элементы, добавленные на панель с блочным размещением, выстраиваются один за другим. Расстояние между элементами по умолчанию нулевое. Однако вместо компонента можно добавить невидимую «распорку», единственная задача которой — раздвигать соседние элементы, обеспечивая между ними заданное расстояние. Горизонтальная распорка создается статическим методом createHorizontalStrut(int width) , а вертикальная — методом createVerticalStrut(int height) . Оба метода определены в классе Box , а целочисленный параметр в каждом из них определяет размер распорки.

Кроме того, на такую панель можно добавить еще один специальный элемент — своеобразную «пружину». Если размер панели будет больше, чем необходимо для оптимального размещения всех элементов, те из них, которые способны растягиваться, будут стараться заполнить дополнительное пространство собой. Если же разместить среди элементов одну или несколько «пружин», дополнительное свободное пространство будет распределяться и в эти промежутки между элементами. Горизонтальная и вертикальная пружины создаются соответственно методами createHorizontalGlue() и createVerticalGlue() .

Понять особенности работы этого менеджера лучше на наглядном примере. Мы расположим четыре кнопки вертикально, поставив между двумя центральными «пружину», а между остальными — распорки в 10 пикселов.

Особенности выравнивания элементов

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

Однако при разработке окна программы может понадобиться, чтобы какие-то элементы были выровнены иначе, например, по правому краю или по центру. Для того, чтобы установить выравнивание любого визуального компонента (например, кнопки или панели), используются методы setAlignmentX(float alignment) — выравнивание по горизонтали и setAlignmentY(float alignment) — выравнивание по вертикали. В качестве параметра проще всего использовать константы, определенные в классе JComponent . Для выравнивания по горизонтали служат константы LEFT_ALIGNMENT (по левому краю), RIGHT_ALIGNMENT (по правому краю) и CENTER_ALIGNMENT (по центру). Для выравнивания по вертикали — BOTTOM_ALIGNMENT (по нижнему краю), TOP_ALIGNMENT (по верхнему краю) и CENTER_ALIGNMENT (по центру).

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

box.add( new JButton( «-» ));

JButton rightButton = new JButton( «-» ); rightButton.setAlignmentX(JComponent.RIGHT_ALIGNMENT); box.add(rightButton);

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

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

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

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

Параметр выравнивания на самом деле представляет собой вещественное число в диапазоне от 0 до 1. Он показывает, какая часть компонента окажется слева от линии выравнивания, т.е. в каких пропорциях компонент будет «разрезан». Константы LEFT_ALIGNMENT и TOP_ALIGNMENT на самом деле равны 0, RIGHT_ALIGNMENT и BOTTOM_ALIGNMENT равны 1, а CENTER_ALIGHNMENT — 0.5. Можно подставлять эти числа напрямую (хотя использование констант значительно повышает наглядность!), а можно выбрать любое другое число от 0 до 1 и настроить совершенно произвольное выравнивание.

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

Ручное размещение элементов

Если в качестве менеджера размещения панели установить null , элементы не будут расставляться автоматически. Координаты каждого элемента необходимо в этом случае указать явно, при этом они никак не зависят от размеров панели и от координат других элементов. По умолчанию координаты равны нулю (т.е. элемент расположен в левом верхнем углу панели). Размер элемента также необходимо задавать явно (в противном случае его ширина и высота будут равны нулю и элемент отображаться не будет).

Координаты элемента можно задать одним из следующих методов:

setLocation(int x, int y) ,

Эти методы работают аналогично, устанавливая левый верхний угол элемента в точку с заданными координатами. Разница в способе задания точки. Можно представить точку двумя целыми числами, а можно объектом класса Point . Класс Point по сути представляет собой ту же пару чисел, его конструктор имеет вид Point(int x, int y) . Получить доступ к отдельной координате можно методами getX() и getY() .

Можно задаться вопросом: зачем использовать класс Point , если можно просто передать пару чисел? Но дело в том, что многие полезные методы возвращают результат — координаты некоторой точки — в виде объекта этого класса. Например, метод getLocation() , возвращающий координаты элемента. Предположим, нам нужно поместить элемент b в точности в то место, которое занимает элемент a . Этого легко добиться одной строкой:

Размер элемента задается одним из двух методов:

setSize(int width, int height) ,

Эти методы работают одинаково — разница, как и в прошлый раз, в способе передачи параметра. Класс Dimension , аналогично классу Point , просто хранит два числа, имеет конструктор с двумя параметрами: Dimension(int width, int height) и позволяет получить доступ к своим составляющим — ширине и высоте — с помощью простых методов getWidth() и getHeigth() . Для того, чтобы получить текущий размер элемента, можно воспользоваться методом getSize() , возвращающего объект класса Dimension . Элемент b можно сделать точно такого же размера, как элемент a , выполнив команду:

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

Мы используем одну и ту же переменную button для обращения к обеим кнопкам (причем, второй раз ее описывать не нужно). В самом деле, осуществив все необходимые операции с первой кнопкой и зная, что обращаться к ней нам больше не понадобится, мы используем «освободившуюся» переменную для манипуляций со второй.

Автоматическое определение размеров компонентов

Если у панели есть любой менеджер размещения, она игнорирует явно заданные размеры и координаты всех своих элементов. В этом легко убедиться, заменив в предыдущем примере команду panel.setLayout( null ) на panel.setLayout( new FlowLayout()) . Менеджер размещения сам определяет координаты и размеры всех элементов.

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

Мы также отмечали, что в некоторых случаях компоненты стараются заполнить все доступное им пространство. Например, всю центральную область в случае менеджера BorderLayout или всю ячейку в менеджере GridLayout . А в панели с менеджером FlowLayout , напротив, элементы никогда не пытаются выйти за определенные границы. Рассмотрим, что это за границы.

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

Методы возвращают результат типа Dimension . Они запрограммированы в соответствующем классе. Например, у кнопки минимальный размер — нулевой, максимальный размер не ограничен, а предпочтительный зависит от надписи на кнопке (вычисляется как размер текста надписи плюс размеры полей).

Менеджер FlowLayout всегда устанавливает предпочтительные размеры элементов. Менеджер BorderLayout устанавливает предпочтительную ширину правого и левого, а также предпочтительную высоту верхнего и нижнего. Остальные размеры подгоняются под доступное пространство панели. Менеджер GridLayout пытается подогнать размеры всех элементов под размер ячеек. Менеджер BoxLayout ориентируется на предпочтительные размеры.

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

Всеми тремя размерами можно управлять с помощью соответствующим методов set:

Чаще всего используется простой прием, когда элементу «не рекомендуется» увеличиваться или уменьшаться относительно своих предпочтительных размеров. Это легко сделать командой:

«Упаковка» окна

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

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

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

Оцените работу этого метода, заменив в каждом из вышеприведенных примеров команду

Заметьте, что когда панель не имеет метода размещения, эта команда не работает (поскольку панель не имеет алгоритма для вычисления своего предпочтительного размера).

Упражнение

Как уже отмечалось, элементом панели может быть другая панель. Создайте панель с тремя кнопками и менеджером размещения FlowLayout и панель с двумя кнопками и менеджером размещения BoxLayout (горизонтальным). Разместите обе панели в главном окне (не изменяя менеджера размещения у панели содержимого): одну в центр, а другую вдоль любой стороны окна.

Рамки

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

Рамка панели устанавливается методом setBorder(Border border) . Параметром метода выступает рамка — объект класса Border . Это абстрактный класс, поэтому для создания рамки используются его наследники:

EmptyBorder — пустая рамка, позволяет создать отступы вокруг панели. Размеры отступов задаются в конструкторе четырьмя целыми числами.

TitledBorder — рамка с заголовком. Простейший конструктор имеет один параметр типа String (текст заголовка). Заголовок может размещаться вдоль любой стороны рамки, иметь различные начертания.

EtchedBorder — рамка с тиснением. Может быть вогнутой или выпуклой.

BevelBorder — объемная рамка (выпуклая или вогнутая). Можно настроить цвета, требуемые для получения объемных эффектов.

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

LineBorder — простая рамка, нарисованная сплошной линией. Можно выбирать цвет и толщину линии, скруглить углы.

MatteBorder — рамка из повторяющегося рисунка.

CompoundBorder — объединяет две рамки, передаваемые в качестве параметров конструктору в одну новую рамку.

Все перечисленные классы описаны в пакете javax.swing.border.

Рассмотрим пример. В этом примере мы создадим шесть панелей с различными рамками и разместим их в виде таблицы. Чтобы не описывать шесть раз процедуру создания новой панели, вынесем ее в отдельный метод:

private JPanel createPanel(Border border, String text)

Метод createPanel() создает панель с кнопкой во весь свой размер. В качестве параметра передается надпись на кнопке и рамка, которую необходимо добавить к панели. Рамка добавляется не напрямую, а путем композиции с пустой рамкой. Этот прием часто используется, чтобы рамка не прилипала к краю панели.

Теперь шесть раз воспользуемся этим методом в конструкторе окна программы.

Этот пример показывает, с помощью каких конструкторов создаются различные рамки и как они выглядят. В нем использованы два новых класса: Color и ImageIcon .

Класс Color предназначен для работы с цветом. В нем есть несколько констант, описывающих наиболее распространенные цвета. В частности, к таковым относится Color.ORANGE .

Класс ImageIcon описывает графическое изображение. Параметр его конструктора — это путь к файлу, из которого изображение может быть загружено. В примере используется относительное имя файла «1.gif». Чтобы объект ImageIcon был успешно создан, файл с таким именем должен быть помещен в папку проекта.

Менеджеры компоновки Layout в Swing

категория
Java
дата 15.06.2010
автор DimansB
голосов 22

Особенность компоновки GUI форм в Java заключается в том, что необходимо использовать менеджеры Layout. Они определяют размер и расположение компонентов, а так же при изменении размера окна пропорционально масштабируют компоненты формы, эта особенность обусловлена тем, что код Java может запускаться на разных ОС с разными разрешением экрана, поэтому могут возникнуть проблемы при их отображении. Менеджеры компоновки Layout в Swing применяются для компонентов(JFrame,JPanel,JButton и др.).

Для установки менеджера компоновки необходимо воспользоваться методом setLayout(), который определен в классе Container.В данной статье рассмотрены стандартные менеджеры компоновки AWT и Swing, если вам нужна более подробная информация по какому-то менеджеру отдельно, то я рекомендую вам обратиться к документации JAVA.

Итак, начнем наш обзор менеджеров компоновки.

BorderLayout

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

BorderLayout.NORTH (верх)
BorderLayout.SOUTH (низ)
BorderLayout.EAST (справа)
BorderLayout.WEST (слева)
BorderLayout.CENTER (заполнить середину до других компонент или до краев)

По умолчанию принимается константа Center.
Пример BorderLayout.

FlowLayout

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

Пример использования FlowLayout.

GridLayout

GridLayout это менеджер, который помещает компоненты в таблицу.

GridBagLayout

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

BoxLayout

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

CardLayout

Этот менеджер предназначен для использования нескольких менеджеров.

GroupLayout

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

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

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

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

SpringLayout

SpringLayout очень гибкий менеджер но и очень сложный для ручного кодирования изначально проектировался для использование в средах автоматического проектирования GUI например таких как NetBeans.Особенности его работы заключается в установки отношении между краями компонентов.

Если по каким либо причинам вам необходимо самостоятельно расположить компоненты, то можно воспользоваться менеджером NullLayout установив в метод setLayout() значение null.

Если Вам понравилась статья, проголосуйте за нее

Swing scrollpane уведомляет, когда вы прокручиваете мимо определенной точки

Эй, чуваки. Мне нужны предложения о том, как лучше всего реализовать что-то, пожалуйста. Моя программа:

У меня есть свинг-программа, которая читает файл с несколькими записями разных типов. Я прочитал эти записи в java-объекты, создал из них JTables с их заголовками и содержимым (чтобы каждая таблица имела только заголовок и 1 запись), добавил эти таблицы на панель и добавил панель на панель прокрутки. Есть много записей, около 70000, поэтому я не могу загрузить все в память сразу.

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

Это подводит меня к моим вопросам

1) Я не уверен, как уведомить себя, что прокрутил мимо определенной точки. Итак, учитывая, что у меня есть 100 JTables, прикрепленных к JPanel, прикрепленной к области прокрутки. Как я могу добавить слушателя, чтобы уведомить, когда пользователь прокрутил, скажем, Jtable 50 для аргументов ради.


2) Другая проблема, которая у меня есть, связана с тем, как я помещаю свои таблицы в панель. Я использую свингер, как показано ниже:

Я передаю свои объекты записи работнику качания. Затем он преобразует запись в JTable со всем необходимым форматированием, а затем добавляет их на панель. Иногда он вызывает команду validate для отображения таблиц, иначе он их не отображает. (не уверен, что есть лучший способ сделать это?)

Так что мой вопрос связан с прокруткой. Если я сначала передаю только 100 из 70000 записей своему рабочему, это, очевидно, создает полосу прокрутки, думая, что есть только 100 записей. Таким образом, полоса прокрутки не очень мала (то есть ясно, что вы не можете прокрутить очень далеко). Что я на самом деле хочу, так это то, что, хотя я показываю только 100 записей, я хочу, чтобы размер полосы прокрутки составлял 70000 записей, чтобы вы могли видеть размер записей на основе полосы прокрутки. Если вы перетаскиваете полосу прокрутки в какую-то точку внизу, ее нужно потянуть и отобразить эти записи. Как я могу создать размер моей полосы прокрутки больше, чем фактические компоненты в ней, но на основе их размера?

IT-ЗАМЕТКИ

Инструменты пользователя

Инструменты сайта

Содержание

AWT и Swing

В первой версии языка Java для работы с графикой было только библиотека AWT. Эта библиотека – простой набор классов, таких, как Button(кнопка),TextField (текстовое поле), Label (текстовая метка или иконка) и другие.
Вскоре была создана более совершенная библиотека, которую назвали Swing. Она так же включает в себя кнопки,текстовые поля и другие элементы управления графическими приложениями. Названия компонентов этой библиотеке начинается с буквы J. Например JButton, JTextField и т.д.

Работать в Swing лучше, быстрей и удобней.

Основные элементы Swing

Вот некоторые основные объекты, из которых состоят Swing приложения:

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

JFrame является главным окном для размещения компонентов и представляет их пользователю.

Панель

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

У каждой панели есть менеджер размещения, который определяет стратегию взаимного расположения элементов, добавляемых на панель. Его можно изменить методом setLayout(LayoutManager manager).

Оконные элементы управления

Класс JComponent

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

Метка JLabel

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

Кнопка JButton

Компоненты JToggleButton, JCheckBox, JRadioButton

Компонент JToggleButton представляет собой кнопку, которая может находиться в двух состояниях: нажатом и отпущенном.
Когда пользователь щелкает мышкой по такой кнопке, она изменяет свое состояние. Именно таким образом ведут себя кнопки форматирования на инструментальной панели текстового редактора. Кнопка [I] не только устанавливает или убирает курсивное начертание в выделенном тексте, но и сигнализирует о его наличии или отсутствии.

От класса JToggleButton унаследован класс JCheckBox — флажок.
Этот класс имеет точно такой же набор конструкторов и методов, т.е. не расширяет функциональность предка. Единственное различие между ними — во внешнем виде: JCheckBox выглядит не как кнопка, а как небольшой квадратик, в котором можно поставить или убрать галочку.

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

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

Текстовое поле JTextField

Для создания текстового поля чаще всего используются конструкторы:

Поле для ввода пароля JPasswordField

JPasswordField является прямым потомком JTextField, поэтому для него справедливо все сказанное выше. JPasswordField является прямым потомком JTextField, поэтому для него справедливо все сказанное выше.

Область для ввода текста JTextArea

JTextArea также является потомком JTextField и наследует все его методы.

Панель прокрутки JScrollPane

JScrollPane — панель прокрутки. Чаще всего она просто «надевается» на требуемый объект посредством собственного конструктора, принимающего этот объект в качестве параметра. Например, чтобы текстовая область textArea из предыдущего примера обрела полосы прокрутки, необходимо заменить команду

Инструментальная панель JToolBar

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

Выпадающий список JComboBox

Выпадающий список — весьма распространенный элемент управления. Он содержит множество вариантов, из которых пользователь может выбрать один и только один, либо (если выпадающий список это позволяет) ввести свой собственный.

Ползунок JSl >

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

Панель со вкладками JTabbedPane

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

Список JList

Список содержит группу элементов, аналогично выпадающему списку JComboBox, но обладает двумя отличительными особенностями. Во-первых, на экране видны одновременно несколько элементов списка. Во-вторых, пользователь может выбрать в списке не один элемент, а несколько (если установлен соответствующий режим выделения).

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

JTable Таблицы

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

JFileChooser для выбора файла

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

JProgressBar полоса загрузки

JMenuBar

Стандартные диалоговые окна

Менеджер размещения

В некоторых старомодных языках программирования необходимо было указывать координаты и размеры каждого компонента окна. Это работало хорошо, если было известно разрешающая способность экрана каждого пользователя. В Java есть схемы размещения (Layout Managers) , которые позволяют разместить компоненты на экране, не зная точных позиций компонентов. Схемы гарантируют, что та часть интерфейса, за которую они отвечают, будет выглядеть правильно в не зависимости от размеров окна и разрешения экрана.

Менеджер последовательного размещения FlowLayout

Менеджер граничного размещения BorderLayout

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

При добавлении элемента на панель с менеджером размещения BorderLayout, необходимо дополнительно указывать в методе add(), какая из областей имеется в виду. Для этого служат строки с названиями сторон света: «North», «South», «East», «West» и «Center». Но вместо них рекомендуется использовать константы, определенные в классе BorderLayout: NORTH, SOUTH, EAST, WEST и CENTER (поскольку в строке можно допустить ошибку и не заметить этого, а при попытке написать неправильно имя константы компилятор выдаст предупреждение).

Менеджер табличного размещения Gr >

GridLayout разбивает панель на ячейки одинаковой ширины и высоты (таким образом окно становится похожим на таблицу). Каждый элемент, добавляемый на панель с таким расположением, целиком занимает одну ячейку. Ячейки заполняются элементами по очереди, начиная с левой верхней.

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

Менеджер блочного размещения BoxLayout и класс Box

Менеджер BoxLayout размещает элементы на панели в строку или в столбец. Обычно для работы с этим менеджером используют вспомогательный класс Box, представляющий собой панель, для которой уже настроено блочное размещение. Создается такая панель не конструктором, а одним из двух статических методов, определенных в классе Box: createHorizontalBox() и createVerticalBox().

Элементы, добавленные на панель с блочным размещением, выстраиваются один за другим. Расстояние между элементами по умолчанию нулевое. Однако вместо компонента можно добавить невидимую «распорку», единственная задача которой — раздвигать соседние элементы, обеспечивая между ними заданное расстояние.

Горизонтальная распорка создается статическим методом createHorizontalStrut(int width), а вертикальная — методом createVerticalStrut(int height). Оба метода определены в классе Box, а целочисленный параметр в каждом из них определяет размер распорки.

Ручное размещение элементов

Если в качестве менеджера размещения панели установить null, элементы не будут расставляться автоматически. Координаты каждого элемента необходимо в этом случае указать явно, при этом они никак не зависят от размеров панели и от координат других элементов. По умолчанию координаты равны нулю (т.е. элемент расположен в левом верхнем углу панели). Размер элемента также необходимо задавать явно (в противном случае его ширина и высота будут равны нулю и элемент отображаться не будет). Координаты элемента можно задать одним из следующих методов:

Использование полосы прокрутки с абсолютным расположением в свинге

Я не может использовать полосы прокрутки с абсолютным макетом в Swing.

Я не хочу использовать этот макет , но я должен отображать динамические объекты на моей панели по нажатию кнопки и выровнять их с помощью setBounds которой можно сделать , используя только этот макет (я думаю).

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

Вы угадали неправильно.

Смотрите этот графический интерфейс , который может не только изменить PLAFs во время выполнения, но и динамически добавлять новые компоненты 1 . Нажмите для..

Add Another Label

  1. Этот пример добавляет новые метки к GridLayout — но принцип одинаков для любого макета (или любого компонента).
Цукерберг рекомендует:  Тест по C#. Средний уровень

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

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

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

Scroll « JList « Java Swing Q&A

1. Java JList scroll to selected item stackoverflow.com

I have a jlist with a lot of items in it, of which one is selected. I would like to scroll to the selected item in this jlist, so the user .

2. JScrollPane and JList auto scroll stackoverflow.com

I’ve got the next code:

listModel = new DefaultListModel(); listModel.addElement(dateFormat.format(new Date()) + «: Msg1»); messageList = new JList(listModel); messageList.setLayoutOrientation(JList.VERTICAL); .

3. scroll/search JList when user starts typing stackoverflow.com

I would like to implement one of the fanciest features I every now and then. I would like to allow a user to click on a JList and if words are .

4. Unable to programatically scroll to last item in JList stackoverflow.com

I have a JList nested inside of a JScrollPane. When I add items to the JList, I want the JScrollPane to automatically scroll to the bottom of the JList so .

5. JList,JScrollPane stackoverflow.com

My JList has >100 values. when the screen is loaded the i have set the selected index of the list to 50 and added the JList to a JScrollPane. the value .

6. JList is getting bad while auto scrolling and auto selecting (GUI issue) stackoverflow.com

I’ve created a log for checking proxys. This log shows me, which proxy is already in use (by selecting item). And the problem is that when log is auto scrolling, and .

7. Jlist scrolling coderanch.com

8. Can you add a Scroll Bar to a JList? forums.oracle.com

I have a Pane with a JList on it and the items in it may or may not fit in the 100 pixels that the JList is set for. If there is more they just get cut off. Is there a way that I can add some sort of scroll bar to the JList? thanks, Lateralus

9. JList update in a Scroll Pane forums.oracle.com

10. JList Scrolling Lags forums.oracle.com

I create a Jlist of JLabels, each contains an ImageIcon about 200×200 pixels and some text. I need that JList to scroll through close to 100 images. But when I do this, the scrolling really lags. Is there another way I can do this so that scrolling is smooth? Thanks Message was edited by: africamp

11. JList SetSelectedIndex doesn’t scroll to index’s position forums.oracle.com

Hi. My program simulates a microprocessor and it has memory locations and a list of instructions. As the user clicks the button to execute the next instruction, I have it so the next instruction to be executed is highlighted using JList’s setSelectedIndex(index) method. Unfortunately, this simply highlights the line in the list that is at the index. Since my lists can .

Введение в Swing

Описание: Это практическое введение в Swing — первая часть серии по Swing-программированию, состоящей из двух частей. В данном руководстве рассмотрены основные компоненты библиотеки Swing. Java-программист и любитель Swing Майкл Абернети рассказывает об основных строительных блоках и о процессе создания простого, но функционального Swing-приложения.

Содержание

Перед началом работы

О данном руководстве

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

Во время работы с данным руководством вы изучите все начальные компоненты Swing; под начальными компонентами я понимаю те компоненты, используя которые можно создавать простые пользовательские интерфейсы (UI). Вы узнаете, как использовать базовые методы для установки их свойств, и как эти Swing-компоненты взаимодействуют с другими компонентами. Вы также прочтете о других UI-концепциях, необходимых для полного знания Swing, включая схемы, события/прослушиватели и модели данных. К концу руководства вы должны уметь создавать простое Swing-приложение.

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

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

Загрузка инструментальных средств и исходных кодов

Для работы с данным руководством вам необходимо следующее программное обеспечение:

  • JDK 5.0.
  • IDE или текстовый редактор. Я рекомендую Eclipse (ссылки на дополнительную информацию по Eclipse можно найти в разделе Ресурсы).
  • swing1.jar для системы резервирования билетов.

Введение в Swing

Введение в UI

Перед началом изучения Swing вы, как настоящий новичок, должны задать вопрос, что такое UI? Ответ для новичков — это «пользовательский интерфейс». Но поскольку цель данного руководства заключается в том, чтобы вы больше не были новичком, нам нужно более широкое определение, чем это.

Итак, я опять задаю вопрос: что такое UI? Вы могли бы определить его как кнопки, на которые нажимаете, поле адреса, в которое вводите информацию, и окна, которые открываете и закрываете. Все это — элементы UI, но это не только вещи, которые вы видите на экране. Мышка, клавиатура, громкость музыки, цвета экрана, используемые шрифты и расположение объекта по отношению к другому объекту — все это тоже составляет UI. Вообще говоря, любой объект, принимающий участие во взаимодействии пользователя и компьютера, является частью UI. Это кажется таким простым, что вы, должно быть, удивитесь тому, как много людей и корпораций занимаются этим годами. Действительно, сейчас есть дисциплины в колледжах, полностью посвященные этому взаимодействию.

Роль Swing

Технология Swing — это UI Java-платформы. Она выступает как программное обеспечение, управляющее всем взаимодействием пользователя и компьютера. По существу, она служит посредником между пользователем и внутренностями компьютера. Как Swing делает это? Он предоставляет механизмы для управления аспектами UI, описанными в предыдущем разделе:

  • Клавиатура: Swing предоставляет способ перехвата пользовательского ввода.
  • Цвета: Swing предоставляет способ менять цвета, которые вы видите на экране.
  • Текстовое поле для ввода: Swing предоставляет текстовые компоненты для обработки всех повседневных задач.
  • Громкость музыки: Ну что ж … Swing не совершенен.

В любом случае Swing предоставляет вам все инструменты, необходимые для создания вашего собственного UI.

Swing идет даже на шаг дальше и реализует известный шаблон проектирования c основными принципами UI. Этот шаблон проектирования называется Модель-Представление-Контроллер (Model-View-Controller — MVC) и стремится «разделить роли». MVC хранит код, ответственный за внешний вид чего-нибудь, отдельно от кода, обрабатывающего данные, и отдельно от кода, реагирующего на взаимодействие и выполняющего изменения.


Вы смущены? Будет легче, если я вам приведу не технический пример этого шаблона проектирования из реального мира. Представьте показ мод. Считайте, что это ваш UI и вообразите одежду данными, компьютерной информацией, которую вы представляете вашему пользователю. Теперь представьте, что этот показ мод состоит только из одного человека. Этот человек спроектировал одежду, модифицировал ее и показал на подиуме. Это не выглядит хорошо продуманным или эффективным проектом.

Теперь представьте себе этот же показ мод, использующий шаблон проектирования MVC. Вместо одного человека, делающего все, роли разделяются. Модели для показа (естественно, не путайте с моделью как акронимом MVC) представляют одежду. Они выступают как представление. Они знают, как правильно показать одежду (данные), но абсолютно не знают, как создавать или проектировать ее. C другой стороны, дизайнер одежды работает за кулисами, изменяя ее при необходимости. Дизайнер выступает в роли контроллера. Это человек не знает, как пройтись по подиуму, но может создавать и изменять одежду. Дизайнер и модели работают с одеждой независимо друг от друга и имеют свою область компетенции.

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

JComponent

Базовым строительным блоком всей библиотеки визуальных компонентов Swing является JComponent . Это суперкласс каждого компонента. Он является абстрактным классом, поэтому в действительности вы не можете создать JComponent , но он содержит буквально сотни функций, которые каждый компонент Swing может использовать как результат иерархии классов. Очевидно, что некоторые концепции более важны, чем другие, но для целей этого руководства важными являются:

  • JComponent — базовый класс не только для Swing-компонентов, но также и для пользовательских компонентов. (более подробная информация приведена в руководстве «Swing для среднего уровня«).
  • Он обеспечивает инфраструктуру окрашивания для всех компонентов — нечто, становящееся удобным для пользовательских компонентов.
  • Он знает, как обрабатывать все нажатия клавиш на клавиатуре. Подклассы, следовательно, должны только прослушивать определенные клавиши.
  • Он содержит метод add() , который позволяет вам добавить другие JComponent . Этим способом вы можете добавить любой Swing-компонент к любому другому Swing-компоненту для создания вложенных компонентов (например, JPanel, содержащую JButton, или даже более причудливые комбинации, например JMenu, содержащее JButton).

Простые Swing-виджеты

JLabel

Самым основным компонентом в библиотеке Swing является JLabel. Он делает именно то, чего вы от него ожидаете: располагается в нужном месте, улучшает вид приложения и описывает другие компоненты. На приведенном ниже изображении показан JLabel в действии:

Не очень впечатляюще, но все равно полезно. Фактически, вы используете компоненты JLabel по всему приложению не только как текстовые описания, но и как графические описания. Когда бы вы ни увидели изображение в Swing-приложении, есть шанс, что это JLabel. У JLabel не много методов для новичков в Swing, кроме, возможно, ожидаемых вами. К основным методам относится установка текста, изображения, выравнивания и других компонентов, которые описывает метка:

  • get/setText() : Получить/установить текст в метке.
  • get/setIcon() : Получить/установить изображение в метке.
  • get/setHorizontalAlignment() : Получить/установить горизонтальную позицию текста.
  • get/setVerticalAlignment() : Получить/установить вертикальную позицию текста.
  • get/setDisplayedMnemonic() : Получить/установить мнемонику (подчеркнутый символ) для метки.
  • get/setLabelFor() : Получить/установить компонент, к которому присоединена данная метка; когда пользователь нажимает комбинацию клавиш Alt+мнемоника, фокус перемещается на указанный компонент.

JButton

Основным активным компонентом в Swing является JButton, кнопка, которую вы видите (с надписями OK и Cancel) в каждом окне; он делает именно то, что ожидается от кнопки — вы нажимаете на нее, и что-то происходит. Что именно происходит? Да, вы должны определить это (дополнительная информация приведена в разделе События). JButton в действии выглядит следующим образом:

Методы, используемые для изменения свойств JButton, аналогичны методам JLabel (вы обнаружите, что они аналогичны для большинства Swing-компонентов). Они управляют текстом, изображениями и ориентацией:

  • get/setText() : Получить/установить текст в кнопке.
  • get/setIcon() : Получить/установить изображение в кнопке.
  • get/setHorizontalAlignment() : Получить/установить горизонтальную позицию текста.
  • get/setVerticalAlignment() : Получить/установить вертикальную позицию текста.
  • get/setDisplayedMnenomic() : Получить/установить мнемонику (подчеркнутый символ), которая в комбинации с кнопкой Alt вызывает нажатие кнопки.

Кроме этих методов я познакомлю вас с еще одной группой методов, которые содержит JButton. Эти методы используют все различные состояния кнопки. Состояние — это свойство, описывающее компонент, обычно имеющее значение true/false. В случае с JButton он имеет следующие возможные состояния: активная/неактивная, выбранная/не выбранная, мышка сверху/мышки нет, нажата/отжата. Кроме того, вы можете комбинировать состояния, например: кнопка может быть выбрана и над ней находится мышка. Сейчас вы, возможно, спрашиваете себя, для чего мне все эти состояния. В качестве примера переместитесь к кнопке Back вашего браузера. Обратите внимание на то, как меняется изображение при наведении на нее указателя мышки, и как оно меняется при нажатии на кнопку. Эта кнопка использует различные состояния. Использование различных изображений для каждого состояния является популярным и очень эффективным способом отображать действия пользователей. Методами состояния для JButton являются:

  • get/setDisabledIcon()
  • get/setDisabledSelectedIcon()
  • get/setIcon()
  • get/setPressedIcon()
  • get/setRolloverIcon()
  • get/setRolloverSelectedIcon()
  • get/setSelectedIcon()

JTextField

Основным текстовым компонентом в Swing является JTextField; он позволяет пользователям вводить текст в UI. Я уверен, что вы знакомы с текстовым полем; вы должны были использовать его при вводе имени пользователя и пароля для получения данного руководства. Вы вводите, удаляете, выделяете текст, перемещаете курсор — Swing заботится обо всем, что вы делаете. Как UI-разработчику вам действительно не нужно делать много для того, чтобы использовать возможности JTextField.

В любом случае, вот как выглядит JTextField в действии:

Вы должны интересоваться только одним методом при работе с JTextField, и это должен быть, очевидно, метод, устанавливающий текст: get/setText() . Этот метод получает/устанавливает текст внутри JTextField.

JFrame

Пока я рассмотрел три основных строительных блока Swing: метку, кнопку и текстовое поле; теперь вы должны куда-то поместить их. Они не могут просто летать по экрану в надежде на то, что пользователь знает, как работать с ними. Класс JFrame делает именно это — он является контейнером, позволяющим добавлять к себе другие компоненты для их организации и предоставления пользователю. Он имеет много других бонусов, но я считаю, что легче всего сначала на него посмотреть:

JFrame

JFrame на самом деле делает больше, чем просто позволяет вам размещать компоненты на нем и предоставлять их пользователю. Несмотря на всю его кажущуюся простоту, он фактически является одним из самых сложных компонентов в Swing-пакетах. Говоря очень упрощенно, JFrame выступает в качестве моста между независимыми от OS Swing-частями и реальной OS, на которой они работают. JFrame регистрируется как окно в OS и таким образом получает многие из знакомых свойств окна операционной системы: минимизация/максимизация, изменение размеров и перемещение. Хотя для целей данного руководства совершенно достаточно считать JFrame палитрой, на которой вы размещаете компоненты. Некоторыми из методов, которые вы можете вызвать с JFrame для изменения его свойств, являются:

  • get/setTitle() : Получить/установить заголовок фрейма.
  • get/setState() : Получить/установить состояние фрейма (минимизировать, максимизировать и т.д.).
  • is/setVisible() : Получить/установить видимость фрейма, другими словами, отображение на экране.
  • get/setLocation() : Получить/установить месторасположение в окне, где фрейм должен появиться.
  • get/setSize() : Получить/установить размер фрейма.
  • add() : Добавить компоненты к фрейму.

Простое приложение

Как и во всех руководствах «Введение в х», у нас есть необходимый элемент — демонстрация HelloWorld. Однако этот пример полезен не только для того, чтобы увидеть, как работает Swing-приложение, но также и для проверки правильности установки системы. Если это простое приложение работает, любое другое тоже будет работать нормально. На приведенном ниже рисунке показан завершенный пример:

Пример HelloWorld

Первым вашим действием является создание класса. Swing-приложение, которое размещает компоненты в JFrame, должно быть подклассом класса JFrame , например так:

Сделав так, вы получаете все свойства JFrame, описанные выше, и, что самое важное, поддержку окна в OS. Следующий шаг — размещение компонентов на экране. В данном примере мы используем схему null. Более подробно о схемах и менеджерах схем вы узнаете позже. Для этого примера числа указывают позицию в JFrame в пикселях:

Теперь, когда компоненты размещены в JFrame, необходимо, чтобы JFrame показался на экране; также нужно сделать ваше приложение запускаемым. Как и во всех Java-приложениях, вы должны добавить метод main, для того чтобы сделать Swing-приложение запускаемым. Внутри этого метода main необходимо создать объект вашего приложения HelloWorld и вызвать setVisible() :

Это все, что нужно для создания приложения!

Дополнительные Swing-виджеты

JComboBox

В этом разделе мы рассмотрим все остальные компоненты в библиотеке Swing: как их использовать, и на что они похожи. Это даст лучшее представление о той мощи, которую дает вам (как UI-разработчику) Swing.

Мы начнем с JComboBox. Комбинированный список является знакомым ниспадающим списком элементов, в котором пользователи могут либо выбрать ноль или один (и только один) элемент из списка. В некоторых версиях комбинированного списка вы можете ввести ваш собственный вариант. Хорошим примером является адресная строка вашего браузера; это комбинированный список, позволяющий ввести собственный вариант. Вот как выглядит JComboBox в Swing:

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

  • addItem() : Добавить элемент к JComboBox.
  • get/setSelectedIndex() : Получить/установить индекс выбранного элемента в JComboBox.
  • get/setSelectedItem() : Получить/установить выбранный объект.
  • removeAllItems() : Удалить все объекты из JComboBox.
  • remoteItem() : Удалить конкретный объект из JComboBox.

JPasswordField

Разновидностью JTextField является JPasswordField, который позволяет скрывать все символы, отображаемые на экране в текстовом поле. В конце концов, что это за пароль, который могут видеть все желающие в то время, когда вы его вводите? Возможно, это вообще не пароль, и в настоящее время, когда ваши персональные данные очень важны, вы должны использовать все возможности по их защите, которые можете получить. Вот как JPasswordField выглядит в Swing:

Дополнительные «защищенные» методы JPasswordField незначительно меняют свое поведение по сравнению с JTextField, для того чтобы вы не смогли прочитать текст:

  • get/setEchoChar() : Получить/установить символ, который появляется в JPasswordField при вводе текста. При получении пароля символ «echo» не возвращается; вместо него возвращается реальный символ.
  • getText() : Вы не должны использовать эту функцию, поскольку она имеет некоторые проблемы с защитой (для интересующихся — String хранится в оперативной памяти, и возможный дамп кучи может открыть пароль).
  • getPassword() : Это корректный метод для получения пароля из JPasswordField, поскольку возвращает массив char[] , содержащий пароль. Для гарантирования нормальной защищенности массив должен быть очищен в 0, для того чтобы он не оставался в оперативной памяти.

JCheckBox/JRadioButton

Компоненты JCheckBox и JRadioButton предоставляют пользователю варианты для выбора, обычно в многовариантном формате. В чем отличия? С практической точки зрения они одинаковы. Их поведение одинаково. Однако в обычной UI-практике они имеют небольшое различие. JRadioButton обычно группируются вместе для предоставления пользователю вопроса с принудительным ответом (ответы взаимоисключающие — может быть только один ответ на вопрос). Поведение JRadioButton заставляет делать именно так. Как только вы выбрали JRadioButton, вы не можете снять его отметку до тех пор, пока не выберете другой вариант из группы. JCheckBox работает иначе. Он позволяет отмечать/снимать отметку с варианта в любое время и выбирать несколько ответов на вопрос.

Вот пример. На вопрос «Вы юноша или девушка?» есть два уникальных варианта ответа: «Юноша» или «Девушка». Пользователь должен выбрать один и не может выбрать оба. С другой стороны, на вопрос «Каково ваше хобби?» можно дать несколько ответов: «Бег», «Сон» или «Чтение».

Классом, который позволяет группировать вместе компоненты JCheckBox или JRadioButton, является класс ButtonGroup . Он позволяет группировать варианты (например, «Юноша» и «Девушка») таким образом, что при выборе одного, с другого отметка автоматически снимается.

Вот как JCheckBox и JRadioButton выглядят в Swing:

Важными методами ButtonGroup, которые стоит запомнить, являются:

  • add() : Добавить JCheckBox или JRadioButton к ButtonGroup.
  • getElements() : Получить все компоненты в ButtonGroup, для того чтобы можно было выполнить итерацию по ним для поиска выбранного.

JMenu/JMenuItem/JMenuBar

Компоненты JMenu, JMenuItem и JMenuBar являются главными строительными блоками для разработки системы меню в вашем JFrame. Основой любой системы меню является JMenuBar. Он простой и скучный, но он необходим, поскольку каждый JMenu и JMenuItem создается с ним. Для присоединения JMenuBar к JFrame используется метод setJMenuBar() . После его закрепления в JFrame вы можете добавлять все меню, подменю и элементы меню, какие хотите.

Различие JMenu/JMenuItem, возможно, очевидно, но фактически оно скрыто внутри и как раз не является очевидным. Если вы посмотрите на иерархию классов, JMenu является подклассом JMenuItem . Однако по внешнему виду они имеют отличие: JMenu используется для содержания других JMenuItem и JMenu; JMenuItem при выборе активизирует действие.

JMenuItem также поддерживает сокращенные клавиатурные команды. Как и большинство приложений, которые вы используете, Swing-приложения позволяют нажать Ctrl+(клавиша) для активизации действия, аналогично нажатию соответствующего элемента меню. Вспомните Ctrl+X и Ctrl+V, которые вы используете для копирования и вставки.

Кроме того, JMenu и JMenuItem поддерживают мнемоники. Вы можете использовать клавишу Alt вместе с буквой, назначенной меню в качестве мнемоники (например, нажатие Alt+F, а затем Alt+x закрывает приложение в Windows).

Вот как выглядят JMenuBar с компонентами JMenu и JMenuItem в Swing:

Важными методами, которые вам нужны в этих классах, являются:

  • JMenuItem и JMenu:
    • get/setAccelerator() : Получить/установить комбинацию Ctrl+клавиша, используемую в качестве клавиатурного сокращения.
    • get/setText() : Получить/установить текст для меню.
    • get/setIcon() : Получить/установить изображение, используемое в меню.
  • Только JMenu:
    • add() : Добавить еще один JMenu или JMenuItem к JMenu (создание вложенного меню).

JSlider

Компонент JSlider используется в приложении для изменения числового значения. Это быстрый и простой способ позволить пользователям визуально получить ответную реакцию не только на их текущий выбор, но увидеть диапазон допустимых значений. Подумайте, вы могли бы предоставить текстовое поле и позволить пользователю ввести значение, но тогда у вас добавляется лишняя работа — вы должны гарантировать, что введенное значение является числом, которое попадает в требуемый диапазон. В качестве примера представьте, что у вас есть финансовый Web-сайт, который запрашивает желаемый процент инвестиций в акции. Вы должны проверять вводимые в текстовое поле значения, для того чтобы гарантировать, что они являются числом и находятся в диапазоне от 0 до 100. Если вы вместо этого используете JSlider, введенные значения гарантировано будут числами в требуемом диапазоне.

В Swing JSlider выглядит следующим образом:

Важными методами в JSlider являются:

  • get/setMinimum() : Получить/установить минимальное значение, которое вы можете выбрать.
  • get/setMaximum() : Получить/установить максимальное значение, которое вы можете выбрать.
  • get/setOrientation() : Получить/установить ориентацию JSlider (вверх/вниз или вправо/влево).
  • get/setValue() : Получить/установить начальное значение JSlider.

JSpinner

Во многом аналогично JSlider вы можете использовать JSpinner, для того чтобы позволить пользователям выбирать целочисленное значение. Одним важным преимуществом является его компактный размер по сравнению с JSlider. Хотя недостатком является то, что вы не можете легко установить его границы.

Однако сравнение этих двух компонентов здесь заканчивается. JSpinner намного более гибок и может быть использован для выбора из любой группы значений. Кроме выбора чисел он может быть использован для выбора дат, имен, цветов, чего-угодно. Это делает JSpinner чрезвычайно мощным, позволяя вам предоставлять компонент, содержащий только предопределенные варианты. В этом он аналогичен JComboBox, хотя их использование не должно быть взаимозаменяемо. Вы должны использовать JSpinner только для логически последовательных вариантов — числа и даты идеально подходят для этого. JComboBox, с другой стороны, более хороший выбор для представления кажущихся случайными вариантов, которые не имеют взаимосвязи между одним вариантом и следующим.

JSpinner выглядит так:

Важными методами являются:

  • get/setValue() : Получить/установить начальное значение JSpinner, которое в базовом случае должно быть целым числом.
  • getNextValue() : Получить следующее значение, которое будет выбрано после нажатия клавиши управления курсором «стрелка вверх».
  • getPreviousValue() : Получить предыдущее значение, которое будет выбрано после нажатия клавиши управления курсором «стрелка вниз».

JToolBar

Компонент JToolBar выступает как палитра для других компонентов (JButtons, JComboBoxes и т.д.), которые совместно образуют панели инструментов, встречающиеся в большинстве приложений. Панели инструментов позволяют программе размещать часто используемые команды в удобном месте и группировать их. Часто, но не всегда, кнопки панели инструментов соответствуют командам в меню. Хотя это и не обязательно, но применение панелей стало общепринятой практикой, и вы тоже должны обращать на них внимание.

JToolBar также предлагает еще одну функцию, которую вы встречали в других панелях инструментов: способность «перемещаться» (то есть, становится отдельным фреймом над главным фреймом).

Ниже показан не перемещающийся JToolBar:

Важным методом JToolBar является is/setFloatable() , который получает/устанавливает свойство: может ли JToolBar перемещаться.

JToolTip

Вы, возможно, встречали JToolTip повсюду, но никогда не знали, как они называются. Они похожи на пластиковые концы ваших шнурков — они повсюду, но вы не знаете правильного названия (они называются aglet (пистон), если кому интересно). JToolTip — это небольшие «пузырьки», которые всплывают тогда, когда вы наводите и держите курсор мышки над чем-нибудь. Они могут быть очень полезны в приложениях, предоставляя подсказки для элементов, детализируя информацию или даже показывая полный текст элемента в сжатых UI. Они активизируются в Swing, если оставить курсор мышки над компонентом на определенное количество времени; обычно они появляются примерно через секунду после остановки мышки и остаются видимыми до тех пор, пока курсор остается над компонентом.

Компоненты JToolTip легко использовать. Метод setToolTip() является методом класса JComponent, то есть, каждый Swing-компонент может иметь всплывающую подсказку, связанную с ним. Хотя JToolTip и сам является Swing-классом, он, фактически, не предоставляет в настоящее время дополнительной функциональности и не должен создаваться. Вы можете обратиться к нему и использовать, вызывая функцию setToolTip() в JComponent.

Вот как выглядит JToolTip:

JOptionPane

Компонент JOptionPane — это своего рода «ускоряющий» класс в Swing. Часто, как UI-разработчик, вы хотели бы предоставить быстрое сообщение для ваших пользователей, говоря им об ошибке или выдавая какую-нибудь другую информацию. Возможно, вы хотели бы быстро получить некоторые данные, например, имя или номер. В Swing класс JOptionPane предоставляет возможность выполнить эти рутинные задачи. Вместо того, чтобы каждый раз изобретать колесо, Swing предоставляет базовый, но полезный класс для предоставления UI-разработчикам способа выдачи и получения простых сообщений.

Вот внешний вид JOptionPane:

Определенного рода хитростью при работе с JOptionPane являются все его возможные варианты, которые вы можете использовать. Будучи простым, он все же предоставляет очень много вариантов, которые могут вызвать замешательство. Одним из лучших способов изучить JOptionPane — это поработать с ним, закодировать и посмотреть, что получилось. Компонент позволяет менять практически каждый свой аспект: заголовок фрейма, само сообщение, отображаемую пиктограмму, варианты кнопок и необходимость текстового ответа. Существует очень много возможностей, для того чтобы их все перечислять в данном руководстве. Перейдите лучше на страницу API JOptionPane документации для их просмотра.

JTextArea

Компонент JTextArea развивает JTextField. В то время как JTextField ограничен одной строкой текста, JTextArea позволяет иметь несколько строк. Думайте о нем, как о пустой странице, позволяющей ввести все что угодно. Как вы уже наверно догадались, JTextArea имеет многие из функций, присутствующих в JTextField; в конце концов, это практически одинаковые компоненты. Однако JTextArea предлагает несколько дополнительных функций. К ним относятся способность переносить слова (то есть, переносить длинное слово в следующую строку вместо обрезания по середине слова) и способность переносить текст (то есть, помещать длинные строки текста на следующую строку вместо создания очень длинной строки, требующей наличия горизонтальной полосы прокрутки).

JTextArea в Swing выглядит так:

Важными методами для разрешения переноса строки и переноса слова являются:

  • is/setLineWrap() : Устанавливает, должна ли переноситься строка, если она становится слишком длинной.
  • is/setWrapStyleWord() : Устанавливает, должно ли переноситься слово на следующую строку, если оно слишком длинное.

JScrollPane

Рассматривая приведенный выше пример, предположим, что JTextArea содержит слишком много текста для данного пространства. Что тогда? Если вы думаете, что полосы прокрутки появятся автоматически, то, к сожалению, ошибаетесь. JScrollPane устраняет этот пробел, предоставляя Swing-компонент для обработки всех действий по прокрутке. То есть (хотя потребуются некоторые усилия, чтобы обеспечить панель прокрутки для каждого компонента, который в ней нуждается), если вы добавите ее, она будет управлять всем автоматически, включая скрытие/показ полос прокрутки при необходимости.

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

Этот обновленный пример выглядит следующим образом:

Компонент JScrollPane предоставляет также два компонента JScrollBar, которые он создаст. Эти компоненты JScrollBar содержат методы, которые вы можете использовать для изменения их поведения (их рассмотрение выходят за рамки данного руководства).

Методами, которые вы должны использовать с JScrollPane, являются:

  • getHorizontalScrollBar() : Возвращает горизонтальный компонент JScrollBar.
  • getVerticalScrollBar(): Возвращает вертикальный компонент JScrollBar.
  • get/setHorizontalScrollBarPolicy() : Эта «политика» может принимать одно из следующих значений: Always (всегда), Never (никогда), или As Needed (по необходимости).
  • get/setVerticalScrollBarPolicy() : Аналогично горизонтальной функции.

JList

Компонент JList является полезным компонентом для предоставления пользователю многих вариантов для выбора. Вы можете представлять его как расширение JComboBox. JList предоставляет больше вариантов и добавляет возможность выбора нескольких вариантов. Выбор между JList и JComboBox часто заключается в следующем: если вам требуется возможность множественного выбора или имеется более 15 вариантов (хотя это число не является общим правилом), вы должны всегда выбирать JList.

Цукерберг рекомендует:  Создание доски отзывов на PHP, MySQL и jQuery

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

JList имеет также модель выбора (также имеющуюся в JTable), которую вы можете установить в различные типы выбора вариантов. Такими типами являются: одиночный выбор (вы можете выбрать только один вариант), одиночный интервал (вы можете выбрать смежные варианты, но в любом их количестве) и множественный интервал (вы можете выбрать любое число вариантов в любых комбинациях).

JList является первым из компонентов, которые я называю «сложными компонентами», и к которым относятся также компоненты JTable и JTree, допускающие большое количество пользовательских настроек, в том числе внешнего вида и способа обработки данных. Поскольку данное руководство предназначено только для рассмотрения основ Swing, я не буду углубляться в эти расширенные функции, но при работе с этими компонентами вы должны помнить — они более сложны, чем рассмотренные до сих пор компоненты.

JList в Swing выглядит так:

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

  • get/setSelectedIndex() : Получить/установить выбранную строку списка; в случае со списками с множественным выбором возвращается int[] .
  • get/setSelectionMode() : Как объяснялось ранее, получить/установить режим выбора в одиночный выбор, одиночный интервал или множественный интервал.
  • setListData() : Установить данные для использования в JList.
  • get/setSelectedValue() : Получить выбранный объект (как противоположность выбранному номеру строки).

JTable

Представляйте себе электронную таблицу Excel при рассмотрении компонента JTable, и вы получите ясную картину того, что делает в Swing компонент JTable. Он имеет много таких же характеристик: ячейки, строки, столбцы, перемещение столбцов и скрытие столбцов. JTable развивает идею JList. Вместо отображения данных в одном столбце он отображает их в нескольких. Давайте возьмем для примера человека. JList смог бы отобразить только одно его свойство, например, имя. Однако JTable смог бы отобразить несколько свойств — имя, возраст, адрес и т.д. JTable является Swing-компонентом, позволяющим предоставлять больше информации о ваших данных.

К сожалению, имеется и недостаток. Он известен также как наиболее сложный Swing-компонент для работы. Многие UI-разработчики мучались при изучении каждой подробности JTable. Я избавлю вас от этого.

Многие концепции JList присутствуют также и в JTable, в том числе, например, множественный выбор интервалов. Но однострочные концепции JList меняются на ячеистую структуру JTable. Это означает, что есть различные способы делать этот выбор в JTable: в виде столбцов, строк или индивидуальных ячеек.

В Swing JTable выглядит так:

Конечно, рассмотрение функциональности JTable выходит за рамки данного руководства.


JTree

JTree — это еще один сложный компонент, который не так трудно использовать, как JTable, но не так просто, как JList. Хитрость при работе с JTree состоит в требуемых моделях данных.

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

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

Однако бывают ситуации, когда дерево логично использовать в качестве UI-компонента. Система файлов и каталогов — это один из примеров, как в Internet Explorer, и JTree является наилучшим компонентом для данных с иерархической структурой, иными словами, когда данные имеют форму дерева.

В Swing компонент JTree выглядит так:

Концепции Swing

Схемы, модели и события

Теперь, когда вы знакомы с большинством (но определенно не со всеми) компонентов, которые можно использовать для создания UI, необходимо что-то с ними делать реальное. Вы не можете просто случайно разместить их на экране и ожидать от них немедленной работы. Вы должны разместить их в определенные места, реагировать на взаимодействие с ними, обновлять их на основе этого взаимодействия и заполнять данными. Необходимо дальнейшее изучение других важных частей UI для заполнения пробелов в ваших знаниях.

Поэтому, давайте рассмотрим:

  • Схемы (layout): Swing содержит множество схем, которые представляют собой классы, управляющие размещением компонентов в приложении и тем, что должно произойти с ними при изменении размеров окна приложения или при удалении или добавлении компонентов.
  • События (event): Вы должны реагировать на нажатия клавиши, нажатия кнопки мыши и на все остальное, что пользователь может сделать в UI. Подумайте о том, что было бы, если бы вы этого не делали — пользователи нажимают на кнопки, а ничего не происходит.
  • Модели (model): Для более продвинутых компонентов (списки, таблицы, деревья) и даже для некоторых более простых, например, JComboBox, модели — это самый эффективный способ работы с данными. Они удаляют большую часть работы по обработке данных из самого компонента (вспомните обсуждение MVC) и предоставляют оболочку для общих объектных классов данных (например, Vector и ArrayList ).

Простые схемы

Как уже говорилось в предыдущем разделе, схема управляет расположением компонентов в приложении. Вашим первым вопросом мог бы быть вопрос «почему я просто не могу указать месторасположение, используя пиксели»? Да, вы можете, но тогда сразу же возникнет проблема при изменении размеров окна, или еще хуже: если пользователь изменит разрешение экрана, или кто-то попробует запустить приложение в другой OS. Менеджеры схем берут все это на себя. Никто не использует одни и те же настройки, поэтому менеджеры схем создают «относительные» схемы, позволяя вам указывать, как должно происходить изменение размеров относительно других размещенных компонентов. Хорошая новость: это легче сделать, чем сказать. Вы просто вызываете setLayout(yourLayout) для настройки менеджера схемы. Последующие вызовы add() добавляют компонент в контейнер и позволяют менеджеру схемы позаботиться об их размещении.

В Swing включено много схем; такое впечатление, что с каждой версией появляется новая, которая служит еще одной цели. Однако некоторые проверенные временем схемы существовали всегда; под словом всегда я понимаю время с появления первой версии языка Java в 1995 году. Такими схемами являются FlowLayout, GridLayout и BorderLayout.

В схеме FlowLayout компоненты располагаются слева направо. Когда пространство заканчивается, происходит переход на новую строку. Это самая простая в использовании схема и наименее мощная:

Схема FlowLayout в работе

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

Схема GridLayout в работе

Схема BorderLayout все еще является очень полезной, несмотря на добавление в Swing новых схем. Даже опытные UI-разработчики часто используют BorderLayout. В ней используются понятия North (север), South (юг), East (восток), West (запад) и Center (центр) для размещения компонентов на экране:

Схема BorderLayout в работе

GridBagLayout

В то время как приведенные выше примеры хороши для простых схем, более продвинутые UI требуют использования более сложного менеджера схемы. Вот здесь нужен GridBagLayout. К сожалению, этот менеджер схем очень запутанный и тяжелый, и каждый, кто работал с ним, согласится с этим. Я тоже не могу не согласиться, но, несмотря на его сложность, он, вероятно, является наилучшим (из всех менеджеров схем, встроенных в Swing) способом создания прекрасно выглядящего UI.

Вот мой первый совет: В новейших версиях Eclipse есть встроенный визуальный построитель, автоматически генерирующий требуемый для GridBagLayout код для каждого экрана. Используйте его! Он сбережет бесчисленные часы бесполезных игр с числами для нормального отображения. Поэтому, имея возможность пуститься в объяснения работы GridBagLayout и настройки его для наилучшего выполнения работы, я, тем не менее, просто посоветую: найдите визуальный редактор и сгенерируйте код. Это сэкономит вам часы.

События

Наконец, мы перешли к наиболее важным элементам Swing — работе с событиями и реакции на взаимодействия с UI. Swing обрабатывает события, используя модель событие/прослушиватель. Эта модель работает путем разрешения некоторым классам регистрироваться на события от компонента. Такой класс называется прослушивателем (listener), поскольку он ждет возникновения событий в компоненте и выполняет действия при их возникновении. Компонент сам знает, как «активировать» событие (то есть, он знает типы взаимодействий, которые может генерировать, и как дать прослушивателям знать, когда происходят эти взаимодействия). Он передает это взаимодействие при помощи событий (event), классов, содержащих информацию о взаимодействии.

Убрав техническую болтовню, рассмотрим некоторые примеры работы событий в Swing. Я начну с простейшего примера — кнопки JButton и вывода сообщений «Hello» на консоль при ее нажатии.

JButton знает, когда на нее нажимают; это обрабатывается внутри компонента, код для обработки этого не нужен. Однако прослушиватель должен зарегистрироваться для получения этого события от JButton, для того чтобы вы могли вывести сообщение «Hello». Класс listener делает это, реализуя интерфейс listener и вызывая метод addActionListener() компонента JButton:

Компонент JList работает аналогично. Когда кто-то выбирает что-то в JList, вы выводите на консоли сообщение о выбранном объекте:

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

Модели

Вы должны знать о Java Collections, наборе Java-классов, обрабатывающих данные. К этим классам относятся ArrayList , HashMap и Set . Большинство приложений использует эти классы повсюду при перемещении данных взад и вперед. Однако при необходимости использования этих данных в UI возникает одно ограничение. UI не знает, как их отображать. Подумайте об этом минутку. Если у вас есть JList и ArrayList некоторых объектов данных (например, объектов Person ), как JList узнает, что отображать? Должен ли он отображать только фамилию, или фамилию и имя вместе?

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

Каждый компонент, работающий с коллекцией данных в Swing, использует концепцию модели, и это предпочтительный способ использования и управления данными. Он четко отделяет работу UI от используемых данных (вспомните пример MVC). Модель описывает компоненту, как отображать коллекцию данных. Что я имею в виду под словом «описывает»? Каждый компонент требует немного разного описания:

  • JComboBox требует от своей модели описания текста для отображения в виде вариантов выбора и количества существующих вариантов.
  • JSpinner требует от своей модели описания текста для отображения, а также описания предыдущего и следующего вариантов.
  • JList тоже требует от своей модели описания текста для отображения как вариантов выбора и количества существующих вариантов.
  • JTable нужно намного больше — он требует от своей модели описания количества существующих строк и столбцов, названий столбцов, класса каждого столбца и текста для отображения в каждой ячейке.
  • JTree требует от своей модели описания корневого узла, предков и дочерних элементов для всего дерева.

Вы можете спросить, зачем все это делать? Зачем понадобилось разделять всю эту функциональность? Представьте себе сценарий: у вас есть законченная таблица со многими столбцами данных, и вы используете эту таблицу на различных экранах. Если вы неожиданно решите удалить один из столбцов, что было бы легче, изменить код в каждом единичном экземпляре JTable, использованном вами, или изменить его в одном классе модели, который вы создали для использования с каждым экземпляром JTable? Очевидно, что лучше изменить классы.

Примеры модели

Давайте рассмотрим, как работает модель, на простом примере JComboBox. В предыдущем разделе о JComboBox я показал вам, как добавлять элементы к данным, вызывая setItem() . Хотя это и приемлемо для простых демонстраций, в реальных приложениях так делают не часто. В конце концов, когда имеется 25 вариантов, и они постоянно меняются, неужели вы захотите проходить по ним в цикле, вызывая addItem() 25 раз? Конечно же, нет.

JComboBox имеет метод setModel() , который принимает экземпляр класса ComboBoxModel . Вы должны использовать этот метод вместо метода addItem() для создания данных в JComboBox.

Предположим, что имеется ArrayList с алфавитом в качестве данных («A», «B», «C» и т.д.):

Хорошей стороной использования модели является то, что вы можете повторно использовать ее снова и снова. Например, предположим, что данные в JComboBox должны быть изменены с букв алфавита на числа от 1 до 27. Вы можете выполнить это изменение одной простой строкой, которая использует новый List данных для заполнения JComboBox без использования дополнительного кода:

Модели являются полезными возможностями Swing, поскольку они предоставляют возможность повторного использования кода и намного более легко работают с данными. Как это часто случается в крупномасштабных приложениях, разработчики серверной части создают и извлекают данные и передают их UI-разработчикам. Обязанностью UI-разработчика является работать с данными и отображать их правильно, а модели — инструменты, которые делают это.

Объединение всего этого вместе

Пример приложения

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

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

Это простое по внешнему виду приложение, которое позволит вам увидеть в действии все элементы Swing. Данный пример должен ответить на любые вопросы, которые, возможно, остались у вас от предыдущих разделов. Перед началом работы посмотрим на законченный продукт:

Пример приложения

Шаг 1: Размещение компонентов

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

Шаг 2: Инициализация данных

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

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

Города сохраняются в простых объектах String . Однако рейсы хранятся в объектах данных, называемых Flights , содержащих поля для города отправления, города прибытия, номера рейса и количества доступных билетов.

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

Шаг 3: Управление событиями

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

Начнем с кнопки Search. Как говорилось выше, вы должны вызвать метод addActionListener() кнопки для регистрации на события, возникающие при ее нажатии. Для простоты я использовал класс FlightReservation для прослушивания всех возможных событий. Вот код обработки нажатия кнопки Search:

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

Затем исследуем, что происходит при нажатии пользователем кнопки Purchase:

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

Наконец, вы должны проверить ошибки и убедиться в том, что никто не пытается купить билет, не выбрав рейса в таблице. Самый простой способ сделать это — запретить компоненты, которые может использовать пользователь для покупки билетов (текстовое поле и кнопку) и разрешать их только после выбора пользователем строки:

Шаг 4: Модели

Далее рассмотрим модели, используемые вами для обработки всех данных, передаваемых в обе стороны в этом приложении. Анализируя приложения и изучив этот демонстрационный пример, вы должны четко увидеть, что вам нужны две модели: модель для JComboBoxes и модель для JTable.

Начнем с простейшей модели JComboBox. Я не буду приводить здесь исходный код, поскольку он аналогичен рассмотренному несколькими разделами ранее (и, фактически, может быть использован для любого из ваших JComboBox). Хотя есть некоторые важные моменты, помните о преимуществах использования моделей. И хотя у вас имеется только один класс модели, вы повторно используете его, создавая два экземпляра класса и предоставляя их каждому из JComboBox. Таким образом, оба экземпляра могут обрабатывать свои собственные данные, хотя вы пишете только один класс для этого. Вот как это делается:

Перейдем к модели для JTable. Эта модель сложнее, чем для JComboBox, и требует более пристального рассмотрения. Начнем с ваших знаний ComboBoxModel и посмотрим, что нужно добавить для JTable. Поскольку JTable содержит те же данные, что и ComboBox, но в нескольких столбцах, вам нужна более полная информация из модели. То есть, кроме знания количества строк данных вы должны знать количество столбцов, названия столбцов и значение конкретной ячейки, а не только самого объекта. Это позволяет вам не только отобразить объект данных, но также отобразить поля объекта данных. В данном примере мы не отображаем объект Flight; вместо этого мы отображаем поля: город отправления, город прибытия, номер рейса и количество доступных билетов. Ниже приведен код, используемый для создания TableModel и для установки этой модели для JTable:

Из за большого объема кода, необходимого для создания TableModel , я не буду приводить его здесь, а перенаправлю вас к исходному коду примера приложения (ссылка для загрузки приведена в разделе «Ресурсы«) для более пристального исследования его работы. Кроме того, это только поверхностно затрагивает TableModel . Как я уже говорил ранее, JTable является самым сложным и трудным компонентом для работы со Swing, и его элементы, в том числе TableModel , не намного более просты.

Шаг 5: Звонки и свистки

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

Рассмотрим условие ошибки, а также то, что активизирует сообщение об ошибке:

Теперь позаботимся о сообщении об ошибке. Вспомните JOptionPane и его обильное количество настроек. Выделим настройки, которые хотим иметь в сообщении об ошибке, перед тем, как решим, какой тип JOptionPane создавать. Это должно быть сообщение об ошибке, а не информационное сообщение. Используйте простой заголовок, например «Error». Детальное сообщение состоит из того, что выдала исключительная ситуация. И, наконец, ошибка возникла по вине пользователей, поэтому должно быть достаточно наличия кнопок OK и Cancel.

Вот код для создания такой JOptionPane:

И вот, как это все выглядит:

Пример сообщения об ошибке

И напоследок…

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

Особенно обратите внимание на то, как я использовал модели для облегчения процесса работы с данными. Используя довольно простой код, вы можете обрабатывать любой тип данных, которые могут получать как JTable, так и JComboBox. Кроме того, обратите внимание на взаимосвязи событие/прослушиватель — как взаимодействующие компоненты принимают участие во взаимоотношении событие/прослушиватель, т.е. на то, как заинтересованные стороны (особенно другие компоненты) должны регистрироваться на эти события.

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

Резюме

Резюме

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

  • Вы познакомились со Swing-компонентами. Вы должны уметь распознавать компоненты, когда видите их на экране, и применять их в ваших собственных приложениях, используя основные функции этих компонентов. Кроме того, вы должны иметь общее представление о том, когда нужно использовать компоненты (например, когда использовать JCheckBox, а когда JRadioButton).
  • Вы узнали, как разместить эти компоненты на экране при помощи менеджеров схем. Менеджеры схем существуют со времен появления Java, и, к сожалению, наиболее мощный менеджер схем наиболее тяжело использовать. Однако визуальные редакторы (например, редактор в Eclipse) делают процесс размещения чрезвычайно легким, создавая весь код схемы автоматически.
  • Вы узнали о модели событий, о том, как Swing использует модель событие/прослушиватель во всех своих компонентах для разрешения одному компоненту принимать пользовательское взаимодействие с приложением и передавать это взаимодействие в другие классы. Эти другие классы регистрируются на события от компонента и выполняют соответствующее действие при получении события. Модель событие/прослушиватель используется во всей библиотеке Swing, и вы должны глубоко изучить ее для лучшей работы с каждым Swing-компонентом.
  • Вы узнали о моделях данных и о том, как они соответствуют архитектуре MVC в Swing. Модели позволяют компонентам отображать данные без каких-либо знаний о самих данных. Они также позволяют вам повторно использовать модели, разрешая нескольким компонентам, отображающим похожие данные, использовать одну и ту же модель, устраняя необходимость создания оригинальной модели для каждого экземпляра компонента. В крупномасштабных приложениях модели служат «транслятором» между серверными объектами данных и клиентскими Swing-компонентами.

Очень важно понимать, что данное руководство не является всеобъемлющим. Оно даже не предназначено для обзора всех основ Swing. Существует еще очень много вещей, которые нужно было бы внести в это руководство, для того чтобы предоставить новичкам исчерпывающее введение в Swing. Надеюсь, что я выделил ключевые элементы, в том числе наиболее широко используемые компоненты и их наиболее широко используемые функции. Вы должны знать, что, возможно, в Swing существует в два раза больше компонентов (я призываю вас прочитать документацию по Swing для изучения тех компонентов, которые я пропустил). Более того, я только слегка затронул функции большинства компонентов; каждый Swing-компонент имеет десятки, даже до сотни, функций, которые вы потенциально можете использовать.

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

Дальнейшие действия

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

  • Более продвинутые функциональные возможности JTable, включая свойства таблицы, более тонкое управление TableModel, TableRenderer для изменения внешнего вида JTable и сортировку столбцов таблицы.
  • Потоки и их соответствие Swing. Поскольку пользователи не принимают интерфейс, который блокируется при выборке из базы данных, Swing должен использовать отдельные потоки для длительных операций.
  • Создание пользовательских компонентов. Если вы чувствуете ограниченность того, что может предложить вам Swing, я расскажу, как создавать компоненты, которые могут выглядеть и вести себя не так, как встроенные Swing-компоненты.
  • Пользовательское поведение и внешний вид. Я расскажу о том, как полностью изменить внешний вид приложения при помощи двух методов: первый создает новое пользовательское поведение и внешний вид UI, а второй использует библиотеку Synth, поддерживающую интерфейс с легко измененяемым внешним видом (skinnable).

Ресурсы

Научиться

  • Оригинал руководства «Introduction to Swing«.
  • Загрузите swing1.jar, который содержит исходный код приложений «Hello World» и системы резервирования билетов.
  • Не пропустите продолжение данного руководства «Swing для среднего уровня«, основанное на материале данного руководства.
  • Руководство Sun по Swing — хорошее дополнение к данному руководству, охватывающее не рассмотренные здесь компоненты.
  • В Swing Javadoc приводится описание всех возможных функций Swing-компонентов.
  • Web-страница JavaDesktop предлагает новые приемы работы в Swing.
  • Дискуссионный форум по программированию клиентских Java-приложений является еще одним хорошим местом для получения справочной информации по Swing.
  • На сайте developerWorks опубликовано множество статей по Swing:
    • В серии статей Джона Жуковски (John Zukowski) «Магия с Merlin» и «Укрощение тигра» постоянно упоминается Swing и смежные темы.
    • Майкл Абернети (Michael Abernethy) написал более продвинутые статьи по Swing, в том числе «Легкая разработка в Swing при помощи свободно распространяемой среды TableModel» (developerWorks, октябрь 2004), «Станьте мастером с IFrame» (developerWorks, март 2004) и «Продвинутый Synth» (developerWorks, февраль 2005).
  • Зона developerWorks открытого исходного кода имеет целый раздел, посвященный Eclipse-разработке.
  • В зоне developerWorks по Java-технологии вы найдете статьи по любому аспекту Java-программирования, в том числе и по рассмотренной в данном руководстве теме.

Получить продукты и технологии

  • eclipse.org — это официальный ресурс платформы разработки Eclipse. Здесь вы найдете файлы для загрузки, статьи и дискуссионные форумы, которые помогут вам профессионально использовать Eclipse.

Об авторе

Майкл Абернети (Michael Abernethy) в настоящее время работает руководителем группы тестировщиков в IBM WebSphere System Management, расположенной в Austin, TX. До этого он работал разработчиком Swing UI.

Графический интерфейс на Java Swing — GUI Tutorial

В Java есть 2 основных пакета для создания графических интерфейсов (Graphics User Interface). Это Abstract Windows Toolkit (AWT) и Swing. AWT использует виджеты операционной системы, поэтому эта библиотека немного быстрее. Но на мой взгляд, Swing более хорошо спроектирован.

В данном туториале мы рассмотрим основные элементы библиотеки Swing и создадим простой интерфейс (GUI) в качестве примера.

Для группировки компонент интерфейса используются контейнеры (Container). Для создания основного контейнера для приложения чаще всего используется контейнер JFrame (есть еще JWindows и JApplet). Проще всего унаследоваться от JFrame тем самым получить доступ ко множеству методов, например:

setBounds(x, y, w, h) — указывает координаты верхней левой вершины окна, а также его ширину и высоту.

setResizable(bool) — указывает, можно ли изменять размер окна.

setTitle(str) — устанавливает название окна.

setVisible(bool) — собственно отображает окно.

setDefaultCloseOperation(operation) — указывает операцию, которая будет произведена при закрытии окна.

Основные элементы управления:

  • JLabel — элемент для отображения фиксированного текста;
  • JTextField — простой edit-box;
  • JButton — обычная кнопка (button);
  • JCheckBox — элемент выбора (аналог checkbox);
  • JRadioButton — радио кнопка

Как видите, все довольно просто и логично.

При отображении элементов управления используются специальные менеджеры — LayoutManager. У всех LayoutManager’ов есть методы для добавления у удаления элементов.

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

GridLayout — отображения элементов в виде таблицы с одинаковыми размерами ячеек.

BorderLayout — используется при отображении не более 5 элементов. Эти элементы располагаются по краям фрейма и в ценрте: North, South, East, West, Center.

BoxLayout — отображает элементы в виде рядка или колонки.

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

Стоит еще обратить внимание на обработку событий. Для этого используются так называемые Event Listeners.

Ну все, довольно теории, перейдем к примеру GUI:

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

Внутренний класс ButtonActionListener реализует интерфейс ActionListener. Для этого необходимо предоставить имплементацию метода actionPerformed.

JOptionPane служит для отображения диалоговых окон.

Жду ваших вопросов и комментариев. Если вы хотите больше узнать о Swing, скажите об этом, и в скором времени я напишу еще одну статью с более сложными приемами и компонентами.

Понравилась статья? Поделиться с друзьями:
Все языки программирования для начинающих