Java Examples In A Nutshell (3rd Edition) [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Java Examples In A Nutshell (3rd Edition) [Electronic resources] - نسخه متنی

O'Reilly Media, Inc

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید








15.2 A Simple Bean


As
noted earlier, Swing and AWT components can all function as beans.
When you write a custom GUI component, it is not difficult to make it
function as a bean as well. Example 15-1 shows the
definition of a custom JavaBeans component,
MultiLineLabel, that displays one or more lines of
static text.

What makes this component a bean is
that all its properties have get and
set accessor methods. Because
MultiLineLabel doesn't respond to
user input in any way, it doesn't define any events,
so no event-listener registration methods are required.
MultiLineLabel also defines a no-argument
constructor, so that it can be easily instantiated by beanboxes.

Example 15-1. MultiLineLabel.java

package je3.beans;
import java.awt.*;
import javax.swing.*;
import java.util.StringTokenizer;
/**
* A custom component that displays multiple lines of text with specified
* margins and alignment.
**/
public class MultiLineLabel extends JComponent {
// User-specified properties
protected String label; // The label, not broken into lines
protected int margin_width; // Left and right margins
protected int margin_height; // Top and bottom margins
protected Alignment alignment; // The alignment of the text.
// Computed state values
protected int num_lines; // The number of lines
protected String[ ] lines; // The label, broken into lines
protected int[ ] line_widths; // How wide each line is
protected int max_width; // The width of the widest line
protected int line_height; // Total height of the font
protected int line_ascent; // Font height above baseline
protected boolean measured = false; // Have the lines been measured?
// Here are five versions of the constructor.
public MultiLineLabel(String label, int margin_width,
int margin_height, Alignment alignment) {
this.label = label; // Remember all the properties.
this.margin_width = margin_width;
this.margin_height = margin_height;
this.alignment = alignment;
newLabel( ); // Break the label up into lines.
}
public MultiLineLabel(String label, int margin_width,
int margin_height) {
this(label, margin_width, margin_height, Alignment.LEFT);
}
public MultiLineLabel(String label, Alignment alignment) {
this(label, 10, 10, alignment);
}
public MultiLineLabel(String label)
{ this(label, 10, 10, Alignment.LEFT);}
public MultiLineLabel( ) { this("); }
// Methods to set and query the various attributes of the component.
// Note that some query methods are inherited from the superclass.
public void setLabel(String label) {
this.label = label;
newLabel( ); // Break the label into lines.
repaint( ); // Request a redraw.
measured = false; // Note that we need to measure lines.
invalidate( ); // Tell our containers about this
}
public void setAlignment(Alignment a) { alignment = a; repaint( ); }
public void setMarginWidth(int mw) { margin_width = mw; repaint( ); }
public void setMarginHeight(int mh) { margin_height = mh; repaint( ); }
// Override this property setter method because we need to remeasure
public void setFont(Font f) {
super.setFont(f); // Tell our superclass about the new font.
repaint( ); // Request a redraw.
measured = false; // Note that we need to remeasure lines.
invalidate( ); // Tell our containers about new size
}
// Property getter methods.
public String getLabel( ) { return label; }
public Alignment getAlignment( ) { return alignment; }
public int getMarginWidth( ) { return margin_width; }
public int getMarginHeight( ) { return margin_height; }
/**
* This method is called by a layout manager when it wants to
* know how big we'd like to be.
*/
public Dimension getPreferredSize( ) {
if (!measured) measure( );
return new Dimension(max_width + 2*margin_width,
num_lines * line_height + 2*margin_height);
}
/**
* This method is called when the layout manager wants to know
* the bare minimum amount of space we need to get by.
*/
public Dimension getMinimumSize( ) { return getPreferredSize( ); }
/**
* This method draws the component.
* Note that it handles the margins and the alignment, but that
* it doesn't have to worry about the color or font--the superclass
* takes care of setting those in the Graphics object we're passed.
**/
public void paintComponent(Graphics g) {
int x, y;
Dimension size = this.getSize( );
if (!measured) measure( );
y = line_ascent + (size.height - num_lines * line_height)/2;
for(int i = 0; i < num_lines; i++, y += line_height) {
if (alignment == Alignment.LEFT) x = margin_width;
else if (alignment == Alignment.CENTER)
x = (size.width - line_widths[i])/2;
else x = size.width - margin_width - line_widths[i];
g.drawString(lines[i], x, y);
}
}
/**
* This internal method breaks a specified label
up into an array of lines.
* It uses the StringTokenizer utility class.
**/
protected synchronized void newLabel( ) {
StringTokenizer t = new StringTokenizer(label, "\n");
num_lines = t.countTokens( );
lines = new String[num_lines];
line_widths = new int[num_lines];
for(int i = 0; i < num_lines; i++) lines[i] = t.nextToken( );
}
/**
* This internal method figures out how the font is, and how wide each
* line of the label is, and how wide the widest line is.
**/
protected synchronized void measure( ) {
FontMetrics fm = this.getFontMetrics(this.getFont( ));
line_height = fm.getHeight( );
line_ascent = fm.getAscent( );
max_width = 0;
for(int i = 0; i < num_lines; i++) {
line_widths[i] = fm.stringWidth(lines[i]);
if (line_widths[i] > max_width) max_width = line_widths[i];
}
measured = true;
}
}


15.2.1 The Alignment Class


MultiLineLabel uses an
auxiliary class named Alignment to define three
alignment constants. The definition of this class is shown in Example 15-2. The class defines three constants that hold
three instances of itself, and declares its constructor
private so that no other instances can be created.
In this way, Alignment effectively creates an
enumerated type. This is a useful technique that is not at all
specific to JavaBeans.

Example 15-2. Alignment.java

package je3.beans;
/** This class defines an enumerated type with three values */
public class Alignment {
/** This private constructor prevents anyone from instantiating us */
private Alignment( ) { };
// The following three constants are the only instances of this class
public static final Alignment LEFT = new Alignment( );
public static final Alignment CENTER = new Alignment( );
public static final Alignment RIGHT = new Alignment( );
}


15.2.2 Packaging a Bean


To prepare a bean for use
in a beanbox, you must package it in a JAR file, along with any other
classes or resource files it requires. (JAR files are
"Java archives"; you can read about
the jar tool in Java in a
Nutshell
.) Because a single bean can have many auxiliary
files, and because a JAR file can contain multiple beans, the
manifest of the JAR file must define which JAR file entries are
beans. You create a JAR file with the c option to
the jar command. When you use the
m option in conjunction with c,
it tells jar to read a partial manifest file
that you specify. jar uses the information in
your partially specified manifest file when creating the complete
manifest for the JAR file. To identify a class file as a bean, you
simply add the following line to the file's manifest
entry:

Java-Bean: true

To package the MultiLineLabel class in a JAR file,
first create a manifest "stub"
file. Create a file, perhaps named
manifest.stub, with these contents:

Name: je3/beans/MultiLineLabel.class
Java-Bean: true

Note that the forward slashes in the
manifest file shouldn't be changed to backward
slashes on Windows systems. The format of the JAR manifest file
requires forward slashes to separate directories, regardless of the
platform. Having created this partial manifest file, you can now
create the JAR file:

% jar cfm MultiLineLabel.jar manifest.stub 
je3/beans/MultiLineLabel.class je3/beans/Alignment.class

Note that this is a single long command line that has been broken
onto two lines. Also, on a Windows system, you do need to replace
forward slashes with backslashes in this command line. If this bean
required auxiliary files, you would specify them at the end of the
jar command line, along with the class files for
the bean.


15.2.3 Installing a Bean


The procedure for installing a bean
depends on the beanbox tool you use. For Sun's
demonstration Bean Builder tool, for example,
use the Load Jar... command in the
File menu to make your beans appear
on the palette of available beans. For our own
ShowBean tool, you simply need to ensure that the
JAR file is in your classpath. In fact, you don't
need to create the JAR file at all to use
ShowBean: you can just ensure that the bean
development directory is in your classpath.

/ 285