JMenuBar, JMenu, JToolBar

Компонент меню JMenu библиотеки Swing позволяет создать набор элементов (пунктов меню) и представить их в интерфейсе окна. Элемент меню представляет собой кнопку, унаследованную от класса AbstractButton и отличающуюся от кнопок, флажков и переключателей только внешним видом и небольшими размерами, позволяющими им находится в JMenu. Соответствие элементов управления и элементов меню представлен в следующей таблице.

Элементы управленияЭлементы меню
Кнопка JButtonэлемент-меню JMenuItem
Переключатель JRadioButtonэлемент-переключатель JRadioButtonMenuItem
Флажок JCheckBoxэлемент-флажок JCheckBoxMenuItem

В меню нет эквивалента выключателя JToggleButton. С его функциями справляются флажки и переключатели

Создание меню - JMenu, JMenuItem

Рассмотрим пример создания простейшего системного меню. Исходный код примера :

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.ButtonGroup;
import javax.swing.AbstractAction;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.ImageIcon;
import javax.swing.JSeparator;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JRadioButtonMenuItem;

public class JMenuTest extends JFrame 
{
    private static final long serialVersionUID = 1L;
    //--------------------------------------------------------
    /**
     * Конструктор класса
     */
    public JMenuTest() 
    {
        super("Системное меню");
        setDefaultCloseOperation( EXIT_ON_CLOSE );
        // Создание строки главного меню
        JMenuBar menuBar = new JMenuBar();
        // Добавление в главное меню выпадающих пунктов меню  
        menuBar.add(createFileMenu());
        menuBar.add(createViewMenu());
        // Подключаем меню к интерфейсу приложения
        setJMenuBar(menuBar);
        // Открытие окна
        setSize(300, 200);
        setVisible(true);
    }
    //--------------------------------------------------------
    /**
     * Функция создания меню "Файл"
     * @return
     */
    private JMenu createFileMenu()
    {
        // Создание выпадающего меню
        JMenu file = new JMenu("Файл");
        // Пункт меню "Открыть" с изображением
        JMenuItem open = new JMenuItem("Открыть", 
                             new ImageIcon("images/open.png"));
        // Пункт меню из команды с выходом из программы
        JMenuItem exit = new JMenuItem(new ExitAction());
        // Добавление к пункту меню изображения
        exit.setIcon(new ImageIcon("images/exit.png"));
        // Добавим в меню пункта open
        file.add(open);
        // Добавление разделителя
        file.addSeparator();
        file.add(exit);

        open.addActionListener(new ActionListener()
            {
                @Override
                public void actionPerformed(ActionEvent arg0) {
                    System.out.println ("ActionListener.actionPerformed : open");
                }
            });
        return file;
    }
    //--------------------------------------------------------
    // создадим забавное меню
    /**
     * Функция создания меню 
     * @return
     */
    private JMenu createViewMenu()
    {
        // создадим выпадающее меню
        JMenu viewMenu = new JMenu("Вид");
        // меню-флажки
        JCheckBoxMenuItem line  = new JCheckBoxMenuItem("Линейка");
        JCheckBoxMenuItem grid  = new JCheckBoxMenuItem("Сетка");
        JCheckBoxMenuItem navig = new JCheckBoxMenuItem("Навигация");
        // меню-переключатели
        JRadioButtonMenuItem one = new JRadioButtonMenuItem("Одна страница");
        JRadioButtonMenuItem two = new JRadioButtonMenuItem("Две страницы");
        // организуем переключатели в логическую группу
        ButtonGroup bg = new ButtonGroup();
        bg.add(one);
        bg.add(two);
        // добавим все в меню
        viewMenu.add(line);
        viewMenu.add(grid);
        viewMenu.add(navig);
        // разделитель можно создать и явно
        viewMenu.add( new JSeparator());
        viewMenu.add(one);
        viewMenu.add(two);
        return viewMenu;
    }
    //--------------------------------------------------------
    /**
     * Вложенный класс завершения работы приложения 
     */
    class ExitAction extends AbstractAction
    {
        private static final long serialVersionUID = 1L;
        ExitAction() {
            putValue(NAME, "Выход");
        }
        public void actionPerformed(ActionEvent e) {
            System.exit(0);
        }
    }
    //--------------------------------------------------------
    public static void main(String[] args)
    {
        // Подключение украшений для окон
        JFrame.setDefaultLookAndFeelDecorated(true);
        new JMenuTest();
    }
}

