Spec-Zone .ru
спецификации, руководства, описания, API
След: Создание GUI С JFC/Swing
Урок: Использование Других Функций Swing
Как Украсить Компоненты Классом JLayer
Домашняя страница > Создание GUI С JFC/Swing > Использование Других Функций Swing

Как Украсить Компоненты Классом JLayer

JLayer class является гибким и мощным декоратором для компонентов Swing. Это позволяет Вам привлечь компоненты и ответить на компонентные события, не изменяя базовый компонент непосредственно.

JLayer class в Java SE 7 подобен в духе проекту проекта JxLayer в java.net. JLayer class был первоначально основан на JXLayer проект, но его API развился отдельно.

Этот документ описывает примеры, которые показывают питание JLayer class. Полный исходный код доступен.

Для краткого введения в материал на этой странице смотрите следующий видеофильм.

Поддерживающий JavaScript веб-браузер и Интернет-соединение требуются для видео. Если невозможно посмотреть видео, попытайтесь просмотреть его в YouTube.

Используя JLayer Класс

javax.swing.JLayer class является половиной команды. Другая половина javax.swing.plaf.LayerUI class. Предположите, что Вы хотите сделать некоторый пользовательский рисунок на a JButton объект (украшают JButton объект). Компонент, который Вы хотите украсить, является целью.

Например, чтобы добавить экземпляр a JPanel разделите на подклассы к a JFrame объект, Вы сделали бы что-то подобное этому:

JFrame f = new JFrame();

JPanel panel = createPanel();

f.add (panel);

Украсить JPanel возразите, сделайте что-то подобное этому вместо этого:

JFrame f = new JFrame();

JPanel panel = createPanel();
LayerUI<JPanel> layerUI = new MyLayerUISubclass();
JLayer<JPanel> jlayer = new JLayer<JPanel>(panel, layerUI);

f.add (jlayer);

Используйте обобщения, чтобы гарантировать что JPanel возразите и LayerUI объект для совместимых типов. В предыдущем примере, оба JLayer возразите и LayerUI объект используется с JPanel class.

JLayer class обычно generified с точным типом его компонента представления, в то время как LayerUI class разрабатывается, чтобы использоваться с JLayer классы его универсального параметра или любой из его предков.

Например, a LayerUI<JComponent> объект может использоваться с a JLayer<AbstractButton> объект.

A LayerUI объект ответственен за пользовательское художественное оформление и обработку событий для a JLayer объект. Когда Вы создаете экземпляр a LayerUI подкласс, Ваше пользовательское поведение может быть применимым к каждому JLayer объект с соответствующим универсальным типом. Именно поэтому JLayer class final; все пользовательское поведение инкапсулируется в Вашем LayerUI подкласс, таким образом нет никакой потребности сделать a JLayer подкласс.

Используя LayerUI Класс

LayerUI class наследовал большую часть своего поведения от ComponentUI class. Вот обычно переопределенные методы:

Привлечение Компонентов

Использовать JLayer class, Вы нуждаетесь в пользе LayerUI подкласс. Самые простые виды LayerUI классы изменяются, как оттягиваются компоненты. Вот один, например, который красит прозрачный цветной градиент на компоненте.

class WallpaperLayerUI extends LayerUI<JComponent> {
  @Override
  public void paint(Graphics g, JComponent c) {
    super.paint(g, c);

    Graphics2D g2 = (Graphics2D) g.create();

    int w = c.getWidth();
    int h = c.getHeight();
    g2.setComposite(AlphaComposite.getInstance(
            AlphaComposite.SRC_OVER, .5f));
    g2.setPaint(new GradientPaint(0, 0, Color.yellow, 0, h, Color.red));
    g2.fillRect(0, 0, w, h);

    g2.dispose();
  }
}

paint() метод - то, где пользовательский рисунок имеет место. Звонок super.paint() метод тянет содержание JPanel объект. После установки 50%-ого прозрачного составного объекта оттягивается цветной градиент.

После LayerUI подкласс определяется, используя его прост. Вот некоторый исходный код, который использует WallpaperLayerUI class:

import java.awt.*;
import javax.swing.*;
import javax.swing.plaf.LayerUI;

