Создание gui java. Создание графического интерфейса на Java Графические библиотеки

21.08.2020

Описание презентации Создание графического интерфейса на Java Графические библиотеки по слайдам

Графические библиотеки Java В Java есть следующие пакеты для создания графических интерфейсов: Abstract Windows Toolkit (AWT) — поставляется с JDK, каждый AWT-компонент имеет свой визуальный компонент (peer) для конкретной ОС, переносимость обеспечивается пакетом java. awt. peer; ограничен набор графических компонентов; внешний вид зависит от ОС. Standard Widget Toolkit (SWT) – поставляется отдельно для конкретных ОС, включена в среду Eclipce, взаимодействуют с ОС с помощью peer-интерфейсов, в отличии от AWT, расширен ассортимент компонентов. Swing – поставляется с JDK, расширяет классы AWT, не зависит от peer-компонентов ОС. Java 3 D – трехмерная графика.

Тяжело- и легковесные компоненты Тяжеловесные (heavyweight) компоненты – Отрисовываются операционной системой – Большинство AWT -компонент Легковесные (ligntweight) компоненты – Отрисовываются java -кодом – Все Swing -компоненты, кроме окон верхнего уровня (окно приложения) Тяжеловесные компоненты всегда отрисовываются поверх легковесных

Архитектура Модель-Представление-Контроллер(MVC) Шаблон проектирования MVC предполагает разделение данных приложения, пользовательского интерфейса и управляющей логики на три отдельных компонента: модель, представление и контроллер – таким образом, что модификация каждого компонента может осуществляться независимо. Модель (model) хранит данные компонента и позволяет легко, не обращаясь к самому компоненту, изменять или получать эти данные. Вид (view) выводит данные на экран для представления их пользователю. Контроллер (controller) определяет, как должны реагировать вид и данные модели в ответ на действия пользователя.

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

Взаимодействия между моделью, видом и контроллером Классическая модель Тесная связь между контроллером и моделью и контроллером и видом. Представление (вид) сопоставлено с единственным Контроллером и каждый Контроллер с единственным Представлением. Представление и Контроллер имеют прямую ссылку на Модель.

Пример MVC public class Model { private int int. Array = {1, 2, 3, 4, 5}; public String get. String. Array() { return «int. Array=» + Arrays. to. String(int. Array); } public void set. Int. Array(int index, int value) { this. int. Array = value; } } public class Controller { Model model = new Model(); View view = new View(); Controller(){ update. View(); } void set. Array. Value(int index, int value) { model. set. Int. Array(index, value); update. View(); } void update. View() { view. show. Array(model. get. String. Array()); } } public class View { public void show. Array(String array. String){ System. out. println(«View»); System. out. println(array. String); System. out. println(); } } public class User { public statc void main(String args) { Controller controller = new Controller(); controller. set. Array. Value(1, 4); } }

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

Компоненты интерфейса Button — кнопка; JCheck. Box — кнопка-флажок; JCombo. Box — выпадающий список; JLabel — метка, надпись; JList — список; JPassword. Field — текстовое поле для скрытого ввода; JProgress. Bar — компонент для отображения числа в некотором диапазоне; JRadio. Button — преключатели, радио-кнопки, обычно используется с компонентом Button. Group; JSlider — компонент позволяющий выбрать значение из заданного диапазона; JTable — таблица; JText. Field — однострочное текстовое поле; JText. Area — многострочное текстовое поле; JTree — дерево.

Контейнеры интерфейса Части пользовательского интерфейса, содержащие другие компоненты Контейнеры верхнего уровня: Frame, JFrame — окно приложения; JDialog — диалог приложения; JColor. Chooser — диалог выбора цвета; JFile. Chooser — диалог выбора файлов и директорий; File. Dialog — диалог выбора файлов и директорий (awt компонент). Простые контейнеры: JPanel — простая панель для группировки элементов, включая вложенные панели; JTool. Bar — панель инструментов (обычно это кнопки); JScrool. Pane — панель прокрутки, позволяющая прокручивать содержимое дочернего элемента; JDesktop. Pane — контейнер для создания виртуального рабочего стола или приложений на основе MDI (multple-document interface); JEditor. Pane , JText. Pane — контейнеры для отображения сложного документа как HTML или RTF; JTabbed. Pane — контейнер для управления закладками;

