Философия Java

         

Более изощренные компоненты (Bean)


Этот следующий пример немного более изощренный, хотя фривольный. Есть JPanel, которая рисует маленькую окружность вокруг мыши, куда бы мышь не переместилась. Когда вы нажимаете кнопку, появляется “Bang!” в середине экрана, и возбуждается слушатель события.

Свойства, которые вы можете менять, это размер окружности, точно так же как и цвет, размер и текст слова, которое отображается при нажатии кнопки. BangBean также имеет свой собственный addActionListener( ) и removeActionListener( ), так что вы можете присоединять свой собственный слушатель, который будет обрабатывать щелчки мыши в BangBean. Вы должны быть способны распознать свойства и поддержку событий:

//: bangbean:BangBean.java

// Графический Bean.

package bangbean; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.io.*; import java.util.*; import com.bruceeckel.swing.*;

public class BangBean extends JPanel implements Serializable { protected int xm, ym; protected int cSize = 20; // Размер окружности

protected String text = "Bang!"; protected int fontSize = 48; protected Color tColor = Color.red; protected ActionListener actionListener; public BangBean() { addMouseListener(new ML()); addMouseMotionListener(new MML()); } public int getCircleSize() { return cSize; } public void setCircleSize(int newSize) { cSize = newSize; } public String getBangText() { return text; } public void setBangText(String newText) { text = newText; } public int getFontSize() { return fontSize; } public void setFontSize(int newSize) { fontSize = newSize; } public Color getTextColor() { return tColor; } public void setTextColor(Color newColor) { tColor = newColor; } public void paintComponent(Graphics g) { super.paintComponent(g); g.setColor(Color.black); g.drawOval(xm - cSize/2, ym - cSize/2, cSize, cSize); } // Это уникальный слушатель, который

// является упрощенной формой управления слушателем:

public void addActionListener ( ActionListener l) throws TooManyListenersException { if(actionListener != null) throw new TooManyListenersException(); actionListener = l; } public void removeActionListener( ActionListener l) { actionListener = null; } class ML extends MouseAdapter { public void mousePressed(MouseEvent e) { Graphics g = getGraphics(); g.setColor(tColor); g.setFont( new Font( "TimesRoman", Font.BOLD, fontSize)); int width = g.getFontMetrics().stringWidth(text); g.drawString(text, (getSize().width - width) /2, getSize().height/2); g.dispose(); // Вызов метода слушателя:


if(actionListener != null) actionListener.actionPerformed( new ActionEvent(BangBean.this, ActionEvent.ACTION_PERFORMED, null)); } } class MML extends MouseMotionAdapter { public void mouseMoved(MouseEvent e) { xm = e.getX(); ym = e.getY(); repaint(); } } public Dimension getPreferredSize() { return new Dimension(200, 200); } } ///:~

Первое, что вы заметите, это то, что BangBean реализует интерфейс Serializable. Это значит, что построитель приложения может “законсервировать” всю информацию для BangBean, используя сериализацию, после того, как дизайнер установит значения свойств. Когда компонент (Bean) создастся как часть работающего приложения, эти “законсервированные” свойства восстанавливаются, так что вы получаете точно то, что разрабатывали.

Вы можете видеть, что все поля являются private, это то, что вы обычно делаете с компонентами, позволяя получить доступ только через методы, обычно, используя схему “property”.

Когда вы взглянете на сигнатуру addActionListener( ), вы увидите, что он может выбрасывать TooManyListenersException. Это означает, что здесь индивидуальная (unicast) обработка, которая означает, что извещается только один слушатель о возникновении события. Обычно вы будете использовать групповые (multicast) события, так что много слушателей могут быть извещены о событии. Однако это вводит нас в область, которую вы не готовы воспринять до следующей главы, так что мы вернемся к этому (под заголовком “возврат к JavaBeans”). Индивидуальная обработка обходит проблему.

Когда вы щелкаете мышью, текст помещается в центр BangBean, а если поле actionListener не null, вызывается actionPerformed( ), в процессе создается новый объект ActionEvent. Куда бы мышь не переместилась, захватываются новые координаты, и происходит перерисовка канвы (стирание любого текста, расположенного на канве, как вы увидите).

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

//: c13:BangBeanTest.java

// <applet code=BangBeanTest



// width=400 height=500></applet>

import bangbean.*; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.*; import com.bruceeckel.swing.*;

public class BangBeanTest extends JApplet { JTextField txt = new JTextField(20); // Во время тестирования отчет о действиях:

class BBL implements ActionListener { int count = 0; public void actionPerformed(ActionEvent e){ txt.setText("BangBean action "+ count++); } } public void init() { BangBean bb = new BangBean(); try { bb.addActionListener(new BBL()); } catch(TooManyListenersException e) { txt.setText("Too many listeners"); } Container cp = getContentPane(); cp.add(bb); cp.add(BorderLayout.SOUTH, txt); } public static void main(String[] args) { Console.run(new BangBeanTest(), 400, 500); } } ///:~

Когда компонент (Bean) находится в среде разработки, этот класс не будет использоваться, но полезно обеспечить тестирование метода для каждого вашего компонента (Bean). BangBeanTest помещает BangBean в апплет, присоединяет простой ActionListener к BangBean для печати счетчика событий в JTextField, когда бы не возникло ActionEvent. Конечно, обычно построитель приложения создает большинство кода, который использует этот компонент (Bean).

Когда вы запустите BangBean через BeanDumper, или поместите BangBean внутрь среды разработки, поддерживающей компоненты, вы заметите, что есть гораздо больше свойств и действий, чем это видно в приведенном выше коде. Это происходит потому, что BangBean наследуется от JPanel, а JPanel - это тоже компонент (Bean), так что вы также видите его свойства и события.


Содержание раздела