Введение в программирование Java GUI

ОГЛАВЛЕНИЕ

Введение

Данная статья рассчитана на людей, совсем не имеющих или имеющих мало опыта в программировании Java GUI. По сути, эта статья делает упор на иерархической структуре, основывающейся на кадре и идущей в панель содержимого. В центре внимания находится виджет кнопки (управляющий элемент в .NET) и соответствующий метод, применяемый для обработки этого слушателя события. Любой программист .NET найдет эти концепции крайне простыми, не считая того, что стиль программирования иногда требует больше текста, и используются иные понятия. Этот код легко компилируется в командной строке после установки среды выполнения Java от Sun на www.java.com и J2EE SDK 5.0 от Sun – надо перейти в каталог по умолчанию: c:\Sun\SDK\JDK\bin>, набрать con > somecode.java Ctrl-Z и затем скомпилировать. Чтобы установить путь, задайте PATH=%PATH%;.;C:\Sun\SDK\JDK\bin.

Программирование Java GUI требует двух пакетов: оригинальный абстрактный набор для windows (AWT) и более новый пакет разработчика Swing. Компоненты Swing имеют префикс J, чтобы отличать их от оригинальных пакетов AWT (например, JFrame вместо Frame). Чтобы добавить компоненты и методы Swing в проект, надо импортировать пакеты java.awt.*, java.awt.event.* и javax.swing.*. Отображаемые кадры являются контейнерами верхнего уровня, такими как JFrame, JWindows, JDialog и JApplet, взаимодействующими с диспетчером окон операционной системы. Не отображающие содержимое панели являются промежуточными контейнерами, такими как JPanel, JOptionsPane,JScrollPane и JSplitPane.

Поэтому контейнеры являются виджетами или управляющими элементами GUI, используемыми для хранения и группировки других виджетов, таких как поля текста, флажки, радиокнопки, и др. В .NET главный интерфейс пользователя, именуемый форма Windows, содержит управляющие элементы, перетаскиваемые и оставляемые на поверхности управляющего элемента. Каждый GUI начинается с окна, отображающего элементы. В Swing есть три типа окон: апплет, диалоговое окно и кадр. Они взаимодействуют с диспетчером окон. В Swing объект frame называется JFrame. JFrame считается самым верхним контейнером. Он также называется отображаемым кадром. Не отображающие содержимое панели являются промежуточными контейнерами, такими как JPanel, JScrollPane, JLayeredPane, JSplitPane и JTabbedPane, формирующие структуру макета при использовании нескольких управляющих элементов. В панель содержимого помещаются текстовые поля и иные виджеты, поэтому чтобы добавить и отобразить управляющие элементы GUI, надо указать, что они добавляются в панель содержимого. Панель содержимого расположена вверху иерархии включения, в которой эта древовидная иерархия имеет контейнер верхнего уровня (в данном случае JFrame). Спускаясь по дереву, можно найти другие контейнеры верхнего уровня, такие как JPanel, хранящие компоненты. Ниже приведен код, создающий простой frame, на котором основываемся:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;  //обратите внимание на javax
public class Frame1 extends JFrame
{
  JPanel pane = new JPanel();
  Frame1() // метод конструктора кадра
  {
    super("My Simple Frame"); setBounds(100,100,300,100);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Container con = this.getContentPane(); // наследует главный кадр
    con.add(pane); // добавляем панель в кадр
    // здесь настраиваем панель
    // pane.add(someWidget);
    setVisible(true); // отображаем этот кадр
  }
  public static void main(String args[]) {new Frame1();}
}

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

import java.util.*;
public class Sys {
public static void main(String[]  args) {
System.out.println
    (“This is a string passed to the print line method of the System class”);
 }
}
 
c:\Sun\SDK\jdk\bin>javac.exe Sys.java     // компилятор javac.exe
                    // компилирует исходный код
 
c:\Sun\SDK\jdk\bin>java.exe Sys     // java.exe интерпретирует файл байт-кода
                // (в том же каталоге, где находится файл класса).

Это строка, переданная методу печатной строки класса Система.

Ниже приведен код, показывающий GUI(графический интерфейс пользователя) с кнопкой.

Однако кнопка ничего не делает при нажатии:

import java.awt.*; 
import java.awt.event.*;
import javax.swing.*;
public class Frame2 extends JFrame
{
  JPanel pane = new JPanel();
  JButton pressme = new JButton("Press Me");
  Frame2()        // конструктор кадра
  {
    super("JPrompt Demo"); setBounds(100,100,300,200);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Container con = this.getContentPane(); // наследуем главный кадр
    con.add(pane);    // контейнеры JPanel по умолчанию добавляются в FlowLayout
    pressme.setMnemonic('P'); // связать горячую клавишу с кнопкой
    pane.add(pressme); pressme.requestFocus();
    setVisible(true); // сделать кадр видимым
  }
  public static void main(String args[]) {new Frame2();}
}
 

C:\...\bin>Javac.exe Frame2.java
 

