JWindow, JFrame, JDialog

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

Все окна библиотеки Swing — а к ним относятся окно без рамки JWindow, окно с рамкой JFrame и диалоговое окно JDialog — являются исключением из правила, согласно которому все компоненты Swing представляют собой легковесные компоненты и унаследованы от базового класса JComponent. Окна Swing являются тяжеловесными контейнерами для размещения в них легковесных компонентов, которые операционная система не видит.

Наиболее полезные JFrame методы

МетодыОписание
setLocation()Эта группа методов позволяет задать позицию и размеры окна на экране. setLocation() задает позицию окна, setSize() позволяет указать его размеры, а с помощью setBounds() можно сразу задать прямоугольник, который займет ваше окно на экране
setSize()
setBounds()
раск()Позволяет «упаковать» имеющиеся в окне компоненты, так чтобы они занимали столько места, сколько им необходимо. Компоненты при вызове этого метода переходят в «видимое» состояние, хотя и не появляются на экране до вызова одного из следующих методов
show()Отображение окна на экране. После вызова этих методов компоненты переходят в «видимое» состояние и начинают обслуживаться очередью событий. Метод show() к тому же проводит валидацию содержащихся в окне компонентов
setVisible()
dispose()Убирает окно с экрана (если оно в момент вызова метода видимо) и освобождает все принадлежащие ему ресурсы.

Окно JWindow

«Родителем» всех окон Swing является окно без рамки и без элементов управления JWindow.

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

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

Рассмотрим пример JWindowTest. Основная идея использования окна без рамки JWindow заключается в копировании части "изображения рабочего стола" в окно приложения. Благодаря появившемуся в пакете JDK 1.3 классу Robot можно "снимать" экранную копию рабочего стола.

Пример JWindow

// Пример использования окна без рамки JWindow
import javax.swing.*;

import java.awt.*;

// Класс прорисовки изображения
class ImageDraw extends JComponent
{
    private Image capture;
    ImageDraw (Image capture) {
        this.capture = capture;
    }
    public void paintComponent(Graphics g) {
        // Прорисовка изображения
        g.drawImage(capture, 0, 0, this);
    }
}
public class JWindowTest extends JWindow
{
    // изображение "рабочего стола"
    private Image capture;
    // Размер окна 
    private int window_w = 300, window_h = 300;

    public JWindowTest() {
        super();
        // Определение положение окна на экране
        setLocation(200, 100);
        // Определение размера окна
        setSize (window_w, window_h);
        try {
            // "Вырезаем" часть изображения "рабочего стола"
            Robot robot = new Robot();
            capture = robot.createScreenCapture(
                      new Rectangle(5, 5, window_w, window_h));
        } catch (Exception ex) { ex.printStackTrace(); }
        // Добавляем в интерфейс изображение
        getContentPane().add(new ImageDraw(capture));
        // Открываем окно
        setVisible(true);
        try {
            // Заканчиваем работу через 10 сек
            Thread.currentThread();
            Thread.sleep(10000);
        } catch (Exception e) { }
            System.exit(0);
    }
    public static void main(String[] args) {
        new JWindowTest();
    }
}

В этом примере приложение наследуем от окна JWindow, чтобы удобнее вызывать методы этого класса и добавлять в окно компоненты. Объект Robot необходимо создавать в блоке try ... catch, т.к. его создание может быть запрещено менеджером безопасности, используемым виртуальной машиной Java. Впрочем, нам нарушение безопасности не грозит, потому что мы создаем отдельное приложение, а не апплет.

Вырезаем часть изображения "рабочего стола" методом createScreenCapture() в стороне он местоположения нашего окна. Затем в панель содержимого окна добавляется компонент ImageDraw, который и отображает вырезанное изображения рабочего стола. После вывода окна на экран программа засыпает на 10 секунд, а потом заканчивает свою работу.

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