В примере создается относительно простое меню, элементами которого являются фактически кнопки, собранные в список. Списки элементов меню, или правильнее выпадающие меню (drop-down menus), реализованы в Swing классом JMenu. Интерфейс примера с открытым меню представлен на следующих двух скриншотах.

Выпадающие меню JMenu создаются методами createFileMenu() и createViewMenu(), в которых методом add() добавляются разнообразные элементы меню, в том числе элементы-флажки и элементы-переключатели.

Выпадающие списки меню размещаются в строке меню класса JMenuBar, содержащей метод add() для добавления выпадающих меню JMenu. Для размещения строки меню в интерфейсе окна вызывается метод setJMenuBar().

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

Строка меню JMenuBar

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

В следующем примере в JMenuBar размещаем выподающее меню и метку с надписью.

// Создание меню в Swing примере с клавиатурными комбинациями и мнемониками 

import javax.swing.*;

import java.awt.event.*;

public class JMenuBarTest extends JFrame 
{
    private static final long serialVersionUID = 1L;
    private  final  String[][]  menuFile = 
                                {{"Файл"     ,  "Ф",  "", ""}, 
                                 {"Открыть"  ,  "О", "O", ""},
                                 {"Сохранить",  "С", "S", ""}};
    private  final  String[][]  menuEdit = 
                                {{"Редактирование" , "Р",  "", ""}, 
                                 {"Вырезать"  , "В", "X", "images/cut.png"},
                                 {"Копировать", "К", "C", "images/copy.png"}};
    //--------------------------------------------------------
    /**
     * Функция создания выпадающего меню
     * @param items описание меню
     * @return JMenu выпадающее меню 
     */
    private JMenu createMenuItems(final String[][] items)
    {
        // Создание выпадающего меню
        JMenu menu = new JMenu(items[0][0]);
        menu.setMnemonic(items[0][1].charAt(0));
        for (int i = 1; i < items.length; i++) {
            // пункт меню "Открыть"
            JMenuItem item = new JMenuItem(items[i][0]);
            item.setMnemonic(items[i][1].charAt(0)); // русская буква
            // установим клавишу быстрого доступа (латинская буква)
            item.setAccelerator(KeyStroke.getKeyStroke(items[i][2].charAt(0), 
                                          KeyEvent.CTRL_MASK));
            if (items[i][3].length() > 0)
                item.setIcon(new ImageIcon(items[i][3]));
            menu.add(item);
        }
        return menu;
    }
    //--------------------------------------------------------
    /**
     * Функция создания выпадающего меню с вложенными подпунктами
     * @return
     */
    private JMenu createSubmenus()
    {
        JMenu text = new JMenu("Текст");
        // и несколько вложенных меню
        JMenu style = new JMenu("Стиль");
        JMenuItem bold = new JMenuItem("Жирный");
        JMenuItem italic = new JMenuItem("Курсив");
        JMenu font = new JMenu("Шрифт");
        JMenuItem arial = new JMenuItem("Arial");
        JMenuItem times = new JMenuItem("Times");
        font.add(arial); font.add(times);
        // размещаем все в нужном порядке
        style.add(bold);
        style.add(italic);
        style.addSeparator();
        style.add(font);
        text.add(style);
        return text;
    }
    //--------------------------------------------------------
    public JMenuBarTest() {
        super("Системное меню");
        setDefaultCloseOperation( EXIT_ON_CLOSE );
        // создаем строку главного меню
        JMenuBar menuBar = new JMenuBar();
        // Создание меню "Файл"
        menuBar.add(createMenuItems(menuFile));
        // Создание меню "Редактирование"
        menuBar.add(createMenuItems(menuEdit));

        menuBar.add(createSubmenus());

        // JMenuBar использует блочное расположение (заполнитель вполне уместен)
        menuBar.add(Box.createHorizontalGlue());
        // Разместим в строке меню не выпадающее меню, а надпись со значком
        JLabel exit = new JLabel(new ImageIcon("images/exit.png"));
        exit.setText("Выход");
        exit.setBorder(BorderFactory.createEtchedBorder());
        menuBar.add(exit);

        // поместим меню в наше окно
        setJMenuBar(menuBar);
        // выводим окно на экран
        setSize(300, 200);
        setVisible(true);
    }
    //--------------------------------------------------------
    public static void main(String[] args)
    {
        // Подключение украшений для окон
        JFrame.setDefaultLookAndFeelDecorated(true);
        new JMenuBarTest();
    }
}

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