Создание окна import java. awt. *; class Too. Simple. Frame extends Frame{ public statc void main(String args){ Frame fr = new Too. Simple. Frame(); fr. set. Size(400, 150); // размер окна fr. set. Visible(true); // визуализация окна } // кнопка закрытия не работает } Swing

Окно с нестандартной иконкой import javax. swing. *; public class Frame. Closing extends JFrame { public Frame. Closing() { super(«Заголовок Окна»); // операция при закрытии окна set. Default. Close. Operaton(EXIT_ON_CLOSE); // при закрытии окна – выход // значок для окна set. Icon. Image(get. Toolkit(). get. Image(«icon. gif»)); //C: / icons / icon. png // вывод на экран set. Size(300, 100); // размеры окна ширина и высота set. Visible(true); // визуализация окна } public statc void main(String args) { new Frame. Closing(); } } Swing

Стандартные диалоговые окна Тип диалогового окна Описание NFORMATION_MESSAGE Диалоговое окно выводит информацию общего назначения со значком соответствующего вида WARNING_MESSAGE Диалоговое окно выводит на экран предупреждающую информацию со значком соответствующего вида QUESTION_MESSAGE Диалоговое окно вопроса для ввода информации ERROR_MESSAGE Диалоговое окно выводит на экран информацию об ошибке со значком соответствующего вида PLAIN_MESSAGE Указывает, что диалоговое окно не принадлежит ни к одному из вышеперечисленных типов. Выводится на экран без стандартного значка. Диалоговые окна могут быть модальными или немодальными Диалоговые окна могут быть модальными (фокус на окне, пока не нажата кнопка) или немодальными

Окна ввода и сообщений import java. awt. *; import javax. swing. *; public class Soluton { public static void main(String args) { JOpton. Pane. show. Message. Dialog(null , «Hello, World»); String s = JOpton. Pane. show. Input. Dialog(«Введите ваше имя»); } } Swing

Стандартные компоновщики Java 1. Компоновщик Border. Layout (полярное размещение). 2. Компоновщик Flow. Layout (последовательное размещение). 3. Компоновщик. Grid. Layout (табличное размещение). 4. Компоновщик Spring. Layout (относительное размещение). 5. Компоновщик Box. Layout (блочное размещение).

Полярное расположение (компоновщик Border. Layout) Значение Border. Layout. NORTH или строка «North» - компонент располагается вдоль верхней (северной) границы окна и растягивается на всю его ширину. Обычно так размещается панель инструментов. Значение Border. Layout. SOUTH или строка «South» - компонент располагается вдоль нижней (южной) границы и растягивается на всю ширину окна. Такое положение идеально для строки состояния. Значение Border. Layout. WEST или строка «West» - компонент располагается вдоль левой (западной) границы окна и растягивается на всю его высоту, однако при этом учитываются размеры северных и южных компонентов (они имеют приоритет). Значение Border. Layout. EAST или строка «East» - компонент располагается вдоль правой (восточной) границы окна. В остальном его расположение аналогично западному компоненту. Значение Border. Layout. CENTER или строка «Center» - компонент помещается в центр окна, занимая максимально возможное пространство.

Пример использования компоновщика Border. Layout import javax. swing. *; import java. awt. *; public class Border. Layout. Sample extends JFrame { public Border. Layout. Sample() { super(«Border. Layout. Sample»); set. Size(400, 300); set. Default. Close. Operaton(EXIT_ON_CLOSE); // получаем панель содержимого класса JFrame Container c = get. Content. Pane(); // По умолчанию в Swing используется менеджер Border. Layout // добавляем компоненты в панель, используя строковые константы c. add(new JButton(«Север»), «North»); c. add(new JButton(«Юг»), «South»); // или константы из класса Border. Layout // JLabelэлемент для отображения текста c. add(new JLabel(«Запад»), Border. Layout. WEST); c. add(new JLabel(«Восток»), Border. Layout. EAST); // если параметр не указывать вовсе, компонент автоматически добавится в центр c. add(new JButton(«Центр»)); // выводим окно на экран set. Visible(true); } public statc void main(String args) { new Border. Layout. Sample(); } } Swing

Последовательное размещение (компоновщик Flow. Layout) Компоновщик размещает компоненты слева направо, сверху вниз (по умолчанию в панелях Jpanel). import javax. swing. *; import java. awt. *; public class Flow. Layout. Sample extends JFrame { public Flow. Layout. Sample() { super(«Flow. Layout 1»); set. Size(400, 200); set. Default. Close. Operaton(EXIT_ON_CLOSE); // получаем панель содержимого Container c = get. Content. Pane(); // устанавливаем последовательное расположение с выравниванием компонентов по центру c. set. Layout(new Flow. Layout(Flow. Layout. CENTER)); // добавляем компоненты c. add(new JButton(«Один»)); c. add(new JButton(«Два»)); c. add(new JButton(«Три»)); // выводим окно на экран set. Visible(true); } public statc void main(String args) { new Flow. Layout. Sample(); } } import java. awt. *; import javax. swing. *; public class Soluton { public static void main(String args) { JOpton. Pane. show. Message. Dialog(null , «Hello, World»); } } Swing

Табличное расположение (компоновщик Grid. Layout) все компоненты имеют одинаковый размер. Доступное пространство разбивается на одинаковое количество ячеек, в каждую из которых помещается компонент; все компоненты всегда выводятся на экран, как бы ни было велико или мало доступное пространство. import java. awt. *; import javax. swing. *; import java. utl. *; class Grid. Test extends JFrame { Grid. Test(String s){ super(s); Container c = get. Content. Pane(); // 4 строки 4 столбца расстояния между строками и столбцами в пикселях c. set. Layout(new Grid. Layout(4, 4, 5, 5)); String. Tokenizer st = new String. Tokenizer(«7 8 9 / 4 5 6 * 1 2 3 — 0. = +»); while(st. has. More. Tokens()) c. add(new Button(st. next. Token())); set. Size(200, 200); set. Visible(true); } public statc void main(String args){ new Grid. Test(» Менеджер Grid. Layout»); } } Swing

Табличное расположение придаст кнопкам одинаковый размер, а последовательное расположение не даст им «расплыться» и заодно выровняет их по правому краю I mport java. awt. *; import javax. swing. *; public class Command. Buttons extends JFrame { public Command. Buttons() { super(«Command. Buttons»); set. Size(350, 250); set. Locaton(150, 100); set. Default. Close. Operaton(EXIT_ON_CLOSE); // создаем панель с табличным расположением для выравнивания размеров кнопок JPanel grid = new JPanel(new Grid. Layout(1, 2, 5, 0)); // 1 строка, 2 столбца, промежутки 5 пикс. по гориз, 0 по верт. // добавляем компоненты grid. add(new JButton(«OK»)); grid. add(new JButton(«Отмена»)); // помещаем полученное в панель с последовательным расположением, выровненным по правому краю JPanel flow = new JPanel(new Flow. Layout(Flow. Layout. RIGHT)); flow. add(grid); // получаем панель содержимого Container c = get. Content. Pane(); // помещаем строку кнопок вниз окна c. add(flow, Border. Layout. SOUTH); // выводим окно на экран set. Visible(true); } public statc void main(String args) { new Command. Buttons(); } } Swing

Блочное расположение (компоновщик Box. Layout) Менеджер блочного расположения выкладывает компоненты в контейнер блоками: столбиком (по оси Y) или полоской (по оси X), при этом каждый отдельный компонент можно выравнивать по центру, по левому или по правому краям, а также по верху или по низу.

Пример блочного размещения import java. awt. *; import javax. swing. *; public class Box 1 extends JFrame { public Box 1() { super(«Box 1 — Y»); set. Size(400, 200); set. Default. Close. Operaton(EXIT_ON_CLOSE); // получаем панель содержимого Container c = get. Content. Pane(); // устанавливаем блочное расположение по оси Y (столбиком) Box. Layout boxy = new Box. Layout(c, Box. Layout. Y_AXIS); c. set. Layout(boxy); // добавляем компоненты c. add(new JButton(«Один»)); c. add(new JButton(«Два»)); c. add(new JButton(«Три»)); // выводим окно на экран set. Visible(true); } statc class Box 2 extends JFrame { public Box 2() { super(«Box 2 — X»); // устанавливаем размер и позицию окна set. Size(400, 200); set. Locaton(100, 100); set. Default. Close. Operaton(EXIT_ON_CLOSE); // получаем панель содержимого Container c = get. Content. Pane(); // устанавливаем блочное расположение по оси X (полоской) Box. Layout boxx = new Box. Layout(c, Box. Layout. X_AXIS); c. set. Layout(boxx); // добавляем компоненты c. add(new JButton(«Один»)); c. add(new JButton(«Два»)); c. add(new JButton(«Три»)); // выводим окно на экран set. Visible(true); } } public statc void main(String args) { new Box 1(); new Box 2(); } } Swing 5 В этом примере создаются два окна. В одном из них реализовано блочное расположение по оси Y, в другом - блочное расположение по оси X.

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

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

Размещено на http://www.allbest.ru/

ВВЕДЕНИЕ

Последние несколько лет разработчики прилагали массу усилий, чтобы интегрировать графику и анимацию в свои апплеты и приложения Java. Используя интерфейсы прикладного программирования java.awt и javax.swing, разработчики могут реализовывать гораздо более сложные графические приложения, включая игры, хранители экрана, экранные заставки и трехмерный графический пользовательский интерфейс.

Цель работы.Расчетно-графическая работа посвящена построению приложений с использованием графического интерфейса библиотек java.awt и javax.swing.

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

1. ПОСТАНОВКА ЗАДАЧИ

Графический пользовательский интерфейс (GUI) - основной способ взаимодействия конечных пользователей с java-приложением. Для разработки прикладного программного обеспечения на языке Java, а точнее графического интерфейса приложений, обычно используются пакеты AWT и Swing.

AWT (для доступа загружается пакет java.awt) содержит набор классов, позволяющих выполнять графические операции и создавать оконные элементы управления, подобно тому, как это делается в VBA и Delphi;

Swing (для доступа загружается пакет javax.swing) содержит новые классы, в основном аналогичные AWT. К именам классов добавляется J (JButton, JLabel и др.).

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

import javax. swing.*;

public final class HelloWorld implements Runnable {

public static void main(String args) {

//Swing имеет собственный управляющий поток (т.н. dispatching thread),

//который работает параллельно с основным (в котором выполняется main())

//потоком. Если основной поток закончит работу (метод main завершится),

//поток отвечающий за работу Swing-интерфейса может продолжать свою работу.

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

//(до тех пор, пока жив данный поток). Начиная с Java 6, когда все

//компоненты уничтожены, управляющий поток останавливается автоматически.

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

SwingUtilities.invokeLater (new HelloWorld());

public void run() {

// Создаем окно с заголовком "Hello, World!"

Frame f = new JFrame ("Hello, World!");

// Ранее практиковалось следующее: создавался listener и регистрировался

// на экземпляре главного окна, который реагировал на windowClosing()

// принудительной остановкой виртуальной машины вызовом System.exit()

// Теперь же есть более "правильный" способ задав реакцию на закрытие окна.

// Данный способ уничтожает текущее окно, но не останавливает приложение. Тем

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

f.setDefaultCloseOperation (JFrame. DISPOSE_ON_CLOSE);

// однако можно задать и так:

// f.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);

// Добавляем на панель окна нередактируемый компонент с текстом.

// f.getContentPane().add (new JLabel("Hello, World!")); - старый стиль

f.add(new JLabel("Hello World"));

// pack() "упаковывает" окно до оптимального размера

// всех расположенных в нем компонентов.

// Показать окно

f.setVisible(true);

Технология Swing предоставляет механизмы для управления следующими аспектами представления:

Клавиатура (Swing предоставляет способ перехвата пользовательского ввода);

Цвета (Swing предоставляет способ менять цвета, которые вы видите на экране);

Текстовое поле для ввода (Swing предоставляет текстовые компоненты для обработки всех повседневных задач).

JComponent

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

JLabel

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

get/setText() - получить/установить текст в метке;

get/setIcon() - получить/установить изображение в метке;

get/setHorizontalAlignment - получить/установить горизонтальную позицию текста;

get/setDisplayedMnemonic() - получить/установить мнемонику (подчеркнутый символ) для метки;

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

JButton

Основным активным компонентом в Swing является Jbutton.

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

get/setText() - получить/установить текст в кнопке;

get/setIcon() - получить/установить изображение в кнопке;

get/setHorizontalAlignment() - получить/установить горизонтальную позицию текста;

get/setVerticalAlignment() - получить/установить вертикальную позицию текста;

get/setDisplayedMnenomic() - получить/установить мнемонику (подчеркнутый символ), которая в комбинации с кнопкой Alt вызывает нажатие кнопки.

JFrame

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

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

get/setTitle() - получить/установить заголовок фрейма;

get/setState() - получить/установить состояние фрейма (минимизировать, максимизировать и т.д.);

is/setVisible() - получить/установить видимость фрейма, другими словами, отображение на экране;

get/setLocation() - получить/установить месторасположение в окне, где фрейм должен появиться;

get/setSize() - получить/установить размер фрейма;

add() - добавить компоненты к фрейму.

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

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

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

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

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

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

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

графический интерфейс java компонент

2. РЕАЛИЗАЦИЯ ЗАДАЧИ НА ЯЗЫКЕ ВЫСОКОГО УРОВНЯ JAVA

import java.awt.*;

import java.awt.geom.*;

import java.awt.image.BufferedImage;

* Задача 4. Изобразить в окне приложения (апплета ) отрезок , вращающийся в

* плоскости фрейма вокруг точки движущейся по отрезку .

public class LB4 extends java.applet.Applet implements Runnable {

private static final long serialVersionUID = 1L;

private int w, h;

private BufferedImage bi;

private Graphics2D big;

private boolean stop = false;

private Thread timer = null;

private Color fonColor = Color.WHITE ;

private Color segmentColor = Color.LIGHT_GRAY ;

private Color pointColor = Color.GREEN ;

private Segment segment;

// начальное расположение рисунка

private double lengthSegment;

// направление смещения оси вращения

private double movePoint = -1;

private double shift = 0;

private double speedPoint = 1;

// скорость изменения положения в пространстве

private int speedRepaint = 30;

// угол на который происходит изменения положения отрезка

private int grad = 15;

/** Этот метод будет вызван после загрузки апплета */

public void init() {

// Создаем объекты и устанавливаем начальные значения .

Dimension dim = getSize();

// Создаем Segment, задавая длину

lengthSegment = (double) Math.min (w, h) / 3;

segment = new Segment(lengthSegment, lengthSegment / 2, grad,

segmentColor, pointColor, fonColor);

bi = (BufferedImage) createImage(w, h);

big = bi.createGraphics();

big.setRenderingHint(RenderingHints.KEY_ANTIALIASING ,

RenderingHints.VALUE_ANTIALIAS_ON );

// Создаем поток , который будет периодически вызывать метод update.

timer = new Thread(this);

} catch (Exception e) {

System.out .println(e);

} // end init

// Этот метод выполняет перерисовку окна апплета

public void update(Graphics g) {

// Получаем указатель на объект Graphics2D

Graphics2D g2 = (Graphics2D) g;

// Рисуем готовое изображение на экране

g2.drawImage(bi, 0, 0, this);

} catch (Exception error) {

System.out .println(error.getMessage());

private void grawSegment() {

* //Очищаем рисунок big.setBackground(Color.BLUE); big.clearRect(0, 0,

// Рисуем отрезок

shift += movePoint * speedPoint;

if (shift < -lengthSegment / 2) {

movePoint *= -1;

shift = -lengthSegment / 2;

} else if (shift > lengthSegment / 2) {

movePoint *= -1;

shift = lengthSegment / 2;

segment.setPos(shift, speedPoint);

segment.rotate();

big.drawImage(segment.getSegment(), null, 0, 0);

// Этот метод выполняется в отдельном потоке (timer).

// Он вызывает перерисовку окна апплета каждую секунду .

public void run() {

Thread.currentThread ();

Thread.sleep (speedRepaint);

} catch (Exception err) {

// Этот метод выполняется если пользователь покинул страницу

// с апплетом . Он останавливает поток (timer) и, соответственно ,

// перерисовку окна апплета.

public void stop() {

// Этот метод выполняется когда пользователь попадает на страницу

// с апплетом. Он запускает парралельный поток (timer).

public void start() {

if (timer == null) {

timer = new Thread(this);

// Этот метод выполняется при закрытии страницы с апплетом.

public void destroy() {

super.destroy();

Thread.currentThread ();

// Ждем пока парралельный поток (timer) завершит работу.

Thread.yield ();

} // end destroy

} // end public class RotatingSegment

// создание отрезка

private static double x = 0;

final double RAD = 10;

private double length;

private BufferedImage segment;

private Color segmentColor;

private Color pointColor;

private Color backGroundColor;

private Rectangle2D.Double r;

private Ellipse2D.Double p;

private double rotationAxis;

private Point2D.Double center;

private double shift;

// угол на который происходит изменения положения отрезка

private int grad;

Segment(double length, double posPointRotating, int grad,

Color segmentColor, Color pointColor, Color backGroundColor)

throws Exception {

// проверяем параметры

if (length <= 0 || posPointRotating < 0 || length < posPointRotating)

throw new Exception(

"Ошибка: неверно задан параметр в классе Segment");

this.grad = grad;

this.segmentColor = segmentColor;

this.pointColor = pointColor;

this.backGroundColor = backGroundColor;

this.length = length;

// создаем рисунок

segment = new BufferedImage((int) length * 3, (int) length * 3,

BufferedImage.TYPE_INT_ARGB );

center = new Point2D.Double(length, 3 * length / 2);

// создаем отрезок

rotationAxis = center.x + posPointRotating - RAD / 2;

p = new Ellipse2D.Double(rotationAxis, center.y, RAD, RAD);

// устанавливаем цвет отрезка

g2.setColor(segmentColor);

// рисуем отрезок

// устанавливаем цвет точки

g2.setColor(pointColor);

// рисуем точку

// смещает точку вращения

public void setPos(double shiftX, double shiftY) {

// создаем отрезок

this.shift = shiftX;

center.y = center.y + shiftY * Math.sin (Math.toRadians (grad * x ));

r = new Rectangle2D.Double(center.x, center.y, length, RAD);

p = new Ellipse2D.Double(rotationAxis + shift, center.y, RAD, RAD);

// вращает отрезок

public void rotate() {

AffineTransform at = AffineTransform.getRotateInstance (

Math.toRadians (grad * (++x )), rotationAxis + RAD / 2 + shift,

// получаем графический контекст

Graphics2D g2 = segment.createGraphics();

// закрашиваем все заданным цветом

g2.setBackground(backGroundColor);

g2.clearRect(0, 0, (int) (3 * length), (int) (3 * length));

g2.setTransform(at);

g2.setColor(segmentColor);

// рисуем отрезок

// устанавливаем цвет точки

g2.setColor(pointColor);

// рисуем точку

// Возвращает изображение

public BufferedImage getSegment() {

3. ПРИМЕР РАБОТЫ ПРОГРАММЫ

Результат выполнения программы:

Рисунок 1. Результат выполнения программы

Рисунок 2. Результат выполнения программы

Рисунок 3. Результат выполнения программы

ЗАКЛЮЧЕНИЕ

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

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

Вторая половина нашего знакомства с графическим программированием на Java. Используя графический интерфейс библиотек java.awt и javax.swing мы создали простой графический редактор, который вращает двумерный объект вокруг своей оси.

СПИСОК ЛИТЕРАТУРЫ

1. Х. М. Дейтел, П.Дж. Дейтел, С.И. Сантри - Технологии программирования наJava, книга 1 (графика, JAVABEANS, интерфейс пользователя)

2. Джуди Бишоп - Эффективная работа Java

3. James Gosling, Bill Joy, Guy Steele, Gilad Bracha - The Java Language Specification, Second Edition.

4. Tim Lindholm, Frank Yellin - The Java Virtual Machine Specification, Second Edition.

5. Гослинг Дж., Арнольд К. - Язык программирования Java

6. Информация с сайта www.ibm.com

7. Информация с сайта www.mexmat.sgu.ru

8. Информация с сайта www.uic.rsu.ru

Размещено на Allbest.ru

...

Подобные документы

    Структура организации графического интерфейса, объявление и создание слушателей событий с помощью анонимных классов. Представление данных для таблицы – класс AbstractTableModel. Визуализация ячеек таблицы. Два основных типа потоков ввода-вывода в Java.

    лекция , добавлен 01.05.2014

    Разработка графического редактора для рисования двухмерной и трехмерной графики, используя язык программирования Java и интерфейсы прикладного программирования Java 2D и Java 3D. Создание графического редактора 3D Paint. Основные методы класса Graphics.

    курсовая работа , добавлен 19.11.2009

    Описание пакета прикладной программы Net Beans 8.1. Разработка пользовательского интерфейса апплета. Создание рамочных окон на базе фреймов библиотеки java.swing. Изменение цвета текстовых данных. Проектирование и создание инфологической модели апплета.

    контрольная работа , добавлен 11.07.2016

    Сетевые возможности языков программирования. Преимущества использования Java-апплетов. Классы, входящие в состав библиотеки java.awt. Создание пользовательского интерфейса. Сокетное соединение с сервером. Графика в Java. Значения составляющих цвета.

    курсовая работа , добавлен 10.11.2014

    Java Foundation Classes, основные концепции. Исходная иерархия классов Abstract Window Toolkit. Представители пользовательского интерфейса. Обработка событий в JavaBeans. Элементы управления, многострочное поле JText. Листинг программы TextEditor.

    курсовая работа , добавлен 26.06.2013

    Выполнение Java-программы. Набор программ и классов JDK. Объектно-ориентированное программирование в Java. Принципы построения графического интерфейса. Компонент и контейнер графической системы. Апплеты как программы, работающие в среде браузера.

    курсовая работа , добавлен 08.02.2011

    Диаграмма консольного приложения табулирования функции. Отличие консольного приложения и приложения и GUI. Диаграмма классов для JFrameи JPanel. Создание простейшего фрейма в Java. Компоновка элементов интерфейса внутри фрейма. Цикл обработки событий.

    лекция , добавлен 01.05.2014

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

    презентация , добавлен 13.06.2014

    Разработка логической схемы базы данных автомобилестроительного предприятия. Инфологическое моделирование системы. Создание графического интерфейса пользователя для базы данных средствами языка программирования Java. Тестирование программных средств.

    курсовая работа , добавлен 16.12.2013

    Создание консольных приложений с использованием графического интерфейса пользователя. Содержание палитры компонентов программы С++ Builder. Использование возможностей объектно-ориентированного программирования, особенности редактора кода и форм в С++.

Так исторически сложилось, что с UI мне приходилось работать очень мало. Видимо, поэтому мне так интересные всякие там Qt и wxWidgets — все кажется новым, интересным, необычным. Впрочем, коль скоро я взялся за изучение Java , речь сегодня пойдет не о Qt и не о wxWidgets, а о Swing. Сегодня совместными усилиями мы напишем простенькое GUI-приложение на Java, с кнопочками, списками и даже умеющее менять шкурки!

Ситуация с GUI фреймворками в мире Java несколько запутанная. Насколько я смог разобраться, дела обстоят следующим образом.

  • AWT (Abstract Window Toolkit) был первым GUI фреймворком. Идея была правильная — AWT использует нативные контролы, то есть, они выглядят и физически являются родными, независимо от того, где вы запускаете свое приложение. К сожалению, оказалось, что (1) общих для различных окружений контролов мало и (2) писать кроссплатформенные нативные интерфейсы так, чтобы ничего не поползло и не разъехалось, очень сложно;
  • Поэтому на смену AWT пришел Swing . Swing использует формочки, создаваемые AWT, на которых он своими силами рисует контролы. Работает это хозяйство, понятно дело, медленнее, но зато UI становится намного более портабельным. Swing предлагает на выбор программисту множество Look&Feel, благодаря которым можно сделать либо так, чтобы приложение выглядело и вело себя одинаково как под Windows, так и под Linux, либо чтобы приложение было очень похоже на нативное независимо от того, где его запускают. В первом случае приложение проще отлаживать, во втором — становятся счастливее пользователи. Кстати, изначально Swing был сделан парнями из Netscape;
  • SWT (Standard Widget Toolkit) — фреймворк, написанный в IBM и используемый в Eclipse. Как и в AWT, используются нативные контролы. SWT не входит в JDK и использует JNI, поэтому не очень соответствует идеологии Java «написано однажды, работает везде». Вроде как при очень сильном желании можно запаковать в пакет реализацию SWT для всех-всех-всех платформ, и тогда приложение вроде как даже станет портабельным, но только до тех пор, пока не появится какая-нибудь новая операционная система или архитектура процессора;
  • JavaFX активно пилится в Oracle и позиционируется, как скорая замена Swing. Идеологически JavaFX похож на Swing, то есть, контролы не нативные. Среди интересных особенностей JavaFX следует отметить хардверное ускорение, создание GUI при помощи CSS и XML (FXML), возможность использовать контролы JavaFX’а в Swing’е, а также кучу новых красивых контролов, в том числе для рисования диаграмм и 3D. Видео с более детальным обзором JavaFX можно . Начиная с Java 7, JavaFX является частью JRE/JDK ;
  • NetBeans Platform (не путать с NetBeans IDE!) — это такая штука, которая, как я понял, работает поверх Swing и JavaFX, предоставляет как бы более удобный интерфейс для работы с ними, а также всякие дополнительные контролы. В одном приложении, использующем NetBeans Platform, я видел возможность перетаскивать вкладки drug&drop’ом, располагая панели в окне подобно тому, как это делают тайловые оконные менеджеры . По всей видимости, сам Swing так не умеет. Почитать про NetBeans Platform поподробнее ;

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

Выше что-то говорилось про какие-то там Look&Feel. Чтобы лучше понять, о чем идет речь, давайте напишем программу, которая выводит список этих самых Look&Feel и позволит переключаться между ними прямо в процессе работы программы.

Наше приложение будет выглядеть следующим образом под Ubuntu:

А так оно будет выглядеть при запуске под Windows:

Как видите, JRE под Windows и Linux включают в себя разный набор L&F. Кроме того, вы можете подключить сторонний Look&Feel или даже написать свой. По умолчанию используется L&F Metal, который во всех ОС и оконных менеджерах выглядит более-менее одинаково. Если вам больше нравятся круглые кнопочки, то вместо Metal можно использовать Look&Feel Nimbus. Если вам хочется, чтобы приложение было похоже на нативное, то под Linux следует выбрать L&F GTK+ (интересно, а если пользователь сидит под KDE?), а под Windows — L&F Windows. Неплохой идеей, видимо, будет предусмотреть в вашей программе возможность переключаться между различными L&F. С другой стороны, при этом придется тестировать работу приложения со всеми этими L&F.

Давайте посмотрим на исходный код приложения. Коллеги UI-щики заверили меня, что никаких WYSIWYG редакторов они не используют, а если используют, то разве что для быстрого прототипирования. Из неплохих WYSIWYG редакторов назывался JFormDesigner . Говорят, генерируемый им код даже похож на код, написанный человеком, а не адовую().последовательность().вызовов().методов(). В общем, весь код писался лапками в IntelliJ IDEA .

public static void main(String args) {

@Override
public void run() {
createGUI() ;
}
} ) ;
}

В Swing и AWT, если мы хотим что-то поменять в UI, мы должны делать это из event dispatching thread. Статический метод invokeLater принимает класс, реализующий интерфейс Runnable, и вызывает его метод run() внутри event dispatching thread. Если вам не знаком приведенный выше синтаксис, то это такой способ в Java объявить класс, не присваивая ему имени. Классы без имени называются анонимными. Часто анонимные классы в Java выполняют ту же роль, что играют лямда-фукнции в функциональных языках программирования. Помимо прочего, поддерживаются и замыкания. Интересно, что, в отличие от лямбд, анонимные классы в Java позволяют передать сразу пачку методов. Притом, при помощи наследования и абстрактных классов, для всех или части методов можно взять их реализацию по умолчанию.

Аннотация @Override проверяет, что метод run() действительно переопределит метод интерфейса Runnable. Без нее при переопределении метода мы можем случайно сделать опечатку и определить новый метод вместо того, чтобы переопределить существующий. Впрочем, в данном конкретном случае аннотация, видимо, не очень полезна, и, наверное, даже является лишней.

В итоге event dispatching thread вызовет метод createGUI(), полный код которого следующий:

private static void createGUI() {
JList< String> list = new JList<> () ;
list.setSelectionMode (ListSelectionModel .SINGLE_SELECTION ) ;

JScrollPane listScrollPane = new JScrollPane (list) ;

JPanel topPanel = new JPanel () ;
topPanel.setLayout (new BorderLayout () ) ;
topPanel.add (listScrollPane, BorderLayout .CENTER ) ;

ActionListener updateButtonListener = new UpdateListAction(list) ;
updateButtonListener.actionPerformed (
new ActionEvent (list, ActionEvent .ACTION_PERFORMED , null )
) ;

JButton updateListButton = new JButton ("Update list" ) ;
JButton updateLookAndFeelButton = new JButton ("Update Look&Feel" ) ;

JPanel btnPannel = new JPanel () ;
btnPannel.setLayout (new BoxLayout (btnPannel, BoxLayout .LINE_AXIS ) ) ;
btnPannel.add (updateListButton) ;
btnPannel.add (Box .createHorizontalStrut (5 ) ) ;
btnPannel.add (updateLookAndFeelButton) ;

JPanel bottomPanel = new JPanel () ;
bottomPanel.add (btnPannel) ;

JPanel panel = new JPanel () ;
panel.setBorder (BorderFactory .createEmptyBorder (5 ,5 ,5 ,5 ) ) ;
panel.setLayout (new BorderLayout () ) ;
panel.add (topPanel, BorderLayout .CENTER ) ;
panel.add (bottomPanel, BorderLayout .SOUTH ) ;

JFrame frame = new JFrame ("Look&Feel Switcher" ) ;
frame.setMinimumSize (new Dimension (300 , 200 ) ) ;
frame.setDefaultCloseOperation (WindowConstants .EXIT_ON_CLOSE ) ;
frame.add (panel) ;
frame.pack () ;
frame.setVisible (true ) ;

UpdateListButton.addActionListener (updateButtonListener) ;
updateLookAndFeelButton.addActionListener (
new UpdateLookAndFeelAction(frame, list)
) ;
}

Тут, в общем-то, нет ничего супер сложного. Создаются кнопки, список, список заворачивается в JScrollPane, чтобы у списка была прокрутка. Элементы управления располагаются во фрейме при помощи панелей. Панели могут иметь различные лайоуты, здесь мы использовали BorderLayout и BoxLayout . Принцип аналогичен тому, что используется в wxWidgets .

Для реакции на различные события, например, нажатия кнопок, используются классы, реализующие интерфейс ActionListener. В приведенном выше коде используется два таких класса — UpdateListAction и UpdateLookAndFeelAction. Как нетрудно догадаться по названию, первый класс отвечает за обработку нажатий на левую кнопку «Update list», второй — на правую кнопку «Update Look&Feel». ActionListener’ы привязываются к кнопкам при помощи метода addActionListener. Поскольку сразу после запуска приложения нам хочется увидеть список доступных Look&Feel, мы эмулируем нажатие на кнопку «Update list». Для этого мы создаем экземпляр класса ActionEvent и передаем его в качестве аргумента методу actionPerformed класса UpdateListAction.

Реализация класса UpdateListAction следующая:

static class UpdateListAction implements ActionListener {
private JList< String> list;

public UpdateListAction(JList< String> list) {
this .list = list;
}

@Override
public void actionPerformed(ActionEvent event) {
ArrayList< String> lookAndFeelList = new ArrayList<> () ;
UIManager.LookAndFeelInfo infoArray =

int lookAndFeelIndex = 0 ;
int currentLookAndFeelIndex = 0 ;
String currentLookAndFeelClassName =
UIManager .getLookAndFeel () .getClass () .getName () ;

for (UIManager.LookAndFeelInfo info : infoArray) {
if (info.getClassName () .equals (currentLookAndFeelClassName) ) {
currentLookAndFeelIndex = lookAndFeelIndex;
}
lookAndFeelList.add (info.getName () ) ;
lookAndFeelIndex++;
}

String listDataArray = new String [ lookAndFeelList.size () ] ;
final String newListData =
lookAndFeelList.toArray (listDataArray) ;
final int newSelectedIndex = currentLookAndFeelIndex;

SwingUtilities .invokeLater (new Runnable () {
@Override
public void run() {
list.setListData (newListData) ;
list.setSelectedIndex (newSelectedIndex) ;
}
} ) ;
}
}

В конструкторе передается указатель на список, в котором мы будет отображать доступные Look&Feel. На самом деле, поскольку UpdateListAction является вложенным классом нашего основного класса LookAndFeelSwitcher, у него есть возможность обращаться напрямую к полям создавшего его экземпляра LookAndFeelSwitcher. Но функциональщик внутри меня сопротивляется такому подходу, поэтому я решил передать ссылку на список явно через конструктор.

Метод actionPerformed будет вызываться при нажатии на кнопку. Код этого метода довольно тривиален — мы просто используем статические методы класса UIManager для получения списка доступных Look&Feel, а также определения текущего Look&Feel. Затем обновляется содержимое списка и выбранный в нем элемент. Тут нужно обратить внимание на два момента. Во-первых, каждый Look&Feel имеет имя и имя класса , это разные вещи. Пользователю мы должны показывать имена, а при переключении Look&Feel использовать имя класса. Во-вторых, обратите внимание на то, как создаются final переменные newListData и newSelectedIndex, которые затем используются в анонимном классе. Это и есть тот самый аналог замыканий, речь о котором шла ранее. Очевидно, использование не final переменных в замыканиях привело бы к печальным последствиям.

Наконец, рассмотрим класс UpdateLookAndFeelAction:

static class UpdateLookAndFeelAction implements ActionListener {
private JList< String> list;
private JFrame rootFrame;

public UpdateLookAndFeelAction(JFrame frame, JList< String> list) {
this .rootFrame = frame;
this .list = list;
}

@Override
public void actionPerformed(ActionEvent e) {
String lookAndFeelName = list.getSelectedValue () ;
UIManager.LookAndFeelInfo infoArray =
UIManager .getInstalledLookAndFeels () ;

for (UIManager.LookAndFeelInfo info : infoArray) {
if (info.getName () .equals (lookAndFeelName) ) {
String message = "Look&feel was changed to " + lookAndFeelName;
try {
UIManager .setLookAndFeel (info.getClassName () ) ;
SwingUtilities .updateComponentTreeUI (rootFrame) ;
} catch (ClassNotFoundException e1) {
message = "Error: " + info.getClassName () + " not found" ;
} catch (InstantiationException e1) {
message = "Error: instantiation exception" ;
} catch (IllegalAccessException e1) {
message = "Error: illegal access" ;
} catch (UnsupportedLookAndFeelException e1) {
message = "Error: unsupported look and feel" ;
}
JOptionPane .showMessageDialog (null , message) ;
break ;
}
}
}
}

Здесь мы просто (1) находим L&F с именем, равным имени, выбранному в списке, (2) меняем L&F при помощи static метода setLookAndFeel класса UIManager и (3) перерисовываем главный фрейм нашего UI, а также, рекурсивно, расположенные на нем элементы, при помощи static метода updateComponentTreeUI класса SwingUtilities. Наконец, мы уведомляем пользователя при помощи сообщения, все ли прошло успешно.

Также хотелось бы сказать пару слов об отладке GUI-приложений на Java, и не только GUI. Во-первых, в Swing есть такое волшебное сочетание клавиш Ctr + Shift + F1, которое выводит в stdout информацию о том, как расположены контролы. Очень полезно, если хочется слизать UI у конкурентов. Во-вторых, есть такой интересный хоткей Ctr + \. Если нажать его в консоли работающего приложения на Java, будут выведены все нитки и их стектрейсы. Удобно, если вы словили дэдлок. Наконец, в-третьих, во время разработки GUI бывает полезно разукрасить панели в разные цвета. Сделать это можно так:

buttonsPanel.setBackground (Color .BLUE ) ;

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

Java AWT

Первой попыткой Sun создать графический интерфейс для Java была библиотека AWT (Abstract Window Toolkit) - инструментарий для работы с различными оконными средами. Sun сделал прослойку на Java, которая вызывает методы из библиотек, написанных на С. Библиотечные методы AWT создают и используют графические компоненты операционной среды. С одной стороны, это хорошо, так как программа на Java похожа на остальные программы в рамках одной ОС. Но при запуске ее на другой платформе могут возникнуть различия в размерах компонентов и шрифтов, которые будут портить внешний вид программы.

Чтобы обеспечить мультиплатформенность AWT интерфейсы вызовов компонентов были унифицированы, вследствии чего их функциональность получилась немного урезанной. Да и набор компонентов получился довольно небольшой. Так например, в AWT нет таблиц, а в кнопках не поддерживается отображение иконок. Тем не менее пакет java.awt входит в Java с самого первого выпуска и его можно использовать для создания графических интерфейсов.

Таким образом, компоненты AWT не выполняют никакой "работы". Это просто «Java-оболочка» для элементов управления той операционной системы, на которой они работают. Все запросы к этим компонентам перенаправляются к операционной системе, которая и выполняет всю работу.

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

Основные концепции SWING

Вслед за AWT Sun разработала графическую библиотеку компонентов Swing , полностью написанную на Java. Для отрисовки используется 2D, что принесло с собой сразу несколько преимуществ. Набор стандартных компонентов значительно превосходит AWT по разнообразию и функциональности. Swing позволяет легко создавать новые компоненты, наследуясь от существующих, и поддерживает различные стили и скины.

Создатели новой библиотеки пользовательского интерфейса Swing не стали «изобретать велосипед» и в качестве основы для своей библиотеки выбрали AWT. Конечно, речь не шла об использовании конкретных тяжеловесных компонентов AWT (представленных классами Button, Label и им подобными). Нужную степень гибкости и управляемости обеспечивали только легковесные компоненты. На диаграмме наследования представлена связь между AWT и Swing.

Важнейшим отличием Swing от AWT является то, что компоненты Swing вообще не связаны с операционной системой и поэтому гораздо более стабильны и быстры. Такие компоненты в Java называются легковесными (lightweight), и понимание основных принципов их работы во многом объяснит работу Swing.

Swing контейнеры высшего уровня

Для создания графического интерфейса приложения необходимо использовать специальные компоненты библиотеки Swing, называемые контейнерами высшего уровня (top level containers). Они представляют собой окна операционной системы, в которых размещаются компоненты пользовательского интерфейса. К контейнерам высшего уровня относятся окна JFrame и JWindow, диалоговое окно JDialog, а также апплет JApplet (который не является окном, но тоже предназначен для вывода интерфейса в браузере, запускающем этот апплет). Контейнеры высшего уровня Swing представляют собой тяжеловесные компоненты и являются исключением из общего правила. Все остальные компоненты Swing являются легковесными.

Простой Swing пример создания оконного интерфейса JFrame .

Import java.awt.Dimension; import javax.swing.JFrame; import javax.swing.JLabel; public class JFrameTest { public static void createGUI() { JFrame frame = new JFrame("Test frame"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JLabel label = new JLabel("Test label"); frame.getContentPane().add(label); frame.setPreferredSize(new Dimension(200, 100)); frame.pack(); frame.setVisible(true); } public static void main(String args) { JFrame.setDefaultLookAndFeelDecorated(true); javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { createGUI(); } }); } }

Конструктор JFrame() без параметров создает пустое окно. Конструктор JFrame(String title) создает пустое окно с заголовком title. Чтобы создать простейшую программу с пустым окном необходимо использовать следующие методы:

  • setSize(int width, int height) - определение размеров окна;
  • setDefaultCloseOperation(int operation) - определение действия при завершении программы;
  • setVisible(boolean visible) - сделать окно видимым.

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

Метод setDefaultCloseOperation определяет действие, которое необходимо выполнить при "выходе из программы". Для этого следует в качестве параметра operation передать константу EXIT_ON_CLOSE, описанную в классе JFrame.

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

Графический интерфейс java swing примера создания окна JFrame представлен на следующем рисунке.

Для подключения библиотеки Swing в приложении необходимо импортировать библиотеку javax.swing .

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

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

На следующем рисунке наглядно представлена структура корневой панели JRootPane .

Корневая панель JRootPane представляет собой контейнер, унаследованный от базового класса Swing JComponent. В этом контейнере за расположение компонентов отвечает специальный менеджер расположения, реализованный во внутреннем классе RootPaneLayout. Этот менеджер расположения отвечает за то, чтобы все составные части корневой панели размещались так, как им следует: многослойная панель занимает все пространство окна; в ее слое FRAME_CONTENT_LAYER располагаются строка меню и панель содержимого, а над всем этим располагется прозрачная панель.

Все составляющие корневой панели JRootPane можно получить или изменить. Для этого у нее есть набор методов get/set. Программным способом JRootPane можно получить с использованием метода getRootPane().

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

Многослойная панель JLayeredPane

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

JLayeredPane используется для добавления в контейнер свойства глубины (depth). To есть, многослойная панель позволяет организовать в контейнере третье измерение, вдоль которого располагаются слои (layers) компонента. В обычном контейнере расположение компонента определяется прямоугольником, который показывает, какую часть контейнера занимает компонент. При добавлении компонента в многослойную панель необходимо указать не только прямоугольник, занимаемый компонентом, но и слой, в котором он будет располагаться. Слой в многослойной панели определяется целым числом. Чем больше определяющее слой число, тем выше слой находится.

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

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

Многослойная панель позволяет организовать неограниченное количество слоев. Структура JLayeredPane включает несколько стандартных слоев, которые и используются всеми компонентами Swing, что позволяет обеспечить правильную работу всех механизмов многослойной панели. Стандартные слои JLayeredPane представлены на следующем рисунке.

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

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

Слой Modal планировался для размещения легковесных модальных диалоговых окон. Однако такие диалоговые окна пока не реализованы, так что этот слой в Swing в настоящее время не используется.

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

Самый верхний слой. Предназначен для операций перетаскивания (drag and drop), которые должны быть хорошо видны в интерфейсе программы.

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

Import javax.swing.*; import java.awt.*; // класс рисования двух типов фигур с текстом class Figure extends JComponent { private static final long serialVersionUID = 1L; private Color color; private int type; private String text; // параметры: цвет и тип фигуры Figure(Color color, int type, String text) { this.color = color; this.type = type; this.text = text; setOpaque(false); } public void paintComponent(Graphics g) { // прорисовка фигуры g.setColor(color); switch (type) { case 0: g.fillOval(0, 0, 90, 90); break; case 1: g.fillRect(0, 0, 130, 80); break; } g.setColor(Color.yellow); g.drawString(text, 10, 35); } } public class JLayeredPaneTest extends JFrame { private static final long serialVersionUID = 1L; public JLayeredPaneTest() { // создание окна super("Example LayeredTest"); // выход при закрытии окна setDefaultCloseOperation(EXIT_ON_CLOSE); // определение многослойной панели JLayeredPane lp = getLayeredPane(); // создание трех фигур Figure figure1 = new Figure(Color.red , 0, "Figure popup"); Figure figure2 = new Figure(Color.blue, 0, "Figure 1"); Figure figure3 = new Figure(Color.cyan, 1, "Figure 2"); // определение местоположения фигур в окне figure1.setBounds(10, 40, 120, 120); figure2.setBounds(60, 120, 160, 180); figure3.setBounds(90, 55, 250, 180); // добавление фигур в различные слои lp.add(figure1, JLayeredPane.POPUP_LAYER); lp.add(figure2, JLayeredPane.PALETTE_LAYER); lp.add(figure3, JLayeredPane.PALETTE_LAYER); // смена позиции одной из фигур lp.setPosition(figure3, 0); // определение размера и открытие окна setSize(280, 250); setVisible(true); } public static void main(String args) { JFrame.setDefaultLookAndFeelDecorated(true); new JLayeredPaneTest(); } }

В примере создается небольшое окно JFrame и в многослойную панель добавляется несколько компонентов Figure. Чтобы получить многослойную панель в любом контейнере Swing высшего уровня, достаточно вызвать метод getLayeredPane() .

Вспомогательный класс Figure наследует свойства базового класса JComponent и позволяет различными цветами рисовать фигуры двух типов (круги и прямоугольники). Параметры для прорисовки фигур задаются в конструкторе класса.

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

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

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

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

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

Обратиться к панели содержимого можно методом getContentPane() класса JFrame. С помощью метода add(Component component) можно добавить на нее любой элемент управления. Заменить ContentPane любой другой панелью типа JPanel можно методом setContentPane()

Пример добавления кнопки в панель содержимого:

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

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

Панель содержимого можно полностью заменить. Рассмотрим следующий Swing пример использования панели содержимого ContentPane .

Import javax.swing.*; public class ContentPaneReplace extends JFrame { private static final long serialVersionUID = 1L; public ContentPaneReplace() { super("Test ContentPane"); setDefaultCloseOperation(EXIT_ON_CLOSE); // Создание панели с двумя кнопками JPanel contents = new JPanel(); contents.add(new JButton("Семья")); contents.add(new JButton("Школа")); // Замена панели содержимого setContentPane(contents); // Определение размера окна setSize(200, 100); // Открытие окна setVisible(true); } public static void main(String args) { JFrame.setDefaultLookAndFeelDecorated(true); new ContentPaneAdd(); } }

В примере создается небольшое окно и панель с двумя кнопками, которая затем методом setContentPane() заменяет панель содержимого окна. Таким образом была использована замена вместо более простого добавления - вызова метода add(). Интерфейс окна представлен на следующем скриншоте.

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

Прозрачная панель JOptionPane

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

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

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

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

Пример использования прозрачной панели Swing JOptionPane:

// Использование прозрачной панели JOptionPane import java.awt.Dimension; import java.awt.Font; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.UIManager; public class JOptionPaneTest extends JFrame { private static final long serialVersionUID = 1L; public static final Font FONT = new Font("Verdana", Font.PLAIN, 11); public static void createGUI() { JFrame frame = new JFrame("Test JOptionPane"); 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) { Object options = { "Да", "Нет!" }; int rc = JOptionPane.showOptionDialog(event.getWindow(), "Закрыть окно?", "Подтверждение", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options); if (rc == 0) { event.getWindow().setVisible(false); System.exit(0); } } }); JLabel label = new JLabel("Использование прозрачной панели при закрытии окна"); frame.getContentPane().add(label); frame.setPreferredSize(new Dimension(350, 80)); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } public static void main(String args) { javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { UIManager.put("Button.font", FONT); UIManager.put("Label.font", FONT); JFrame.setDefaultLookAndFeelDecorated(true); JDialog.setDefaultLookAndFeelDecorated(true); createGUI(); } }); } }

Если методу setDefaultCloseOperation передать константу JFrame.EXIT_ON_CLOSE , то при закрытии окна приложение будет прекращать работу. В примере этому методу передается константа JFrame.DO_NOTHING_ON_CLOSE , чтобы при закрытии окна ничего не происходило. Выход из приложения в примере осуществляется из JFrame слушателя WindowListener в методе windowClosing . При закрытии окна вызывается метод windowClosing с параметром WindowEvent event, который в прозрачной панели Swing JOptionPane открывает диалоговое окно подтверждения.

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

Строка меню JMenuBar

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

Строка меню JMenuBar размещается в многослойной панели в специальном слое FRAME_CONTENT_LAYER и занимает небольшое пространство в верхней части окна. По размерам в длину строка меню равна размеру окна. Ширина строки меню зависит от содержащихся в ней компонентов.

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

Примеры Swing

Исходные коды примеров, рассмотренных в тексте страницы, можно скачать .

Давыдов Антон Валериевич
Студент ТГУ, Россия, г. Тольятти
Научный руководитель: Ерофеева Е.А.

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

Abstract Window Toolkit

Abstract Window Toolkit (сокращённо AWT) впервые была выпущена в 1995 году компанией Sun Microsystems. Это была первая попытка создать графический интерфейс для Java. AWT выступал в качестве прослойки, вызывающей методы из библиотек, написанных на С. А эти методы, в свою очередь, использовали графические компоненты операционной системы . С одной стороны, программа, построенная таким образом, внешне была похожа на все остальные программы в используемой операционной системе, но с другой, одна и та же программа может выглядеть совершенно по-разному на разных операционных системах, что осложняло разработку. К тому же, ради мультиплатформенности пришлось унифицировать интерфейсы вызовов компонентов, что привело к несколько урезанной функциональности. Набор компонентов также довольно скромный. Например, отсутствуют таблицы, а в кнопки нельзя поместить иконки. AWT старается автоматически освобождать использованные ресурсы. Это влияет на производительность и усложняет архитектуру. AWT прост для освоения, но написание чего-то сложного вызывает затруднения. Сейчас AWT используется в основном для аплетов. Oracle в данный момент поощряет переход разработчиков на Swing, как более безопасный.

Рис.1 – Образец программы, написанной с использованием AWT в среде Windows

После AWT, в 1998 году, Sun выпустила Swing. Он полностью написан на Java и для отрисовки использует 2D. В Swing гораздо больше разнообразных компонентов, чем в AWT. Сами компоненты стало гораздо проще создавать, наследуя их от существующих . Также была введена возможность использования различных стилей и скинов. Однако, скорость работы ранних версий Swing была довольно низкой, а ошибки в написании программы могли и вовсе привести к зависанию операционной системы.

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


Рис.2 – Образец программы, написанной с использованием Swing

Standard Widget Toolkit

SWT был выпущен компанией IBM во времена, когда Swing был ещё медленным, и в основном для продвижения среды программирования Eclipse. Как и AWT, SWT использует компоненты ОС, но для различных платформ используются различные интерфейсы взаимодействия . Таким образом для каждой операционной системы необходимо поставлять отдельную JAR-библиотеку. Это позволяет более полно использовать функции, соответствующие различным операционным системам. А недостающие компоненты были реализованы с помощью 2D. Тем не менее, SWT получилась более сложной для освоения, чем Swing. Кроме того, программист должен сам реализовывать освобождение ресурсов приложением.

Рис.3 – Образец программы, написанной с использованием Swing

JavaFX была выпущена в 2008 году компанией Oracle. Она позиционируется как платформа для создания насыщенного интернет-приложения. Для отрисовки используется графический конвейер, что значительно ускоряет работу приложения. Имеется большой набор встроенных компонентов. Также имеются отдельные компоненты для построения графиков. Реализована поддержка мультимедийного контента, анимации и даже множественное касание. Внешний вид компонентов настраивается при помощи CSS-стилей . Кроме того, в набор утилит JavaFX входит возможность сделать родной инсталлятор для самых популярных платформ: exe или msi для Windows, deb или rpm для Linux, dmg для Mac. На сайте Oracle имеется подробная документация и большое число готовых примеров.

Таким образом, описав основным особенности и недостатки вышеперечисленных графических пользовательских интерфейсов, мы можем решить, для каких задач они лучше подходят. Abstract Window Toolkit больше подойдёт для создания аплетов. Новичку можно порекомендовать Swing в виду того, что для него можно найти огромное количество документации в интернете, в том числе и на русском языке. Для создания насыщенных интернет-приложений отлично подойдёт JavaFX.

Список использованных источников

    Рыженко А. В. Объектно-ориентированное программирование: Учебно-методический комплекс по дисциплине для специальности 010501 – "Прикладная математика и информатика". – 2007.

    Хабибуллин И. Ш. Java 7 (4-е изд.). – БХВ-Петербург, 2012.

    Clarke J., Connors J., Bruno E. J. JavaFX: Developing Rich Internet Applications. – Pearson Education, 2009.

    Northover S., Wilson M. Swt: the standard widget toolkit, volume 1. – Addison Wesley Professional, 2004.