Прежде чем производить настройку окна, в примере JWindowTest вызывается конструктор базового класса ключевым словом super() без параметров. На самом деле окна без рамки JWindow обязательно требуют при создании указывать своего «родителя» — окно с рамкой JFrame,что не всегда может быть неудобно. Специально для таких случаев в класс JWindow был добавлен конструктор без параметров, который создает вспомогательное невидимое окно JFrame и использует его как «родителя». После этого все окна без рамки, созданные таким образом, задействуют только это окно и экономят ресурсы.

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

Окно JFrame

Окно JFrame наследует свойства класса JWindow и представляет собой наиболее часто используемое в приложениях окно «общего назначения». Основные отличия окна JFrame от JWindow :

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

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

JFrame пример

import java.awt.Dimension;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.JFrame;
import javax.swing.JLabel;

public class JFrameWindowListener extends JFrame
{
    private static final long serialVersionUID = 1L;
    private static int    counter = 0; // счетчик
    private static JLabel label   = null;
    private static String TEMPL   = "Закрытие окна (попыток %d)";
    public JFrameWindowListener ()
    {
        // Создание окна с заголовком
        JFrame frame = new JFrame("JFrameWindowListener");
        // Не закрывать окно по нажатию на кнопку с крестиком 
        frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        // Подключение слушателя окна
        frame.addWindowListener(new WindowListener() {
 
            public void windowActivated  (WindowEvent event) {}
            public void windowClosed     (WindowEvent event) {}
            public void windowDeactivated(WindowEvent event) {}
            public void windowDeiconified(WindowEvent event) {}
            public void windowIconified  (WindowEvent event) {}
            public void windowOpened     (WindowEvent event) {}
            // Метод обработки события "Закрытие окна"
            public void windowClosing (WindowEvent event) {
                if (++counter == 3) {
                    event.getWindow().setVisible(false);
                    System.exit(0);
                } else
                    label.setText(String.format(TEMPL, counter));
            }
        }); 
        label = new JLabel(String.format(TEMPL, counter));
        frame.getContentPane().add(label);

        frame.setPreferredSize(new Dimension(250, 80));
        frame.pack();
        frame.setVisible(true);
    }
    public static void main(String[] args)
    {
        JFrame.setDefaultLookAndFeelDecorated(true);
        new JFrameWindowListener();
    }
}

В примере создается окно JFrame с определением заголовка в конструкторе базового класса. Для определения титульной строки окна можно также использовать метод setTitle() класса JFrame.

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

В примере методу setDefaultCloseOperation передается константа DO_NOTHING_ON_CLOSE - ничего не делать при закрытии окна. К окну JFrame подключается слушатель и обработка события закрытия окна выполняется в методе windowClosing. Алгоритм обработки построен таким образом, что окно закрывается при третьей попытке. Номер попытки отображается в метке интерфейса.

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

Для определения иконки окна необходимо использовать метод setIconImage(). Иконка располагается на кнопке свернутого окна или в заголовке окна в нормальном состоянии.

Из дополнительных возможностей окна с рамкой JFrame следует упомянуть о его способности «прятать» свои «украшения»: рамку и элементы управления окном. Делает это метод JWindow.

События окон, WindowListener, WindowFocusListener

Окна Swing (JWindow, JFrame, JDialog) поддерживают два типа событий :

  • WindowListener - позволяет узнать об изменениях в состоянии окна;
  • WindowFocusListener - сообщает о получении или потере компонентами окна фокуса ввода

Полный список методов данных слушателей можно найти в интерактивной документации Java.

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

К фрейму JFrame можно подключить слушателя окна, созданного на основе WindowAdapter (чтобы не реализовывать все определенные в интерфейсе WindowListener методы) и переопределить метод windowClosing, как это представлено в следующих строках кода :