В примере для создания элементов пунктом меню "Файл" и "Редактирования" используется метод createMenuItems, которому в качестве параметров передается многомерный массив строк с описанием пунктов меню. Данный метод создает элемент меню с "мнемоникой" и "акселератором". При необходимости можно устанавливать в элемент меню изображение в виде иконки. Метод createSubmenus() создает выпадающее меню с вложенными подпунктами.

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

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

Загрузчик меню

В представленных примерах код формирования меню «раздувает» тело основной программы. А если принять во внимание, что это не последняя Swing-программа, то целесообразно разработать загрузчик меню "на все случаи жизни", или стремиться к этому. Также было бы неплохо и описание меню вынести из основного кода.

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

Загрузчик XML-файла XMLReader.java

/**
 * Модуль чтения файла XML
 */

import java.io.Reader;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.FileNotFoundException;

import org.xml.sax.InputSource;

public class XMLReader 
{
    private  InputSource  source;  // источник данных XML

    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /**
     * Конструктор класса
     * @param fname полный путь к файлу XML
     * @param charset кодировка содержимого XML файла 
     * @throws FileNotFoundException
     */
    public XMLReader (final String fname, final String charset) 
                      throws FileNotFoundException
    {
        this (new FileInputStream(fname), charset);
    }
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /**
     * Конструктор класса
     * @param stream поток данных
     * @param charset кодировка типа UTF8
     */
    public XMLReader (final InputStream stream, final String charset)
    {
        // Чтение данных XML
        try {
            Reader reader = new InputStreamReader(stream, charset);
            source = new InputSource(reader);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /**
     * Функция получения источника данных XML
     * @return InputSource источник данных XML
     */
    public InputSource getInputSource()
    {
        return source;
    }
}

В загрузчик XML-файла включены только самые необходимые конструкторы и методы, которые используются в в загрузчике меню. Особо хочется отметить, что в конструкторы включен параметр, определяющий кодировку XML-файла "charset".

XML-файл описания меню menu.xml

Файл описания меню может включать наименования в кириллице, поскольку загрузчик файла учитывает кодировку. XML-файл описания меню можно представить в следующем виде:

<?xml version="1.0" encoding="UTF-8"?>
<menubar name="mainMenu">
    <menu name="file" text="Файл" mnemonic="Ф">
        <menuitem name="create" text="Создать" mnemonic="С" accelerator="control N"/>
        <menuitem name="open" text="Открыть" mnemonic="О" enabled="false"/>
        <menuitem name="close" text="Закрыть" mnemonic="З" enabled="false"/>
        <menuitem name="separator"/>
        <menu name="print" text="Печать" mnemonic="П">
            <menuitem name="preview" text="Предварительный просмотр" mnemonic="р"/>
        </menu>
        <menuitem name="separator"/>
        <menuitem name="exit" text="Выход" mnemonic="В" accelerator="alt X"/>
    </menu>
</menubar>

Корневым узлом описания меню является элемент с названием "menubar", описывающий строку меню, в которой размещаются все выпадающие меню и его элементы. Все теги описания меню имеют атрибут "name" (имя). По имени будет выполняться поиск элемента. Чтобы при поиске элементов меню не возникало ошибок, имена всех элементов должны быть уникальными.

К строке меню "menubar" присоединяются выпадающие меню : для XML-контента это означает наличие элементов-потомков с названием "menu". Как правило, для выпадающих меню настраиваются два свойства: text (текст меню) и mnemonic (символ мнемоники). Данные свойства будут задаваться в виде атрибутов элемента "menu".

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

Тег "menuitem" соддержит больше всего атрибутов : для него можно задавать не только текст меню и символ мнемоники, но и сочетание клавиш быстрого доступа (accelerator), а также его доступность для отображения в системном меню (enabled). В качестве особых элементов меню выступают разделители меню "separator", позволяющие организовывать группы элементов.

Пример анализатора XML-контента

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;

import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.KeyStroke;

import org.xml.sax.Attributes;
import org.xml.sax.helpers.DefaultHandler;

public class XMLMenuParser extends DefaultHandler
{
    private JMenuBar currentMenuBar; // текущая строка меню
                                     // хранилище для всех частей системы меню
    private Map <String, Object> menuStorage = new HashMap<String, Object>();
                                     // список для упорядочения выпадающих меню
    private LinkedList<JMenu> menus      = new LinkedList<JMenu>();

    private  final  String  ATTRIB_menubar     = "menubar"    ;
    private  final  String  ATTRIB_menu        = "menu"       ;
    private  final  String  ATTRIB_menuitem    = "menuitem"   ;
    private  final  String  ATTRIB_name        = "name"       ;
    private  final  String  ATTRIB_text        = "text"       ;
    private  final  String  ATTRIB_mnemonic    = "mnemonic"   ;
    private  final  String  ATTRIB_accelerator = "accelerator";
    private  final  String  ATTRIB_enabled     = "enabled"    ;
    private  final  String  ATTRIB_separator   = "separator"  ;
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Новый узел тега XML
    public void startElement(String uri, String localName, String qName, 
                             Attributes attributes)
    {
        // Определяем тип узла
        if (qName.equals(ATTRIB_menubar))
            parseMenuBar(attributes);
        else if (qName.equals(ATTRIB_menu))
            parseMenu(attributes);
        else if (qName.equals(ATTRIB_menuitem))
            parseMenuItem(attributes);
    }
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Конец узла, используется для смены выпадающих пунктов меню
    public void endElement(String uri, String localName, String qName) {
        if (qName.equals(ATTRIB_menu)) menus.removeFirst();
    }
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Создание новой строки меню JMenuBar
    private void parseMenuBar(Attributes attrs) {
        JMenuBar menuBar = new JMenuBar();
        // Определение имени
        String name = attrs.getValue(ATTRIB_name);
        menuStorage.put(name, menuBar);
        currentMenuBar = menuBar;
    }
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Создание выпадающего меню
    private void parseMenu(Attributes attrs) {
        // Создание меню
        JMenu menu = new JMenu();
        String name = attrs.getValue(ATTRIB_name);
        // Настройка общих атрибутов
        adjustProperties(menu, attrs);
        menuStorage.put(name, menu);
        // Добавление меню к предыдущему выпадающему меню или к строке меню
        if ( menus.size() != 0 ) {
            ((JMenu)menus.getFirst()).add(menu);
        } else {
            currentMenuBar.add(menu);
        }
        // Добавлние в список выпадающих меню
        menus.addFirst(menu);
    }
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Создание пункта меню
    private void parseMenuItem(Attributes attrs) {
        // Проверка, не разделитель ли это
        String name = attrs.getValue(ATTRIB_name);
        if (name.equals(ATTRIB_separator)) {
            ((JMenu)menus.getFirst()).addSeparator();
            return;
        }
        // Создание пункта меню
        JMenuItem menuItem = new JMenuItem();
        // настраиваем свойства
        adjustProperties(menuItem, attrs);
        menuStorage.put(name, menuItem);
        // Добавление к текущему выпадающему меню
        ((JMenu)menus.getFirst()).add(menuItem);
    }
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Настройка общих атрибутов пунктов меню
    private void adjustProperties(JMenuItem menuItem, Attributes attrs) {
        // Чтение поддерживаемых атрибутов
        String text        = attrs.getValue(ATTRIB_text       );
        String mnemonic    = attrs.getValue(ATTRIB_mnemonic   );
        String accelerator = attrs.getValue(ATTRIB_accelerator);
        String enabled     = attrs.getValue(ATTRIB_enabled    );
        // Определение заголовка элемента меню
        menuItem.setText(text);
        if (mnemonic != null) {
            menuItem.setMnemonic(mnemonic.charAt(0));
        }
        if (accelerator != null) {
            menuItem.setAccelerator(
                    KeyStroke.getKeyStroke(accelerator));
        }
        if (enabled != null) {
            boolean isEnabled = true;
            if (enabled.equals(String.valueOf(false)))
                isEnabled = false;
            menuItem.setEnabled(isEnabled);
        }
    }
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    public Map<String, Object> getMenuStorage()
    {
        return menuStorage;
    }
}

Анализатор XML-контента наследует все свойства DefaultHandler и формирует хранилище меню menuStorage типа Map.

Пример тестирования загрузчика меню

В модуле тестирования загрузчика создается объект XMLReader для чтения файла меню с кодировкой UTF-8. После этого о пределяется объект создателя меню XMLMenuCreater с передачей конструктору в качестве параметра источника XML-файла. XMLMenuCreater выполняет разложение XML-содержимого (метод parse) с созданием меню и подключением JMenuBar к интерфейсу. В заключение к создателю меню подключается слушатель (addActionListener), который позволяет завершить работу программы, выбрав соответствующий пункт меню.

/**
 * Класс тестирования модуля загрузки меню из файла XML
 */

import javax.swing.*;
import java.awt.event.*;

public class XMLMenuCreaterTest extends JFrame 
{
    private static final long serialVersionUID = 1L;

    public XMLMenuCreaterTest()
    {
        super("XML Menu Loader");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        try {
            // открываем файл XML с описанием меню
            XMLReader xmlReader = new XMLReader ("menu.xml", "UTF8");
            // Загружаем меню
            XMLMenuCreater menuCreater = new XMLMenuCreater(xmlReader.getInputSource());
            menuCreater.parse();
            // Подключение строки меню
            setJMenuBar(menuCreater.getMenuBar("mainMenu"));
            // Подключение слушателя
            menuCreater.addActionListener("exit", new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    System.exit(0);
                }});
        } catch (Exception e) {
            e.printStackTrace();
        }
        // выводим окно на экран
        setSize(300, 200);
        setVisible(true);
    }
    public static void main(String[] args) {
        new XMLMenuCreaterTest();
    }
}

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

