sonyps4.ru

Как сделать интерфейс для программы на java. Оконный пользовательский интерфейс в Java-программе

Графический интерфейс в 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

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

JFace — это доплнительный слой абстракции над графической библиотекой SWT, предоставляющий возможности для разработки графического интерфейса приложения на основе модели MVC(Model View Controller). Основные компоненты JFace включают:

  • Viewers — классы для инкапсуляции задач предоставления данных для отображения, их фильтрации, сортировки и т.п.
  • Actions and contributions — вводят семантику описания пользовательских действий и того, как они должны быть доступны пользователю.
  • Image and font registries — предоставляют классы для управления ресурсами, такими как изображения и шрифты.
  • Dialogs and wizards — фреймворк для построения сложного диалогового взаимодействия с пользователем.
  • Field assist — предоставляет возможности для реализации вспомогательной функциональности для полей, такой как отображение статуса поля или подсказки о содержимом.

В первой части будет рассмотрено создание простого окна с использованием JFace, добавление к нему меню, статусной строки и панели инструментов.

Настройка проекта

Для того, чтобы разрабатывать графические приложения с использованием JFace в Eclipse, необходимо подключить jar-файлы SWT и JFace.

  • В случае, если в Eclipse установлено PDE, то это можно сделать, указав в настройках проекта использовать библиотеку SWT, и поставить галочку для поддержки JFace.
  • Если же PDE не установлен, то необходимо подключить jar-файлы к проекту вручную. Найти их можно в директории plugins эклипса, называются они org.eclipse.swt_*.jar и org.eclipse.jface_*.jar

Создание окна

Окно приложения в JFace наследуется от класса ApplicationWindow, предоставляющего возможности для создания меню, панелей управления и строки статуса.

Простейший вариант создания окна приведен в следующем примере:

import org.eclipse.jface.window.ApplicationWindow; import org.eclipse.swt.widgets.Display; public class MainWindow extends ApplicationWindow { public static void main(String args) { MainWindow window = new MainWindow(); // Создаем наше окно window.setBlockOnOpen(true); // Устанавливаем флаг - ждать закрытия окна window.open(); // Открываем окно Display.getCurrent().dispose(); // Освобождаем ресурсы } public MainWindow() { super(null); // Вызываем конструктор родительского класса } }

Создание содержимого окна

Для того, чтобы создать какое-то содержимое окна, необходимо переопределить метод Control createContents(Composite parent) класса ApplicationWindow. Метод должен возвращать компонент, который будет являться содержимым окна.

В этом же методе можно установить и заголовок окна, вызвав метод setText(String text) шелла, доступного по вызову getShell()

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

Собственно, пример:

protected Control createContents(Composite parent) { getShell().setText("My window"); // Устанавливаем заголовок окна Label lbl = new Label(parent, SWT.NONE); // Создаем новый элемент, в нашем случае - просто метку lbl.setText("Window contents"); // Устанавливаем ей текст lbl.setBackground(new Color(Display.getCurrent(), 255, 255, 255)); // Устанавливаем белый цвет фона return lbl; }

Добавление статусной строки

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

Для того, чтобы отобразить текст в статусной строке необходимо вызвать метод setStatus(String status), аргументом которого и является та самая строка, которую необходимо отобразить.

Создание меню

Для создания строки меню в JFace необходимо, вызвать метод addMenuBar(), как и для создания строки статуса.
Но затем необходимо добавить пункты меню на панель. Осуществляется это следующим образом:

  • Раздел меню описывается классом MenuManager. В конструкторе ему может быть передана строка — имя раздела, где символ «&» означает, что следующий за ним символ будет ключом при навигации с помошью клавиши Alt. Добавляется раздел меню на панель с помощью конструкции getMenuBar().add(menu).
  • Пункт меню описывается классом Action. Сам класс является абстрактным, пункт меню должен быть унаследован от него и переопределять метод void run(), в котором размещается код, выполняемый при выборе пункта меню пользователем. На самом деле, метод можно и не переопределять, но тогда, зачем этот пункт меню нужен?=) Имя пункта может быть задано путем передачи в конструктор, или вызовом метода void setText(String text). После создания пункт меню добавляется в раздел вызовом метода add у объекта раздела меню. Например: menu.add(menuItem)
  • Подменю создаются очень просто: Необходимо в один раздел меню методом add добавить другой раздел. Вот и все.

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

private void createMenu() { addMenuBar(); // Добавляем панель меню MenuManager fileMenu = new MenuManager("&File"); // Создаем новое меню getMenuBarManager().add(fileMenu); // Добавляем меню на панель fileMenu.add(new Separator()); // Добавляем разделитель в меню fileMenu.add(new Action("&Hello") { // Создаем новое действие, указываем его текст @Override public void run() { // Код выполняемый при активации действия setStatus("Hello world!!"); // Мы просто отображаем новое значение в статусной строке } }); // И добавляем действие в качестве пункта меню }

Создание панели инструментов

Для того, чтобы создать панель инструментов в окне необходимо в конструкторе окна вызвать метод addToolBar(int style), в который передать стиль компонента панели.

Для доступа к созданной панели используется метод getToolBarManager(). Для добавления действия на панель используется метод add панели, куда передается действие.

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

private void createToolBar() { addToolBar(SWT.NONE); getToolBarManager().add(new Action("&Hello") { // Создаем новое действие, указываем его текст @Override public void run() { // Код выполняемый при активации действия setStatus("Hello world!!"); // Мы просто отображаем новое значение в статусной строке } }); }

Создание нескольких перемещаемых панелей инструментов

Вместо одной панели инструментов можно создать набор перемещаемых панелей (CoolBar). Для этого необходимо:

  1. Вместо метода addToolBar вызвать метод addCoolBar
  2. Для доступа к набору панелей используется метод getCoolBarManager()
  3. Создать панель инструментов, на которую можно будет добавлять действия. Для этого необходимо создать новый экземпляр класса ToolBarManager, который будет представлять панель и вызвать метод add у CoolBarManager, передав туда панель.
  4. На созданную панель можно добавлять действия

Пример кода, создающего две плавающие панели:

private void createCoolbar() { addCoolBar(SWT.NONE); ToolBarManager tm = new ToolBarManager(); getCoolBarManager().add(tm); tm.add(helloAction); ToolBarManager tm2 = new ToolBarManager(); getCoolBarManager().add(tm2); tm2.add(helloAction); tm2.add(helloAction); }

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

Возможные проблемы

Здесь будут описаны некоторые проблемы, с которыми можно столкнуться:

  • При добавлении пунктов меню после запуска приложения они не появляются — чтобы изменения меню после создания окна отобразились на нем, необходимо вызвать метод getMenuBarManager().update(true) — указать обновить панель меню.

Ссылки

Дополнительная информация по JFace может быть найдена по следующим ссылкам:

  • Русскоязычная вводная статья на ibm.com
  • Цикл англоязычных статей на ibm.com
  • Описание API Eclipse — среди прочего там есть и пакеты, относящиеся к SWT и JFace

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

Представьте себе будущее, где автомобилями управляют компьютеры без участия человека. Производители автомобилей пишут программное обеспечение (на Java, конечно 🙂), которое управляет машиной — остановиться, поехать, повернуть и т.д. Другие разработчики делают системы, которые принимают данные GPS (Global Positioning System) и используют эти данные для управления автомобилем. Производители автомобилей публикуют интерфейс-стандарт, который описывает методы для управления машиной. Таким образом сторонние разработчики могут знать какие методы вызывать, чтобы заставить автомобиль двигаться, а производители автомобилей могут изменять внутреннюю реализацию своего продукта в любое время. Ни одна из групп разработчиков не знает как написаны их программы.

Интерфейсы Java

Интерфейсы в Java во многом напоминают классы, но могут содержать только константы, сигнатуры методов и . В интерфейсах нет описания методов. Нельзя создать объект типа интерфейса (но можно использовать в качестве типа — интерфейсные ссылки, об этом позже) — интерфейсы могут только реализовываться некоторым классом или наследоваться другим интерфейсом. Объявление интерфейса очень похоже на объявление класса:

Public interface OperateCar { // константы, если есть // enum перечисление направлений RIGHT, LEFT // сигнатуры методов int turn(Direction direction, double radius, double startSpeed, double endSpeed); int changeLanes(Direction direction, double startSpeed, double endSpeed); int signalTurn(Direction direction, boolean signalOn); int getRadarFront(double distanceToCar, double speedOfCar); int getRadarRear(double distanceToCar, double speedOfCar); }

Сигнатуры методов объявляются без скобок и заканчиваются точкой с запятой. Для использования интерфейса вы должны написать класс, который будет реализовывать ваш интерфейс. Класс который реализует интерфейс, должен описывать все методы, объявленные в интерфейсе. Например:

Public class OperateBMW760i implements OperateCar { // здесь методы интерфейса OperateCar с описанием // например: int signalTurn(Direction direction, boolean signalOn) { // поворот RIGHT или LEFT поворотник on или off } }

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

Интерфейсы в качестве API

Пример с автомобилями показывает как интерфейсы могут использоваться в качестве API (Application Programming Interface ) или интерфейса программирования приложений. Использование API — обычная практика при разработке коммерческого ПО. Обычно компании-разработчики продают программное обеспечение, содержащее набор методов, которые другие компании хотят использовать в своих продуктах.

Интерфейсы и множественное наследование

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

Объявление интерфейса

Объявление интерфейса содержит ключевое слово interface , имя интерфейса, список родительских интерфейсов через запятую (если есть) и тело интерфейса. Например:

Public interface GroupedInterface extends Interface1, Interface2, Interface3 { // число e double E = 2.718282; // сигнатуры методов void doSomething (int i, double x); int doSomethingElse(String s); }

Модификатор доступа public означает что интерфейс может быть использован любым классом в любом пакете. Если не определить интерфейс как публичный, он будет доступен только в рамках своего пакета. Интерфейс может наследовать другие интерфейсы, как классы могут наследовать другой класс. В отличие от классов, интерфейсы могут наследовать любое количество других интерфейсов.

Реализация интерфейса

Для объявления класса, реализующего интерфейс, вы должны использовать ключевое слово implements после которого перечисляются интерфейсы.
Класс может реализовывать много интерфейсов. Объявление реализуемых интерфейсов идет после объявления наследуемого (extends) класса (если есть).

Пример простого интерфейса

Рассмотрим интерфейс, который определяет метод для сравнения объектов.

Public interface Relatable { // this (объект, который вызывает isLargerThan) // объект-параметр должен быть того же класса // возвращет 1, 0, -1 // если объект больше, равен или // меньше чем other public int isLargerThan(Relatable other); }

Чтобы иметь возможность сравнивать объекты мы должны реализовать интерфейс Relatable . Любой класс может реализовать интерфейс Relatable , если есть способ сравнить объекты. Для строк сравнивать можно количество символов, для книг — количество страниц, для студентов — вес и т.д. Для плоских геометрических фигур отличной характеристикой будет площадь, для трехмерных — объем. Все эти классы могут реализовать метод isLargerThan() . Если вы знаете, что класс реализует интерфейс Relatable , то вы смело можете сравнивать объекты этого класса.

Реализация интерфейса Relatable

Напишем класс Rectangle , реализующий интерфейс Relatable .

Public class RectanglePlus implements Relatable { public int width = 0; public int height = 0; public Point origin; // четыре конструктора public RectanglePlus() { origin = new Point(0, 0); } public RectanglePlus(Point p) { origin = p; } public RectanglePlus(int w, int h) { origin = new Point(0, 0); width = w; height = h; } public RectanglePlus(Point p, int w, int h) { origin = p; width = w; height = h; } // метод для передвижения прямоугольника public void move(int x, int y) { origin.x = x; origin.y = y; } // вычисление площади public int getArea() { return width * height; } // метод для реализации интерфейса Relatable public int isLargerThan(Relatable other) { RectanglePlus otherRect = (RectanglePlus)other; if (this.getArea() < otherRect.getArea()) return -1; else if (this.getArea() > otherRect.getArea()) return 1; else return 0; } }

Так как класс RectanglePlus реализует Relatable , размеры любых двух объектов типа RectanglePlus можно сравнивать.

Метод isLargerThan в качестве аргумента принимает объекты типа Relatable . При реализации метода в примере выше мы используем приведение типов, потому что компилятор не поймет что, other — объект типа RectanglePlus и вызов метода other.getArea() без приведения типов приведет к ошибке.

Использование интерфейса в качестве типа

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

Рассмотрим пример — метод, который ищет больший объект из двух любых объектов, класс которых реализует интерфейс Relatable:

Public Object findLargest(Object object1, Object object2) { Relatable obj1 = (Relatable)object1; Relatable obj2 = (Relatable)object2; if ((obj1).isLargerThan(obj2) > 0) return object1; else return object2; }

Приведением object1 к типу Relatable , мы делаем возможным вызов метода isLargerThan .

Так же для любого класса, реализующего интерфес Relatable, можно реализвать методы:

Public Object findSmallest(Object object1, Object object2) { Relatable obj1 = (Relatable)object1; Relatable obj2 = (Relatable)object2; if ((obj1).isLargerThan(obj2) < 0) return object1; else return object2; } public boolean isEqual(Object object1, Object object2) { Relatable obj1 = (Relatable)object1; Relatable obj2 = (Relatable)object2; if ((obj1).isLargerThan(obj2) == 0) return true; else return false; }

Переопределение интерфейсов

Допустим, вы написали интерфейс DoIt:

Public interface DoIt { void doSomething(int i, double x); int doSomethingElse(String s); }

Предположим, позже, вы захотели добавить в него третий метод:

Public interface DoIt { void doSomething(int i, double x); int doSomethingElse(String s); boolean didItWork(int i, double x, String s); }

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

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

Public interface DoItPlus extends DoIt { boolean didItWork(int i, double x, String s); }

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

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

import java.awt.*;

import javax.swing.*;

public class MoneyForNothing extends JFrame {

// Конструктор

public MoneyForNothing () {

setTitle ("Добро пожаловать в Money for Nothing");

setSize (new Dimension (600, 400));

setDefaultCloseOperation (EXIT_ON_CLOSE);

setVisible (true);

public static void main (String args) {

MoneyForNothing mfn = new MoneyForNothing ();

А вот этот же код в окне редактирования FAR-а:

Кстати, рекомендуем сразу набирать исходные коды программ в кодировке CP1251 (или в просторечии, в кодировке Windows): переключение кодировок осуществляется клавишей F8, а текущая кодировка высвечивается в строке состояния над областью редактирования.

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


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

Сначала решим вторую задачу – центровка окна. Тут мы рекомендуем остановиться и подумать – как бы вы это сделали?

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

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

Dimension sSize = Toolkit.getDefaultToolkit ().getScreenSize (),

fSize = getSize ();

if (fSize.height > sSize.height) {fSize.height = sSize.height;}

if (fSize.width > sSize.width) {fSize.width = sSize.width;}

setLocation ((sSize.width - fSize.width)/2,

(sSize.height - fSize.height)/2);

непосредственно за строкой setSize (new Dimension (600, 400)); в конструкторе. Внесите необходимые изменения в исходный код, откомпилируйте программу и запустите на исполнение; окно должно появиться в центре экрана монитора.

Теперь несколько слов о внешнем виде окна. Его странный вид объясняется тем, что разработчики Java стремились добиться того, чтобы вне зависимости от аппаратной платформы и программной «начинки», все графические элементы (окна, кнопки, списки и проч.) имели единую отрисовку и единую цветовую гамму. Для этого они разработали специальный стиль, который назвали «METAL». Если разработчик не предпримет специальных усилий, то элементы графического интерфейса в его программах будут выглядеть именно в этом стиле, без учета особенностей конкретных компьютеров и их программного обеспечения. В отдельных случаях в этом есть смысл, но все-таки, согласитесь, что гораздо лучше, если программа, запущенная на Windows будет похожа на windows-программу, а запущенная на LINUX будет похожа на linux-программу. Добиться этого легко. Все, что нужно - включить в точку входа, перед созданием экземпляра класса следующий код:

try {UIManager.setLookAndFeel

(UIManager.getSystemLookAndFeelClassName ());

catch (Exception lfe) {}

Так мы и поступим. Теперь, после компиляции обновленной версии нашей программы и запуска ее на исполнение, графическое окно будет выглядеть гораздо «пристойнее»:


В зависимости от настройки свойств экрана вашего монитора отображение окна будет отличаться; мы используем классическую тему Windows XP. У вас это же окно может выглядеть, например, так:

Убедитесь, что все работает как ожидалось: окно выводится в центре экрана и его внешний вид соответствует ожидаемому.

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

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

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

(подсказка: ищите информацию по ключевым словам javax и JFrame). Так что, засучите рукава и удачи!

Замечание

Может случиться, что сформированное окно будет полностью или частично невидимо (из-за того, что вы неправильно рассчитали координаты его вывода на экран). Кнопки управления окна могут также оказаться недоступными. Как же прервать работу приложения не снимая задачу в «Диспетчере задач» или не перезагружая компьютер?

Поскольку мы запускаем программы на исполнение из FAR-а, то прерывание исполнения программы на Java достигается нажатием комбинации клавиш Control-C (здесь «C» - латинская буква, не путайте ее со сходной по начертанию буквой кириллической).

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


Чтобы размещать кнопки, текстовые надписи и другие компоненты в окне программы, вам следует понять, как работает JPanel . Это что-то вроде контейнера для компонентов, который занимает прямоугольную область экрана и показывает компоненты, выровненные по какому-то простому принципу. Как именно выровнены компоненты, зависит от типа схемы размещения, которую вы установили для панели. Для простых задач программирования вам следует знать, как минимум, BorderLayout , который располагает компоненты по краям и один большой компонент ставит в середину, затем FlowLayout , который обычно располагает компоненты в ряд по горизонтали, и, наконец, GridLayout , который располагает компоненты в произвольной таблице n * m. Есть другие типы, но они слишком сложны для новичков. Ключевая идея в том, что "компонентой" может быть не только кнопка или флажок, но и другая JPanel. Вы можете получить достаточно сложный пользовательский интерфейс, просто расположив панели одна на другой и выбрав для них планировку.


Если у вас есть экземпляр объекта JPanel, вызовите метод .setLayout , чтобы установить тип планировки, и затем метод.add, чтобы добавить на панель компоненты. В случае BorderLayout в качестве второго параметра вам нужно будет передать положение. Например, чтобы расположить кнопку в верхней части, вызовите myPanel.add(myButton, BorderLayout.North) .


Контейнер самого высокого уровня, который появляется на экране, представляющем приложение Java, является экземпляром JFrame , а не JPanel . Чтобы добавить вашу основную панель в экземпляр JFrame просто вызовите myJFrame.getContentPane().add(myJPanel, BorderLayout.Center) .


Чтобы заставить ваше приложение делать что-то большее, чем просто появляться, вам нужно будет понять интерфейс ActionListener . У любого неабстрактного ActionListener есть только один метод actionPerformed, который вызывается, когда пользователь выполняет "действие" над компонентой, в которой зарегистрирован слушатель (например, действие над кнопкой - это, очевидно, ее нажатие). Чтобы зарегистрировать слушателя действий для кнопки или любого другого компонента, вызовите метод .addActionListener. .

Шаги

Создание общего фрейма

    Создайте класс, который расширяет класс JFrame . Этот класс будет содержать все ваши компоненты графического интерфейса (GUI), такие как кнопки и текстовые поля.

    Продумайте общий внешний вид вашего первого приложения. Неплохо было бы начать с центральной панели типа BorderLayout с другой панелью в нижней ее части (BorderLayout.South ). Эта вторая панель будет иметь тип FlowLayout и содержать несколько кнопок, флажков и других контрольных элементов. И наконец, расположите большой компонент JTextArea посередине центрального компонента. Чтобы взаимодействовать с пользователем посредством текста, вы сможете использовать методы getText() и setText() .

    Напишите конструктор для вашего класса. Этот конструктор должен создать все панели и компоненты, которые вы запланировали, расположить их правильно и добавить последнюю панель, которая "прикрепляет все" к вашему фрейму (myFrame.getContentPane().add(myLargePanel, BorderLayout.Center).

    Напишите метод main, который будет точкой входа программы. В этом методе создайте экземпляр фрейма, установите его начальные размер и положение (используйте.setSize(x,y) и .setLocation(width, height) ), и заставьте его появиться на экране, вызвав .setVisible(true).

    Программирование ответов на действия пользователя

    1. Сделайте ваш фрейм реализующим интерфейс ActionListener . Это позволит вашему классу "слушать" действия компонентов.

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

      Переопределите абстрактный метод класса ActionListener, который называется actionPerformed(ActionEvent event). В этом методе вам следует добавить условные выражения "if", чтобы проверить, откуда пришло событие. В этом условном операторе "if" должно быть условие вроде такого: "if (event.getSource() == button1 )". Здесь проверяется, откуда пришло событие, и пришло ли оно от кнопки. Внутри выражения "if" выполняйте любые действия, которые вам необходимы при нажатии на кнопку.

      У JTextArea есть метод .setText("myText") , который является неплохим способом запрограммировать какой-то видимый ответ на ваше действие.

    • Совсем не намного сложнее реализовать интерфейс MouseListener и использовать .addMouseListener , чтобы зарегистрировать его для любой компоненты.
    • Если вам нужно запросить от пользователя ввести какую-то строку, вызовите статический метод JOptionPane.showInputDialog(this, "My message"). первым параметром должен быть фрейм вашего приложения или какая-нибудь панель (поле для ввода появится посередине родительского элемента). Метод возвращает значение, которое пользователь ввел в диалоговом окне.
    • Вполне возможно разместить все компоненты на одной панели, использующей тип GridBagLayout, но этим классом труднее управлять.
    • Если вы хотите нарисовать собственные графические объекты (например, шахматную доску), почитайте о компоненте Canvas . Он может быть размещен в вашем приложении, как любой другой компонент, но вам нужно будет написать метод.paint, который полностью отвечает за его отрисовку.
    • Во многих реальных приложениях наиболее полезным компонентом Swing является JTable . После изучения основ, продолжайте работать с ним.

    Предупреждения

    • Некоторые средства разработки предлагают возможность составить графический интерфейс Swing способом, "удобным для пользователя". Однако, зачастую они не могут должным образом сделать панель с продвинутыми возможностями. Эти возможности включают деревья, таблицы, списки и комбинированные списки, которые меняют свое содержимое по мере работы программы, а также компоненты с моделями данных пользователя и т.д. Код, написанный при таком "дружеском для пользователя" способе, станет настоящим кошмаром, если вам потом потребуется дописать его вручную. Поэтому слишком не увлекайтесь подобными "дизайнерами графического интерфейса, дружественными для пользователя", потому что это ограничит ваши возможности из-за их ограниченных возможностей.
    • Swing - это однопоточное приложение. Если обработка действия у вас занимает слишком много времени, оно "зависнет", пока не произойдет выход из метода .actionPerformed . Изучайте и используйте многопоточность java, чтобы Swing оставался "живым", пока работает какой-то трудоемкий процесс.
    • Большинство методов компонентов Swing можно безопасно вызвать только из потока диспетчеризации событий (метод .actionPerformed и другие похожие методы слушателя). Если вам нужно вызвать их из какого-то другого потока (например, чтобы обновить индикатор прогресса или показать результаты какого-то длительного процесса), почитайте о SwingUtils.invokeLater .

    Источники

    Исходный код

    Import java.awt.BorderLayout ; import java.awt.FlowLayout ; import java.awt.event.ActionEvent ; import java.awt.event.ActionListener ; import javax.swing.JButton ; import javax.swing.JCheckBox ; import javax.swing.JFrame ; import javax.swing.JPanel ; import javax.swing.JTextArea ; /** * Очень простое приложение java swing. * Содержит кнопку и флажок. Отвечает * на изменения этих контрольных элементов * изменением текста в главном текстовом поле. * * @author audriusa */ public class WikiHow extends JFrame implements ActionListener { /** * Кнопка. */ JButton myButton = new JButton ("Button" ) ; /** * Флажок. */ JCheckBox myCheckBox = new JCheckBox ("Check" ) ; /** * Текстовое поле. */ JTextArea myText = new JTextArea ("My text" ) ; /** * Нижняя панель, содержащая кнопку. */ JPanel bottomPanel = new JPanel () ; /** * Родительская панель, содержащая все. */ JPanel holdAll = new JPanel () ; /** * Конструктор. */ public WikiHow() { bottomPanel.setLayout (new FlowLayout () ) ; bottomPanel.add (myCheckBox) ; bottomPanel.add (myButton) ; holdAll.setLayout (new BorderLayout () ) ; holdAll.add (bottomPanel, BorderLayout .SOUTH ) ; holdAll.add (myText, BorderLayout .CENTER ) ; getContentPane() .add (holdAll, BorderLayout .CENTER ) ; myButton.addActionListener (this ) ; myCheckBox.addActionListener (this ) ; setDefaultCloseOperation(DISPOSE_ON_CLOSE) ; } /** * Программа * @param args Параметры старта программы, не используются. */ public static void main(String args) { WikiHow myApplication = new WikiHow() ; // Указываем, где оно должно появиться: myApplication.setLocation (10 , 10 ) ; myApplication.setSize (300 , 300 ) ; // Показать! myApplication.setVisible (true ) ; } /** * Любой неабстрактный класс, который реализует ActionListener * должен иметь этот метод. * * @param e Событие. */ public void actionPerformed(ActionEvent e) { if (e.getSource () == myButton) myText.setText ("A button click" ) ; else if (e.getSource () == myCheckBox) myText.setText ("The checkbox state changed to " + myCheckBox.isSelected () ) ; else myText.setText ("E ...?" ) ; } }



Загрузка...