public class Wallpaper {
  public static void main(String[] args) {
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        createUI();
      }
    });
  }

  public static void createUI() {
    JFrame f = new JFrame("Wallpaper");
    
    JPanel panel = createPanel();
    LayerUI<JComponent> layerUI = new WallpaperLayerUI();
    JLayer<JComponent> jlayer = new JLayer<JComponent>(panel, layerUI);
    
    f.add (jlayer);
    
    f.setSize(300, 200);
    f.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
    f.setLocationRelativeTo (null);
    f.setVisible (true);
  }

  private static JPanel createPanel() {
    JPanel p = new JPanel();

    ButtonGroup entreeGroup = new ButtonGroup();
    JRadioButton radioButton;
    p.add(radioButton = new JRadioButton("Beef", true));
    entreeGroup.add(radioButton);
    p.add(radioButton = new JRadioButton("Chicken"));
    entreeGroup.add(radioButton);
    p.add(radioButton = new JRadioButton("Vegetable"));
    entreeGroup.add(radioButton);

    p.add(new JCheckBox("Ketchup"));
    p.add(new JCheckBox("Mustard"));
    p.add(new JCheckBox("Pickles"));

    p.add(new JLabel("Special requests:"));
    p.add(new JTextField(20));

    JButton orderButton = new JButton("Place Order");
    p.add(orderButton);

    return p;
  }
}

Вот результат:

Панель с джазовым художественным оформлением

Исходный код:

Wallpaper NetBeans Project
Wallpaper.java

Выполненный с Сетью Java Запустите:

Запускает пример

LayerUI class' paint() метод дает Вам полный контроль над тем, как оттягивается компонент. Вот другой LayerUI подкласс, который показывает, как все содержание панели может быть изменено, используя Java 2-D обработка изображений:

class BlurLayerUI extends LayerUI<JComponent> {
  private BufferedImage mOffscreenImage;
  private BufferedImageOp mOperation;

  public BlurLayerUI() {
    float ninth = 1.0f / 9.0f;
    float[] blurKernel = {
      ninth, ninth, ninth,
      ninth, ninth, ninth,
      ninth, ninth, ninth
    };
    mOperation = new ConvolveOp(
            new Kernel(3, 3, blurKernel),
            ConvolveOp.EDGE_NO_OP, null);
  }

  @Override
  public void paint (Graphics g, JComponent c) {
    int w = c.getWidth();
    int h = c.getHeight();

    if (w == 0 || h == 0) {
      return;
    }

    // Only create the offscreen image if the one we have
    // is the wrong size.
    if (mOffscreenImage == null ||
            mOffscreenImage.getWidth() != w ||
            mOffscreenImage.getHeight() != h) {
      mOffscreenImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
    }

    Graphics2D ig2 = mOffscreenImage.createGraphics();
    ig2.setClip(g.getClip());
    super.paint(ig2, c);
    ig2.dispose();

    Graphics2D g2 = (Graphics2D)g;
    g2.drawImage(mOffscreenImage, mOperation, 0, 0);
  }
}

В paint() метод, панель представляется во внеэкранном изображении. Внеэкранное изображение обрабатывается с оператором свертки, тогда привлеченным на экран.

Весь пользовательский интерфейс, все еще живут, только расплывчатые:

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

Исходный код:

Myopia NetBeans Project
Myopia.java

Выполненный с Сетью Java Запустите:

Запускает пример

Отвечание на События

Ваш LayerUI подкласс может также получить все события его соответствующего компонента. Однако, JLayer экземпляр должен зарегистрировать свой интерес к определенным типам событий. Это происходит с JLayer class' setLayerEventMask() метод. Как правило, однако этот вызов выполняется от инициализации, выполняемой в LayerUI class' installUI() метод.

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

public void installUI(JComponent c) {
  super.installUI(c);
  JLayer jlayer = (JLayer)c;
  jlayer.setLayerEventMask(
    AWTEvent.MOUSE_EVENT_MASK |
    AWTEvent.MOUSE_MOTION_EVENT_MASK
  );
}

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

protected void processMouseEvent(MouseEvent e, JLayer l) {
  // ...
}

protected void processMouseMotionEvent(MouseEvent e, JLayer l) {
  // ...
}

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

class SpotlightLayerUI extends LayerUI<JPanel> {
  private boolean mActive;
  private int mX, mY;

  @Override
  public void installUI(JComponent c) {
    super.installUI(c);
    JLayer jlayer = (JLayer)c;
    jlayer.setLayerEventMask(
      AWTEvent.MOUSE_EVENT_MASK |
      AWTEvent.MOUSE_MOTION_EVENT_MASK
    );
  }

  @Override
  public void uninstallUI(JComponent c) {
    JLayer jlayer = (JLayer)c;
    jlayer.setLayerEventMask(0);
    super.uninstallUI(c);
  }