Примечание : исходный код формирователя меню XMLMenuCreater на странице сайта не приводится, но он включен в архив всех примеров, рассмотренных на странице.

Панели инструментов, JToolBar

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

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

Основные свойства панели инструментов JToolBar

СвойствоОписание
orientation Определение направления панели инструментов: вертикальное или горизонтальное. По умолчанию - горизонтальное. Компоненты будут добавляться в заданном направлении. Направление можно сменить и после создания панели инструментов.
floatable Флаг перетаскивания панели инструментов. По умолчанию перетаскивание включено. Если перетаскивание не нужно или способно запутать пользователя, задайте свойство равным false.
rollover Включение эффекта интерактивности — при наведении на компонент указателя мыши у компонента появляется специальная рамка или иной визуальный эффект (к примеру, особый значок). По умолчанию эффект интерактивности отключен.
borderPainted Управление прорисовкой рамки панели инструментов. Наличие рамки зависит от внешнего вида и поведения; по умолчанию рамка отображается. Как правило, это специальная полоса, с помощью которой пользователь может перетаскивать панель инструментов.

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

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

// Класс создания комбинированных панелей инструментов
import javax.swing.*;

import java.awt.event.*;

public class JToolBarTest extends JFrame
{
    private static final long serialVersionUID = 1L;
    
