410013796724260
• Webmoney
R335386147728
Z369087728698
JButton, JGroupButton, ActionБиблиотека Swing включает абсолютно все придуманные на сегодняшний день элементы управления. К ним относятся кнопки, флажки, переключатели, меню и его элементы, и многое другое. Все эти элементы в библиотеке связаны, поскольку они унаследованы от абстрактного класса AbstractButton, определяющего поведение любого компонента, претендующего на звание элемента управления. Кнопки JButtonКнопки JButton кроме собственного внешнего вида не включают практически ничего уникального. Поэтому всё, что верно для кнопок, будет верно и для остальных элементов управления. Пример кода создания обычной кнопки : JButton button = new JButton("Кнопка"): button.addActionListener(new ButtonAction()); Основное время работы с кнопками связано не столько с их созданием и настройкой, сколько с размещением в контейнере и написанием обработчиков событий. Интерфейс кнопокВнешний вид кнопок JButton можно легко изменить, не меняя менеджера внешнего вида и поведения. С интерфейсом кнопок можно делать практически все — сопоставлять каждому действию пользователя своё изображение, убирать рамку, закрашивать в любой цвет, перемещать содержимое по разным углам, не рисовать фокус. Рассмотрим пример, в котором будут созданы кнопки JButton разных форм и размеров. // Класс представления различного внешнего вида кнопок JButton import java.awt.*; import java.awt.event.ItemEvent; import java.awt.event.ActionEvent; import java.awt.event.ItemListener; import java.awt.event.ActionListener; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; public class ButtonStylesTest extends JFrame { private static final long serialVersionUID = 1L; public ButtonStylesTest() { super("Интерфейсы кнопок"); setDefaultCloseOperation( EXIT_ON_CLOSE ); // Устанавливаем последовательное расположение Container container = getContentPane(); container.setLayout(new FlowLayout( FlowLayout.LEFT, 10, 10)); // Простая кнопка JButton button = new JButton("Обычная кнопка"); // Подключение слушателей событий button.addActionListener(new ListenerAction()); button.addChangeListener(new ListenerChange()); // присоединение слушателя прямо на месте button.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { System.out.println("Это событие мы не увидим"); }}); container.add(button); // Кнопка со значками на все случаи жизни button = new JButton(); button.setIcon (new ImageIcon("images/copy.png")); button.setRolloverIcon(new ImageIcon("images/cut.png" )); button.setPressedIcon (new ImageIcon("images/open.png")); button.setDisabledIcon(new ImageIcon("images/save.png")); // Убираем все ненужные рамки и закраску button.setBorderPainted(false); button.setFocusPainted(false); button.setContentAreaFilled(false); container.add(button); // Кнопка с описанием интерфейса в виде HTML-текста button = new JButton("<html><h2><font color=\"yellow\">Синяя кнопка"); // button.setOpaque(true); button.setBackground(Color.blue); container.add(button); // Изменение выравнивания текста и изображения button = new JButton("Изменение выравнивания", new ImageIcon("images/exit.png")); button.setMargin (new Insets(10, 10, 10, 10)); button.setVerticalAlignment (SwingConstants.TOP ); button.setHorizontalAlignment (SwingConstants.RIGHT ); button.setHorizontalTextPosition(SwingConstants.LEFT ); button.setVerticalTextPosition (SwingConstants.BOTTOM); button.setIconTextGap(10); // сделаем кнопку большой, чтобы увидеть выравнивание button.setPreferredSize(new Dimension(300, 100)); container.add(button); // отключенная кнопка button = new JButton("Выключено"); button.setEnabled(false); container.add(button); // выводим окно на экран setSize(400, 350); setVisible(true); } class ListenerAction implements ActionListener { public void actionPerformed(ActionEvent e) { System.out.println("Нажатие кнопки! От - "+ e.getActionCommand() + "\n"); } } class ListenerChange implements ChangeListener { public void stateChanged(ChangeEvent e) { // Источник события Object src = e.getSource(); System.out.println("Cообщение о смене состояния объекта : " + src.getClass()); } } public static void main(String[] args) { new ButtonStylesTest(); } } В примере создается небольшое окно с менеджером последовательного расположения FlowLayout. В форме помещается несколько кнопок, для каждой из которых используется свой способ представления внешнего вида. На скриншоте представлен интерфейс окна. Первой в контейнер помещается самая обычная кнопка. Затем следует кнопка, на которой вместо текста располагаются иконки на «все случаи жизни». Для определения иконок применяются свойства, перечисленные в таблице.
Если вывести кнопку с иконками на экран «как есть», она будет выглядеть не очень хорошо, поскольку у нее останутся все свойственные обычной кнопке с текстом свойства — будет рисоваться рамка, при наличии фокуса появится контур, а при нажатии она будет закрашиваться темным цветом. Чтобы убрать эти эффекты, в примере и задействуются методы setBorderPainted(), setFocusPainted() и setContentAreaFilled(). Метод setBorderPainted() позволяет отключить прорисовку рамки. То же самое можно сделать вызовом setBorder(null), но в этом случае нельзя вернуть кнопке ее рамку обратно. Метод setFocusPainted() отключает прорисовку специального контура, проявляющегося, если кнопка обладает фокусом ввода. setContentAreaFilled() дает возможность отключить закраску кнопки в нажатом состоянии. С этими методами лучше быть осторожней, потому что пользователю с такой кнопкой работать гораздо сложнее: будет непонятно, выбрана кнопка или нет, где она начинается и т. п. Применять эти методы лучше только в тех приложениях, в которых весь интерфейс основан на разнообразных изображениях (например, в играх). Методом setBackground() можно устанавливать цвет заполнения JButton. Цвет заполнения изменится только в том случае, если у кнопки включено свойство непрозрачности (opaque). По умолчанию оно установлено. Кнопки JButton также, как и надписи JLabel, позволяют определять интерфейс с использованием HTML, что вместе с широчайшими возможностями по настройке расположения содержимого и по управлению всеми аспектами внешнего вида кнопок дает неограниченную власть над видом приложения. Настройки кнопок JButtonВ таблице представлены параметры, позволяющие выполнить определенные настройки интерфейса кнопок JButton.
События элементов управления - ActionEvent, ChangeEvent, ItemEventУнаследованные от класса AbstractButton элементы управления, в том числе и кнопки JButton, могут посылать сообщения о трех типах событий (за исключением стандартных событий, общих для всех компонентов Swing). В таблице представлены эти события.
В примере после создания первой кнопки к ней подключаются слушатели событий. Для событий ActionEvent и ChangeEvent слушатели помещаются в отдельные внутренние классы, а слушатель события ItemEvent создается прямо на месте, как анонимный внутренний класс. При возникновении события информация об инициаторе выводится в консоль приложения. При щелчке на кнопке слушатель события определяет имя нажатой кнопки, используя метод getActionCommand() класса ActionEvent. Этот метод применяется для того, чтобы при обработке событий от нескольких кнопок в одном слушателе можно было их отличить. Событие ItemEvent не возникает вовсе, поскольку оно «работает» только с флажками, переключателями и другими компонентами, имеющими состояние, а кнопки его просто игнорируют. Пример использования Action при создании JButton// Использование Action при создании кнопки import java.awt.*; import java.awt.event.*; import javax.swing.*; public class AbstractActionTest extends JFrame { private static final long serialVersionUID = 1L; private final String BUTTON_NAME = "button1"; public AbstractActionTest() { super("Пример использования Action"); setDefaultCloseOperation(EXIT_ON_CLOSE); // Панель содержимого Container container = getContentPane(); // Устанавливаем менеджер последовательного расположения container.setLayout(new FlowLayout()); // Создание кнопок, выполняющих одно действие Action action = new SimpleAction(); JButton button1 = new JButton(action); button1.setName(BUTTON_NAME); button1.setText("First button"); button1.setMnemonic('F'); JButton button2 = new JButton(action); button2.setName("button2"); button2.setText("Second button"); button2.setMnemonic('S'); container.add(button1); container.add(button2); // выводим окно на экран setSize(320, 100); setVisible(true); } // Внутренний класс class SimpleAction extends AbstractAction { private static final long serialVersionUID = 1L; SimpleAction() { // Параметры команды // putValue(NAME, "Класс Action!"); putValue(SHORT_DESCRIPTION, "Это подсказка"); // putValue(MNEMONIC_KEY, new Integer('A')); } // Обработка события нажатия на кнопку public void actionPerformed(ActionEvent e) { JButton btn = (JButton) e.getSource(); System.out.println("Нажатие на кнопку <" + btn.getName() + ">"); // можно выключить команду, не зная, к каким компонентам она присоединена if (btn.getName().equalsIgnoreCase(BUTTON_NAME)) { btn.setEnabled(false); // Изменение надписи // putValue(NAME, "Disabled button"); btn.setText("Disabled button"); } } }; public static void main(String[] args) { new AbstractActionTest(); } } В примере создаются две кнопки, которые выполняют одно и то же действие, и, соответственно, обладают одним и тем же набором параметров. Чтобы не дублировать код для настройки этих кнопок, создается один экземпляр команды SimpleAction, который и передается кнопкам. SimpleAction расширяет абстрактный класс AbstractAction, имеющий поддержку слушателей PropertyChangeListener, которые оповещаются об изменениях в параметрах команды. Кнопки выступают в роли таких слушателей, что и позволяет им быть в курсе всех изменений и вовремя отображать их на экране. Все сводится к настройке параметров команды (обычно это производится в конструкторе) и определению метода actionPerformed(), отвечающего за обработку событий. Параметры команды хранятся в виде пар «ключ-значение», где ключ — одна из строк, определенных в интерфейсе Action. Эта строка показывает, какой именно параметр команды хранится в паре. Для того чтобы изменить параметр, используется метод putValue(). Параметры интерфейса Action
Конечно, это не полный список ключей. Можно установить и несколько других параметров, в том числе иконку. Полный список можно найти в интерактивной документации Java. Интерфейс примера представлен на следующих двух скриншотах. В методе actionPerformed() определяется источник, вызвавший событие кнопки JButton. Если это кнопкам button1, то меняется ее наименование и она блокируется (скриншот справа). МнемоникиРазработчики Swing наделили библиотеку поддержкой мнемоник для всех элементов управления. Мнемоники позволяют получить доступ к компоненту нажатием специальной клавиши (обычно Alt) вместе с клавишей символа, идентифицирующего этот компонент. Для обеспечения доступа пользователя к визуальному компоненту с помощью клавиатуры следует использовать следующие методы класса AbstractButton :
Пример определения мнемоники кнопки JButton : JButton button = new JButton("Файл (F)"); button.setMnemonic('F'); Элементы управления JToggleButton, ButtonGroup, JRadioButton, JCheckBoxВ приложениях, кроме кнопок, используются другие элементы управления, для которых характерно наличие двух устойчивых состояний. К ним относятся флажки, переключатели и выключатели. Единственное отличие их от JButton состоит в том, что они могут находиться в одном из двух состояний. При смене состояния эти компоненты генерируют событие ItemEvent, которое кнопки игнорируют. Поддержка двух состояний встроена в класс выключателя JToggleButton, от которого, в свою очередь, унаследованы классы флажков и переключателей. Выключатель JToggleButtonJToggleButton — довольно необычный элемент управления, чаще всего используемый в панелях инструментов, где он играет роль флажков. Фактически, по виду это та же самая кнопка, только ее можно нажать, и она остается в этом состоянии. Можно использовать JToggleButton и в обычном интерфейсе, когда нужно сделать выбор из двух альтернатив. Группы элементов управления ButtonGroupКласс ButtonGroup позволяет связать несколько элементов управления в логическую группу, в которой выбранным может быть только один из них. При выборе пользователем другого элемента управления класс ButtonGroup позаботится о том, чтобы выбранный прежде элемент вернулся в исходное состояние. Переключатели JRadioButtonПереключатель JRadioButton унаследован от выключателя JToggleButton и отличается от него только внешним видом. JRadioButton используют, как правило, при объединении нескольких переключателей в группу и реализации выбора «один из многих». По одиночке в интерфейсе их практически не используют; обычно эту роль исполняют флажки. Флажки JCheckBoxФлажки в библиотеке Swing реализуются классом JCheckBox. Они, также как и переключатели, отличаются от выключателей только внешним видом. Флажки используются там, где нужно предоставить пользователю возможность что-то включить или выключить. Они также могут группироваться. Но, в отличие от JRadioButton, никогда не реализуют выбор «один из нескольких», а всегда позволяют выбрать несколько равноценных вариантов. Рассмотрим пример, который включает все перечисленные элементы управления. // Кнопки управления import java.awt.*; import java.awt.event.*; import javax.swing.*; public class ButtonsTest extends JFrame { private static final long serialVersionUID = 1L; private JToggleButton button; private JPanel panelRadio, panelCheck; public ButtonsTest() { super("Кнопки управления"); setDefaultCloseOperation( EXIT_ON_CLOSE ); // Панель содержимого Container container = getContentPane(); // Последовательное расположение container.setLayout(new FlowLayout()); // Создание кнопки JToggleButton button = new JToggleButton("Нажмите", false); // Слушатель события о смене состояния button.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { String text = (button.isSelected()) ? "Отпустите" : "Нажмите"; button.setText(text); panelRadio.setVisible(!button.isSelected()); panelCheck.setVisible( button.isSelected()); } }); // Группа связанных радио-переключателей panelRadio = new JPanel(new GridLayout(0, 1, 0, 5)); panelRadio.setBorder(BorderFactory.createTitledBorder("Напитки")); String[] names1 = { "Байкал", "Тархун", "Минеральная" }; ButtonGroup bg1 = new ButtonGroup(); for (int i = 0; i < names1.length; i++) { JRadioButton radio = new JRadioButton(names1[i]); panelRadio.add(radio); bg1.add(radio); } // Группа связанных флажков panelCheck = new JPanel(new GridLayout(0, 1, 0, 5)); panelCheck.setBorder(BorderFactory.createTitledBorder("Мороженое")); String[] names2 = { "Шоколадное", "Крем-брюле", "Пломбир" }; ButtonGroup bg2 = new ButtonGroup(); for (int i = 0; i < names2.length; i++) { JCheckBox check = new JCheckBox(names2[i]); panelCheck.add(check); bg2.add(check); } panelCheck.setVisible(false); // Добавляем компоненты в контейнер container.add(button1 ); container.add(panelRadio); container.add(panelCheck); // Открываем окно setSize(280, 170); setVisible(true); } //-------------------------------------- public static void main(String[] args) { new ButtonsTest(); } } Интерфейс приложения представлен на следующих двух скриншотах. На левом скриншоте кнопка JToggleButton отпущена, панель panelRadio «открыта», в панели размещены кнопки JRadioButton. Панель panelCheck «скрыта». На правом скриншоте кнопка JToggleButton нажата, панель panelRadio «скрыта», панель panelCheck «открыта», в панели размещены кнопки JCheckBox. В примере обработка события «изменения состояния кнопки» JToggleButton выполняется в методе itemStateChanged слушателя ItemListener. В зависимости от состояния нажатия кнопки изменяется название кнопки и «окрывается/скрывается» одна из панелей. Архив примеровИсходные коды примеров, рассмотренных на странице, можно скачать здесь (4.28 Кб). |