C:\...\bin>Java.exe Frame2

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

import java.awt.*; 
import java.awt.event.*;
import javax.swing.*;
public class Frame3 extends JFrame implements ActionListener
{
  JLabel answer = new JLabel("");
  JPanel pane = new JPanel(); // создаем объект панели
  JButton pressme = new JButton("Press Me");
  Frame3()   // конструктор
  {
    super("Event Handler Demo"); setBounds(100,100,300,200);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Container con = this.getContentPane(); // наследует главный кадр
    con.add(pane); pressme.setMnemonic('P'); // привязываем горячую клавишу
    pressme.addActionListener(this);   // регистрируем слушатель кнопки
    pane.add(answer); pane.add(pressme); pressme.requestFocus();
    setVisible(true); // делаем кадр видимым
  }
  // здесь находится базовый обработчик события
  public void actionPerformed(ActionEvent event)
  {
    Object source = event.getSource();
    if (source == pressme)
    {
      answer.setText("Button pressed!");
      JOptionPane.showMessageDialog(null,"I hear you!","Message Dialog",
      JOptionPane.PLAIN_MESSAGE); setVisible(true);  // показываем что-то
    }
  }
  public static void main(String args[]) {new Frame3();}
}
 

Первый шаг при добавлении базового обработчика события нажатия кнопки в вышеуказанный пример - импортировать awt.event.*, содержащий все классы событий. Затем добавляем фразу implements(реализует) ActionListener в заголовок класса, чтобы использовать интерфейс. Регистрируем слушателей события для каждого виджета кнопки с помощью метода addActionListener(this). Служебное слово this(этот) указывает, что требуемый (согласно implements ActionListener) вызываемый метод обработчика actionPerformed() будет добавлен в текущий класс. Например, рассмотрим следующий более яркий пример:

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

public class ButtonDemo{

    public JPanel createContentPane (){

        // Создаем основную JPanel, чтобы все поместить на нее.
        JPanel totalGUI = new JPanel();
        totalGUI.setLayout(null);

        // Создание панели, содержащей метки названий
        JPanel titlePanel = new JPanel();
        titlePanel.setLayout(null);
        titlePanel.setLocation(10, 0);
        titlePanel.setSize(250, 30);
        totalGUI.add(titlePanel);

        JLabel redLabel = new JLabel("Red Team");
        redLabel.setLocation(0, 0);
        redLabel.setSize(100, 30);
        redLabel.setHorizontalAlignment(0);
        redLabel.setForeground(Color.red);
        titlePanel.add(redLabel);

        JLabel blueLabel = new JLabel("Blue Team");
        blueLabel.setLocation(120, 0);
        blueLabel.setSize(100, 30);
        blueLabel.setHorizontalAlignment(0);
        blueLabel.setForeground(Color.blue);
        titlePanel.add(blueLabel);

        // Создание панели, содержащей метки числа очков.
        JPanel scorePanel = new JPanel();
        scorePanel.setLayout(null);
        scorePanel.setLocation(10, 40);
        scorePanel.setSize(250, 30);
        totalGUI.add(scorePanel);

        JLabel redScore = new JLabel("0");
        redScore.setLocation(0, 0);
        redScore.setSize(100, 30);
        redScore.setHorizontalAlignment(0);
        scorePanel.add(redScore);

        JLabel blueScore = new JLabel("0");
        blueScore.setLocation(120, 0);
        blueScore.setSize(100, 30);
        blueScore.setHorizontalAlignment(0);
        scorePanel.add(blueScore);

        // Создание метки, содержащей все JButtons.
        JPanel buttonPanel = new JPanel();
        buttonPanel.setLayout(null);
        buttonPanel.setLocation(10, 80);
        buttonPanel.setSize(250, 70);
        totalGUI.add(buttonPanel);

        // Создаем кнопку и манипулируем ей с помощью синтаксиса,
        // использованного раньше.
        JButton redButton = new JButton("Red Score!");
        redButton.setLocation(0, 0);
        redButton.setSize(100, 30);
        buttonPanel.add(redButton);

        JButton blueButton = new JButton("Blue Score!");
        blueButton.setLocation(120, 0);
        blueButton.setSize(100, 30);
        buttonPanel.add(blueButton);

        JButton resetButton = new JButton("Reset Score");
        resetButton.setLocation(0, 40);
        resetButton.setSize(220, 30);
        buttonPanel.add(resetButton);
       
        totalGUI.setOpaque(true);
        return totalGUI;
    }

    private static void createAndShowGUI() {

        JFrame.setDefaultLookAndFeelDecorated(true);
        JFrame frame = new JFrame("[=] JButton Scores! [=]");

        //Создаем и устанавливаем панель содержимого.
        ButtonExample demo = new ButtonExample();
        frame.setContentPane(demo.createContentPane());

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(250, 190);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        //Заносим в график задание для потока управления событиями:
        //создание и отображение графического интерфейса пользователя этого приложения.
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}