    public JToolBarTest()
    {
        super("Пример использования JToolBar");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        // Создание панелей инструментов
        JToolBar tbCommon = new JToolBar();
        tbCommon.add(new OpenAction());
        tbCommon.add(new ExitAction());
        tbCommon.addSeparator();
        tbCommon.add(new JButton("Стиль"));
        // Блокируем возможность перетаскивания панели
        tbCommon.setFloatable(false);

        String[] schools = new String[] {"Школа", "Институт", "Академия"};
        JToolBar tbEducation = new JToolBar();
        tbEducation.add(new JButton("Образование"));
        tbEducation.add(new JComboBox<String> (schools));
        // Блокируем возможность перетаскивания панели
        tbEducation.setFloatable(false);
        // Блокируем возможность эффекта интерактивности - при наведении
        // мыши кнопка выделяется
        tbEducation.setRollover(false);

        JToolBar tbStyle = new JToolBar();
        tbStyle.add(new JButton("Обычный"));
        tbStyle.add(new JButton("Полужирный"));
        tbStyle.add(new JButton("Подчеркнутый"));
        // Выравнивание содержимого
        tbEducation.add(Box.createGlue());

        // Добавление двух панелей инструментов
        BoxLayoutUtils blUtils = new BoxLayoutUtils();
        // Панель с горизонтальным расположением компонентов
        JPanel first = blUtils.createHorizontalPanel();
        first.add(tbCommon);
        first.add(Box.createHorizontalStrut(50));
        first.add(tbEducation);
        // Панель с вертикальным расположением компонентов
        JPanel all = blUtils.createVerticalPanel();
        all.add(first);
        all.add(tbStyle);
        // Выравнивание по горизонтали
        blUtils.setGroupAlignmentX(new JComponent[] { first, tbStyle }, 
                                JComponent.LEFT_ALIGNMENT);
        // Размещение в верхней части окна
        getContentPane().add(all, "North");
        // Выводим окно на экран
        setSize(400, 300);
        setVisible(true);
    }
    //-----------------------------------------------------------------------------
    // Команда для кнопки "Открытия"
    class OpenAction extends AbstractAction {
        private static final long serialVersionUID = 1L;
        public OpenAction() {
            // Настройка иконок
            putValue(AbstractAction.SMALL_ICON, new ImageIcon("images/open.png"));
        }
        // Обработка действия
        public void actionPerformed(ActionEvent e) {
            // ничего не делаем
        }
    }
    //-----------------------------------------------------------------------------
    // Команда для кнопки "Выхода"
    class ExitAction extends AbstractAction {
        private static final long serialVersionUID = 1L;
        public ExitAction() {
            // Настройка иконок
            putValue(AbstractAction.SMALL_ICON, new ImageIcon("images/exit.png"));
        }
        // Обработка действия
        public void actionPerformed(ActionEvent e) {
            System.exit(0);
        }
    }
    //-----------------------------------------------------------------------------
    /**
     * Класс выравнивания компонентов в контейнере
     */
    class BoxLayoutUtils 
    {
        // Выравнивание компонентов по оси X
        public void setGroupAlignmentX(JComponent[] cs, float alignment) {
            for (int i = 0; i < cs.length; i++) {
                cs[i].setAlignmentX(alignment);
            }
        }
        // Выравнивание компонентов по оси Y
        public void setGroupAlignmentY(JComponent[] cs, float alignment) {
            for (int i = 0; i < cs.length; i++) {
                cs[i].setAlignmentY(alignment);
                }
        }
        // Создание панели с установленным вертикальным блочным расположением
        public JPanel createVerticalPanel() {
            JPanel p = new JPanel();
            p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
            return p;
        }
        // Создание панели с установленным горизонтальным блочным расположением
        public JPanel createHorizontalPanel() {
            JPanel p = new JPanel();
            p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));
            return p;
        }
    }
    //-----------------------------------------------------------------------------
    public static void main(String[] args) {
        new JToolBarTest();
    }
}

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

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

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