// Добавляем слушателя событий от окна
frame.addWindowListener (new WindowAdapter() {
    @Override
	public void windowClosing(WindowEvent e) {
    // Потверждение закрытия окна JFrame
    int res = JOptionPane.showConfirmDialog(null, "Выйти из программы?");
    if (res == JOptionPane.YES_OPTION)
         System.exit(0);
    }
});

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

Диалоговое окно JDialog

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

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

При создании диалоговых окон Swing необходимо указать «родительское окно», которым может быть окно с рамкой JFrame или другое диалоговое окно JDialog. Имеется также конструктор, не требующий «родительского» окна, но использующий вспомогательное прозрачное окно, о котором было сказано на странице «Окно без рамки JWindow».

JDialog пример создания диалоговых окон

/**
 * Тестовый класс создания диалоговых окон
 */
import javax.swing.*;
import java.awt.event.*;

public class JDialogTest extends JFrame 
{
    private static final long serialVersionUID = 1L;
    public JDialogTest() {
        super("DialogWindows");
        // Выход из программы при закрытии
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        // Кнопки для создания диалоговых окон
        JButton button1 = new JButton("Немодальное окно");
        button1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                JDialog dialog = createDialog("Немодальное", false);
                dialog.setVisible(true);
            }
        });
        JButton button2 = new JButton("Модальное окно");
        button2.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                JDialog dialog = createDialog("Модальное", true);
                dialog.setVisible(true);
            }
        });
        // Создание панели содержимого с размещением кнопок
        JPanel contents = new JPanel();
        contents.add(button1);
        contents.add(button2);
        setContentPane(contents);
        // Определение размера и открытие окна
        setSize(350, 100);
        setVisible(true);
    }
    /** Функция создания диалогового окна.
     * @param title - заголовок окна
     * @param modal - флаг модальности
     */
    private JDialog createDialog(String title, boolean modal)
    {
        JDialog dialog = new JDialog(this, title, modal);
        dialog.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        dialog.setSize(180, 90);
        return dialog;
    }

    public static void main(String[] args)
    {
        new JDialogTest();
    }
}

В примере создаем окно с рамкой JFrame, в панели содержимого которого размещается две кнопки JButton. По нажатию на кнопки создаются диалоговые окна в отдельном методе createDialog(). Диалоговое окно с заданным заголовком JDialog может быть модальным и немодальным. Программа позволяет создать несколько немодальных окон одновременно, но только одно модальное. Немодальные окна не блокируют работу с основным окном приложения. При закрытии диалогового окна используется константа DISPOSE_ON_CLOSE, удаляющую окно после закрытия.

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

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

Оформление окон

Начиная с JDK 1.4 появилась возможность настраивать так называемое визуальное «оформление» окон: рамка, элементы управления окном (кнопки закрытия или свертывания), системное меню. Необходимость этого ощущалась с самых первых выпусков Swing.

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

В классах JFrame и JDialog имеется статический метод setDefaultLookAndFeelDecorated(), обеспечивающий возможность оформления всех создаваемых окон.

Пример оформления окон : JDialog decoration

// Оформление окон Swing

import javax.swing.*;

public class JFrameDecorations
{
    public static void main(String[] args)
    {
        // Подключение украшений для окон
        JFrame.setDefaultLookAndFeelDecorated(true);
        JDialog.setDefaultLookAndFeelDecorated(true);
        // Создание окна с рамкой
        JFrame frame = new JFrame("Oкнo с рамкой");
        // Определение способа завершения работы программы
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(200, 200);
        frame.setVisible(true);
        // Создание диалогового окна
        JDialog dialog = new JDialog(frame, "Диалоговое окно");
        // Определение способа завершения работы диалогового окна
        dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
        dialog.setSize(150, 100);
        // Определение типа оформления диалогового окна
        dialog.getRootPane().setWindowDecorationStyle(JRootPane.INFORMATION_DIALOG);
        dialog.setVisible(true);
    }
}

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

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

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

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

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

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

  Рейтинг@Mail.ru