  @Override
  public void paint (Graphics g, JComponent c) {
    Graphics2D g2 = (Graphics2D)g.create();

    // Paint the view.
    super.paint (g2, c);

    if (mActive) {
      // Create a radial gradient, transparent in the middle.
      java.awt.geom.Point2D center = new java.awt.geom.Point2D.Float(mX, mY);
      float radius = 72;
      float[] dist = {0.0f, 1.0f};
      Color[] colors = {new Color(0.0f, 0.0f, 0.0f, 0.0f), Color.BLACK};
      RadialGradientPaint p =
          new RadialGradientPaint(center, radius, dist, colors);
      g2.setPaint(p);
      g2.setComposite(AlphaComposite.getInstance(
          AlphaComposite.SRC_OVER, .6f));
      g2.fillRect(0, 0, c.getWidth(), c.getHeight());
    }

    g2.dispose();
  }

  @Override
  protected void processMouseEvent(MouseEvent e, JLayer l) {
    if (e.getID() == MouseEvent.MOUSE_ENTERED) mActive = true;
    if (e.getID() == MouseEvent.MOUSE_EXITED) mActive = false;
    l.repaint();
  }

  @Override
  protected void processMouseMotionEvent(MouseEvent e, JLayer l) {
    Point p = SwingUtilities.convertPoint(e.getComponent(), e.getPoint(), l);
    mX = p.x;
    mY = p.y;
    l.repaint();
  }
}

mActive переменная указывает, является ли мышь в координатах панели. В installUI() метод, setLayerEventMask() метод вызывают, чтобы указать LayerUI интерес подкласса к получению мыши и событий движения мыши.

В processMouseEvent() метод, mActive флаг устанавливается в зависимости от позиции мыши. В processMouseMotionEvent() метод, координаты перемещения мыши сохранены в mX и mY задействованные переменные так, чтобы они могли использоваться позже в paint() метод.

paint() метод показывает появление значения по умолчанию панели, затем накладывает радиальный градиент для эффекта центра внимания:

Центр внимания, который следует за мышью

Исходный код:

Diva NetBeans Project
Diva.java

Выполненный с Сетью Java Запустите:

Запускает пример

Анимация Занятого Индикатора

Этим примером является анимированный занятый индикатор. Это демонстрирует анимацию в a LayerUI разделите на подклассы и обладает постепенным появлением и постепенным исчезновением. Это более усложняется, что предыдущие примеры, но это основано на том же самом принципе определения a paint() метод для пользовательского рисунка.

Нажмите кнопку Place Order, чтобы видеть занятый индикатор в течение 4 секунд. Заметьте, как панель отображается серым и вращения индикатора. У элементов индикатора есть переменные уровни прозрачности.

LayerUI подкласс, WaitLayerUI class, шоу, как запустить события изменения свойства, чтобы обновить компонент. WaitLayerUI class использует a Timer возразите, чтобы обновить его состояние 24 раза в секунду. Это происходит в целевом методе таймера, actionPerformed() метод.

actionPerformed() метод использует firePropertyChange() метод, чтобы указать, что внутреннее состояние было обновлено. Это инициировало звонок applyPropertyChange() метод, который перекрашивает JLayer объект:

Гладкий занятый индикатор

Исходный код:

TapTapTap NetBeans Project
TapTapTap.java

Выполненный с Сетью Java Запустите:

Запускает пример

Проверка допустимости Текстовых полей

Заключительный пример в этом документе показывает как JLayer class может использоваться, чтобы украсить текстовые поля, чтобы показать, содержат ли они допустимые данные. В то время как другие примеры используют JLayer class, чтобы обернуть панели или общие компоненты, этот пример показывает, как обернуть a JFormattedTextField компонент определенно. Это также демонстрирует что сингл LayerUI реализация подкласса может использоваться для многократного JLayer экземпляры.

JLayer class используется, чтобы обеспечить визуальную индикацию для полей, у которых есть недопустимые данные. Когда ValidationLayerUI class красит текстовое поле, он тянет красноту X, если полевое содержание не может быть проанализировано. Вот пример:

Непосредственная обратная связь для плохого ввода

Исходный код:

FieldValidator NetBeans Project
FieldValidator.java

Выполненный с Сетью Java Запустите:

Запускает пример

Проблемы с примерами? Попытайтесь Компилировать и Выполнить Примеры: FAQ.
Жалобы? Поздравление? Предложения? Дайте нам свою обратную связь.

Предыдущая страница: Как к Windows Create Translucent и Shaped
Следующая страница: Как Использовать Действия