Кнопки в панель инструментов можно добавлять в виде компонента JButton с использованием метода метода add(), а также как экземпляр команды Action с использованием специального перегруженного метода add(). Использование в качестве параметра команды Action во многих случаях очень удобно, поскольку позволяет совмещать в одном месте настройку внешнего вида элемента управления и описание действия, которое он выполняет. Это особенно верно для панелей инструментов: в классе команды задается значок, текст подсказки и описывается действие, которое должна будет выполнить команда. После этого остается только добавить команду в панель инструментов. Если же необходимо будет модифицировать команду, будь то внешний вид или действие, то это все скрыто в одном классе.

Следует обратить внимание на специальную полосу с левого края нижней перемещаемой панели инструментов. Это так называемые вешки перемещения : с их помощью можно перетаскивать (drag and drop) панель инструментов и "причаливать" (drag and dock) к разным края окна, или же оставлять «плавающими». Перетаскивать панели инструментов и причаливать их к краям окна можно, только если в нем используется расположение BorderLayout. Отсюда следует нехитрый совет: если в вашем окне есть панели инструментов и вы хотите дать пользователю возможность их перетаскивать к другим краям окна, применяйте менеджер расположения BorderLayout, в противном случае пользователь может быть весьма озадачен тем, что панели инструментов оказываются совсем не там, куда он их перетаскивает.

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

Скачать примеры

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

  Рейтинг@Mail.ru