Отображение рабочего пространства
Хотя тот код, который, который делает программу запускаемой и как апплет, и как приложение, предоставляет ценные результаты, если его использовать везде, он сбивает с толку и впустую тратит бумагу. Вместо этого приведенное ниже отображение рабочего пространства будет использоваться для примеров Swing в оставшейся части книги:
//: com:bruceeckel:swing:Console.java
// Инструмент для запуска демонстрации Swing
// из консоли и доя апплета, и для JFrames.
package com.bruceeckel.swing; import javax.swing.*; import java.awt.event.*;
public class Console { // Создание строки заголовка из имени класса:
public static String title(Object o) { String t = o.getClass().toString(); // Удаление слова "class":
if(t.indexOf("class") != -1) t = t.substring(6); return t; } public static void setupClosing(JFrame frame) { // Решение JDK 1.2 - это
// анонимный внутренний класс:
frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); // улучшенное решение в JDK 1.3:
// frame.setDefaultCloseOperation(
// EXIT_ON_CLOSE);
} public static void run(JFrame frame, int width, int height) { setupClosing(frame); frame.setSize(width, height); frame.setVisible(true); } public static void run(JApplet applet, int width, int height) { JFrame frame = new JFrame(title(applet)); setupClosing(frame); frame.getContentPane().add(applet); frame.setSize(width, height); applet.init(); applet.start(); frame.setVisible(true); } public static void run(JPanel panel, int width, int height) { JFrame frame = new JFrame(title(panel)); setupClosing(frame); frame.getContentPane().add(panel); frame.setSize(width, height); frame.setVisible(true); } } ///:~
Этот инструмент вы можете использовать сами, так как он помещен в библиотеке com.bruceeckel.swing. Класс Console полностью состоит из статических методов. Первый используется для получения имени класса (используя RTTI) из любого объекта и удаления слова “class”, которое обычно присоединяется спереди методом getClass( ). Здесь используется метод indexOf( ) из String для определения присутствия слова “class” и substring( ) для получения новой строки без приставки “class” или заключающих пробелов. Это имя используется для метки окна, которая отображается в методах run( ).
setupClosing( ) используется для упрятывания кода, являющегося причиной выхода из программы при закрытии JFrame. По умолчанию при этом ничего не делается, так что если вы не вызовите setupClosing( ) или не напишите аналогичный код для своего JFrame, приложение не закроется. Причина упрятывания этого кода, а не помещения его прямо в последовательность метода run( ), частично в том, что это позволяет вам использовать этот метод сам по себе, когда вы захотите сделать что-то более сложное по сравнению с тем, что обеспечивает run( ). Однако это изолирует фактор изменения: Java 2 имеет два пути для закрытия некоторых видов окон. В JDK 1.2 решение состоит в создании нового класса WindowAdapter и реализации windowClosing( ), как показано выше (значение этого будет полностью объяснено позже в этой главе). Однако во время создания JDK 1.3 разработчики библиотеки заметили, что вам обычно нужно закрывать окна в любом случае, если вы создаете не апплет, и поэтому они добавили setDefaultCloseOperation( ) в JFrame и JDialog. С точки зрения написания кода, новый метод более приятный в использовании, но эта книга была написана в то время, когда еще не было реализации JDK 1.3. для Linux и других платформ, поэтому в интересах совместимости версий изменения были изолированы в методе setupClosing( ).
Методы run( ) перегружены для работы с JApplet, JPanel и JFrame. Обратите внимание, что только для JApplet вызывается init( ) и start( ).
Теперь любой апплет может быть запущен из консоли путем создания main( ), содержащей строку, подобную этой:
Console.run(new MyClass(), 500, 300);
в которой последние два аргумента показывают ширину и высоту. Здесь приведена Applet1c.java измененная для использования Console:
//: c13:Applet1d.java
// Console запускает апплет из командной строки.
// <applet code=Applet1d width=100 height=50>
// </applet>
import javax.swing.*; import java.awt.*; import com.bruceeckel.swing.*;
public class Applet1d extends JApplet { public void init() { getContentPane().add(new JLabel("Applet!")); } public static void main(String[] args) { Console.run(new Applet1d(), 100, 50); } } ///:~
Это позволяет уменьшить количество повторяющегося кода, одновременно обеспечивая великолепную гибкость в запуске примеров.