Java/Swing Components/Panel
Содержание
- 1 A basic panel that displays a small up or down arrow.
- 2 A JPanel with a textured background.
- 3 Gradient Panel
- 4 Graph Canvas
- 5 Swing Panel Group
- 6 Swing Panel Group 2
- 7 Time panel shows the current time.
- 8 Transfer focus from button to button with help of arrows keys.
- 9 Transparent Panel
- 10 Yes / No Panel
A basic panel that displays a small up or down arrow.
<source lang="java">
/*
* JCommon : a free general purpose class library for the Java(tm) platform * * * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors. * * Project Info: http://www.jfree.org/jcommon/index.html * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. * * [Java is a trademark or registered trademark of Sun Microsystems, Inc. * in the United States and other countries.] * * --------------- * ArrowPanel.java * --------------- * (C) Copyright 2002-2004, by Object Refinery Limited. * * Original Author: David Gilbert (for Object Refinery Limited); * Contributor(s): -; * * $Id: ArrowPanel.java,v 1.6 2007/11/02 17:50:36 taqua Exp $ * * Changes * ------- * 25-Sep-2002 : Version 1 (DG); * 13-Oct-2002 : Added Javadocs (DG); * */
import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Insets; import java.awt.Polygon; import java.awt.Shape; import java.awt.geom.Rectangle2D; import javax.swing.JPanel; /**
* A basic panel that displays a small up or down arrow. * * @author David Gilbert */
public class ArrowPanel extends JPanel {
/** A constant for the up arrow. */ public static final int UP = 0; /** A constant for the down arrow. */ public static final int DOWN = 1; /** The arrow type. */ private int type = UP; /** The available area. */ private Rectangle2D available = new Rectangle2D.Float(); /** * Creates a new arrow panel. * * @param type * the arrow type. */ public ArrowPanel(final int type) { this.type = type; setPreferredSize(new Dimension(14, 9)); } /** * Paints the arrow panel. * * @param g * the graphics device for drawing on. */ public void paintComponent(final Graphics g) { super.paintComponent(g); final Graphics2D g2 = (Graphics2D) g; // first determine the size of the drawing area... final Dimension size = getSize(); final Insets insets = getInsets(); this.available.setRect(insets.left, insets.top, size.getWidth() - insets.left - insets.right, size.getHeight() - insets.top - insets.bottom); g2.translate(insets.left, insets.top); g2.fill(getArrow(this.type)); } /** * Returns a shape for the arrow. * * @param t * the arrow type. * * @return the arrow shape. */ private Shape getArrow(final int t) { switch (t) { case UP: return getUpArrow(); case DOWN: return getDownArrow(); default: return getUpArrow(); } } /** * Returns an up arrow. * * @return an up arrow. */ private Shape getUpArrow() { final Polygon result = new Polygon(); result.addPoint(7, 2); result.addPoint(2, 7); result.addPoint(12, 7); return result; } /** * Returns a down arrow. * * @return a down arrow. */ private Shape getDownArrow() { final Polygon result = new Polygon(); result.addPoint(7, 7); result.addPoint(2, 2); result.addPoint(12, 2); return result; }
}
</source>
A JPanel with a textured background.
<source lang="java">
/*
* TexturedPanel.java * 2006-11-02 */
//cb.aloe.decor; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Insets; import java.awt.Paint; import java.awt.Rectangle; import java.awt.TexturePaint; import java.awt.image.BufferedImage; import javax.swing.Icon; import javax.swing.JPanel; /**
* A JPanel with a textured background. * * @author Christopher Bach */
public class TexturedPanel extends JPanel {
private TexturePaint ourPainter = null; private Color ourDefaultForeground = Color.white; private Color ourDefaultBackground = Color.gray; /** * Creates a new TexturedPanel with a simple striped pattern. */ public TexturedPanel() { super(); ourDefaultForeground = Color.white; ourDefaultBackground = getBackground(); setupDefaultPainter(ourDefaultForeground, ourDefaultBackground); } /** * Creates a new TexturedPanel with a simple striped pattern consisting of the * given foreground and background colors. */ public TexturedPanel(Color foreground, Color background) { super(); ourDefaultForeground = (foreground != null ? foreground : Color.white); ourDefaultBackground = (background != null ? background : getBackground()); setupDefaultPainter(ourDefaultForeground, ourDefaultBackground); } /** * Creates a new TexturedPanel with a simple pattern based on the provided * texture map and consisting of the given foreground and background colors. */ public TexturedPanel(Color foreground, Color background, boolean[][] texture) { super(); ourDefaultForeground = (foreground != null ? foreground : Color.white); ourDefaultBackground = (background != null ? background : getBackground()); setupTexturePainter(ourDefaultForeground, ourDefaultBackground, texture, 1); } /** * Creates a new TexturedPanel with a simple pattern based on the provided * texture map and consisting of the given foreground and background colors. */ public TexturedPanel(Color foreground, Color background, boolean[][] texture, int scale) { super(); ourDefaultForeground = (foreground != null ? foreground : Color.white); ourDefaultBackground = (background != null ? background : getBackground()); setupTexturePainter(ourDefaultForeground, ourDefaultBackground, texture, scale); } /** * Creates a new TexturedPanel that tiles the provided image. */ public TexturedPanel(Image texture) { super(); ourDefaultForeground = Color.white; ourDefaultBackground = getBackground(); if (texture != null) setupImagePainter(texture); else setupDefaultPainter(ourDefaultForeground, ourDefaultBackground); } /** * Creates a new TexturedPanel that tiles the provided icon. */ public TexturedPanel(Icon textureIcon) { super(); ourDefaultForeground = Color.white; ourDefaultBackground = getBackground(); if (textureIcon != null) { setupIconPainter(textureIcon); } else setupDefaultPainter(ourDefaultForeground, ourDefaultBackground); } /** * Sets up this TexturedPanel to paint a simple background based on the * provided texture and consisting of the provided colors. */ public void setTexture(Color foreground, Color background, boolean[][] texture) { if (foreground != null && background != null && texture != null && texture.length > 0 && texture[0].length > 0) { setupTexturePainter(foreground, background, texture, 1); } } /** * */ public void setTexture(Color foreground, Color background, boolean[][] texture, int scale) { setupTexturePainter(foreground, background, texture, scale); } /** * Sets up this TexturedPanel to paint a striped background consisting of the * provided colors. */ public void setTextureColors(Color foreground, Color background) { if (foreground != null && background != null) { ourDefaultForeground = foreground; ourDefaultBackground = background; setupDefaultPainter(foreground, background); } } /** * Sets up this TexturedPanel to paint a tiled background consisting of the * provided image. If the image is null, the background will revert to a * striped texture consisting of the last known colors. */ public void setTextureImage(Image texture) { if (texture != null) setupImagePainter(texture); else setupDefaultPainter(ourDefaultForeground, ourDefaultBackground); } /** * Sets up this TexturedPanel to paint a tiled background consisting of the * provided icon. If the icon is null, the background will revert to a striped * texture consisting of the last known colors. */ public void setTextureIcon(Icon textureIcon) { if (textureIcon != null) { setupIconPainter(textureIcon); } else setupDefaultPainter(ourDefaultForeground, ourDefaultBackground); } /** * Returns the image buffer used by this TexturedPanel"s painter. */ public Image getTexture() { if (ourPainter == null) return null; else return ourPainter.getImage(); } /** * Creates a new TexturePaint using the provided colors. */ private void setupDefaultPainter(Color foreground, Color background) { if (foreground == null || background == null) { ourPainter = null; return; } BufferedImage buff = new BufferedImage(6, 6, BufferedImage.TYPE_INT_ARGB_PRE); Graphics2D g2 = buff.createGraphics(); g2.setColor(background); g2.fillRect(0, 0, 6, 6); g2.setColor(foreground); g2.drawLine(0, 2, 6, 2); g2.drawLine(0, 5, 6, 5); ourPainter = new TexturePaint(buff, new Rectangle(0, 0, 6, 6)); g2.dispose(); } /** * Creates a new TexturePaint using the provided colors and texture map. */ private void setupTexturePainter(Color foreground, Color background, boolean[][] texture, int scale) { if (texture == null || texture.length < 1 || texture[0].length < 1) { setupDefaultPainter(foreground, background); return; } else if (foreground == null || background == null) { ourPainter = null; return; } scale = Math.max(1, scale); int w = texture[0].length; int h = texture.length; BufferedImage buff = new BufferedImage(w * scale, h * scale, BufferedImage.TYPE_INT_ARGB_PRE); Graphics2D g2 = buff.createGraphics(); g2.setColor(background); g2.fillRect(0, 0, w * scale, h * scale); g2.setColor(foreground); for (int i = 0; i < h; i++) { for (int j = 0; j < w; j++) { try { if (texture[i][j]) g2.fillRect(j * scale, i * scale, scale, scale); } // g2.drawLine(j, i, j, i); } catch (ArrayIndexOutOfBoundsException aob) { } } } ourPainter = new TexturePaint(buff, new Rectangle(0, 0, w * scale, h * scale)); g2.dispose(); } /** * Creates a new TexturePaint using the provided image. */ private void setupImagePainter(Image texture) { if (texture == null) { ourPainter = null; return; } int w = texture.getWidth(this); int h = texture.getHeight(this); if (w <= 0 || h <= 0) { ourPainter = null; return; } BufferedImage buff = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE); Graphics2D g2 = buff.createGraphics(); g2.drawImage(texture, 0, 0, this); ourPainter = new TexturePaint(buff, new Rectangle(0, 0, w, h)); g2.dispose(); } /** * Creates a new TexturePaint using the provided icon. */ private void setupIconPainter(Icon texture) { if (texture == null) { ourPainter = null; return; } int w = texture.getIconWidth(); int h = texture.getIconHeight(); if (w <= 0 || h <= 0) { ourPainter = null; return; } BufferedImage buff = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE); Graphics2D g2 = buff.createGraphics(); texture.paintIcon(this, g2, 0, 0); ourPainter = new TexturePaint(buff, new Rectangle(0, 0, w, h)); g2.dispose(); } /** * Paints this component with its textured background. */ protected void paintComponent(Graphics g) { super.paintComponent(g); if (ourPainter != null) { int w = getWidth(); int h = getHeight(); Insets in = getInsets(); int x = in.left; int y = in.top; w = w - in.left - in.right; h = h - in.top - in.bottom; if (w >= 0 && h >= 0) { Graphics2D g2 = (Graphics2D) g; Paint pt = g2.getPaint(); g2.setPaint(ourPainter); g2.fillRect(x, y, w, h); g2.setPaint(pt); } } }
}
</source>
Gradient Panel
<source lang="java">
/*
* soapUI, copyright (C) 2004-2009 eviware.ru * * soapUI is free software; you can redistribute it and/or modify it under the * terms of version 2.1 of the GNU Lesser General Public License as published by * the Free Software Foundation. * * soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details at gnu.org. */
import java.awt.BorderLayout; import java.awt.Color; import java.awt.GradientPaint; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.LayoutManager; import java.awt.Paint; import javax.swing.JPanel; /**
* Created by IntelliJ IDEA. */
public class GradientPanel extends JPanel {
// ------------------------------ FIELDS ------------------------------ public final static int HORIZONTAL = 0; public final static int VERTICAL = 1; public final static int DIAGONAL_LEFT = 2; public final static int DIAGONAL_RIGHT = 3; private int direction = HORIZONTAL; private boolean cyclic; private int maxLength; // --------------------------- CONSTRUCTORS --------------------------- public GradientPanel() { this( HORIZONTAL ); } public GradientPanel( int direction ) { super( new BorderLayout() ); setOpaque( false ); this.direction = direction; } public GradientPanel( LayoutManager layoutManager ) { super( layoutManager ); setOpaque( false ); this.direction = HORIZONTAL; } // --------------------- GETTER / SETTER METHODS --------------------- public int getDirection() { return direction; } public void setDirection( int direction ) { this.direction = direction; } public boolean isCyclic() { return cyclic; } public void setCyclic( boolean cyclic ) { this.cyclic = cyclic; } public void setMaxLength( int maxLength ) { this.maxLength = maxLength; } // -------------------------- OTHER METHODS -------------------------- public void paintComponent( Graphics g ) { if( isOpaque() ) { super.paintComponent( g ); return; } int width = getWidth(); int height = getHeight(); // Create the gradient paint GradientPaint paint = null; Color sc = getForeground(); Color ec = getBackground(); switch( direction ) { case HORIZONTAL : { paint = new GradientPaint( 0, height / 2, sc, width, height / 2, ec, cyclic ); break; } case VERTICAL : { paint = new GradientPaint( width / 2, 0, sc, width / 2, maxLength > 0 ? maxLength : height, ec, cyclic ); break; } case DIAGONAL_LEFT : { paint = new GradientPaint( 0, 0, sc, width, height, ec, cyclic ); break; } case DIAGONAL_RIGHT : { paint = new GradientPaint( width, 0, sc, 0, height, ec, cyclic ); break; } } if( paint == null ) { throw new RuntimeException( "Invalid direction specified in GradientPanel" ); } // we need to cast to Graphics2D for this operation Graphics2D g2d = ( Graphics2D )g; // save the old paint Paint oldPaint = g2d.getPaint(); // set the paint to use for this operation g2d.setPaint( paint ); // fill the background using the paint g2d.fillRect( 0, 0, width, height ); // restore the original paint g2d.setPaint( oldPaint ); super.paintComponent( g ); }
}
</source>
Graph Canvas
<source lang="java">
/*
* The contents of this file are subject to the Sapient Public License * Version 1.0 (the "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * http://carbon.sf.net/License.html. * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for * the specific language governing rights and limitations under the License. * * The Original Code is The Carbon Component Framework. * * The Initial Developer of the Original Code is Sapient Corporation * * Copyright (C) 2003 Sapient Corporation. All Rights Reserved. */
import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.geom.AffineTransform; import java.awt.geom.GeneralPath; import java.awt.geom.Line2D; import java.awt.geom.PathIterator; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.text.NumberFormat; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import javax.swing.JFrame; import javax.swing.JPanel;
/**This class provides a consistent space within to graph real * numbers. It provides features such as auto-centering and * real-time scaling. A user of this graph provides data by creating * one or more tracks and then adding real points to those. Calling * translate periodically allows you to create a scrolling graph as * well.
**
This graph will also maintain tick marks that resize and * can be stuck to the sides of the screen so they are always * visible even if the origin is off-screen.
* * Copyright 2001 Sapient * @author Greg Hinkle * @version $Revision: 1.4 $ ($Author: dvoet $ / $Date: 2003/05/05 21:21:26 $) */
public class GraphCanvas extends JPanel {
/** A list of Track"s that are a part of this graph */ private Map tracks = new HashMap(11); /** The current graph bounds that are visible */ protected Rectangle2D graphBounds; /** The portion of the entire height that should be researved as * a border, above and below the highest and lowest track points */ private static final double BORDER_PERCENT = 0.1d; /** The background color for this graph */ protected Color backgroundColor = new Color(204,204,204); protected static NumberFormat labelFormat = null; protected static NumberFormat bigNumberLabelFormat = null; /** * Instantiates a graph canvas */ public GraphCanvas() { super(); setBackground(Color.blue); this.graphBounds = new Rectangle2D.Double(-5,0,150,2);
this.labelFormat = NumberFormat.getNumberInstance(); this.labelFormat.setMaximumFractionDigits(2); this.bigNumberLabelFormat = NumberFormat.getNumberInstance(); this.bigNumberLabelFormat.setMaximumFractionDigits(0);
System.out.println("GraphCanvas::<init> - New GraphCanvas created."); } /***
Sets the background color of this graph * * @param color the Color to set the background to */ public void setBackgroundColor(Color color) { this.backgroundColor = color; } /** Gets the bounds of the graphing space that are currently showing * on the screen. * @return Rectangle2D The bounds of the currently visible graph */ public Rectangle2D getGraphBounds() { return this.graphBounds; } /** * Sets the bounds that this graph is displaying * * @param rect the Rectangle2D of the desired graph points */ public void setGraphBounds(Rectangle2D rect) { this.graphBounds = rect; } public AffineTransform getTransform() { AffineTransform affineT = new AffineTransform(1d,0d,0d,-1d,0d,super.getParent().getHeight()); // scale to current scale affineT.concatenate( AffineTransform.getScaleInstance( this.getBounds().getWidth() / this.graphBounds.getWidth(), this.getBounds().getHeight() / this.graphBounds.getHeight())); // translate to the current origin affineT.concatenate( AffineTransform.getTranslateInstance( -this.graphBounds.getX(), -this.graphBounds.getY())); return affineT; } // CLEAR ALL CURVES FROM PLOT public void clear() { } public void addTrack(String trackName) { this.tracks.put(trackName, new Track(trackName)); } public void addTrack(String trackName,Color color) { this.tracks.put(trackName, new Track(trackName,color)); } // ADD CURVE TO STORAGE (DOESN"T GRAPH UNTIL REPAINT()). public void addPoint(String track, Point2D point) { ((Track)this.tracks.get(track)).addPoint(point); } public Track getTrack(String trackName) { return (Track) this.tracks.get(trackName); } public void clearAll() { this.getGraphics().clearRect( (int)getBounds().getX(), (int)getBounds().getY(), (int)getBounds().getWidth(), (int)getBounds().getHeight()); } public void paint(Graphics gg) { Graphics2D g = (Graphics2D) gg; g.setBackground(this.backgroundColor); // What is the current graph to panel transform AffineTransform newTrans = getTransform(); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF); // Erase this entire graph so that we can redraw it g.clearRect( (int)getBounds().getX(), (int)getBounds().getY(), (int)getBounds().getWidth(), (int)getBounds().getHeight()); // This draws the tick marks and the tick values drawLines(g,newTrans); // This drawes the axeses drawAxes(g,newTrans); // This draws each of tracks in this graph drawTracks(g,newTrans); // This draws the keys for each graph drawKey(g,newTrans); } /** * <p>Draw the key to the tracks by calling thier toString
* * @param graphics2D the Graphics2D to draw to * @param transform the Affine Transform to use to determine how to draw */ protected void drawKey(Graphics2D g, AffineTransform transform) { int start = 20; Iterator trackIterator = this.tracks.values().iterator(); while(trackIterator.hasNext()) { Track track = (Track) trackIterator.next(); String info = track.toString(); // Will draw the key in the same color as it"s line g.setColor(track.getColor()); g.drawString(info,50, start+=25); } } protected void drawTracks(Graphics2D g, AffineTransform transform) { // Store original transform to restore it later // until I figure out how to track differences only AffineTransform origTrans = g.getTransform();
// Transform for local drawing g.transform(transform); g.setColor(Color.orange); // Using a small stroke will minimize the width to a single output // level pixel up to a reasonable scaling size g.setStroke(new BasicStroke(0.001f)); // Draw the tracks Iterator trackIterator = this.tracks.values().iterator(); while (trackIterator.hasNext()) { Track track = (Track) trackIterator.next(); g.setColor(track.getColor()); GeneralPath path = track.getPath(); g.draw(path); } // Reset transformation g.setTransform(origTrans); } /** * This draws the axes */ protected void drawAxes(Graphics2D g,AffineTransform transform) { g.setColor(Color.white); Point2D origin = transform.transform(new Point2D.Double(0,0),null); // If you want to have rubber banding axes (always visible) Rectangle2D axesRect = new Rectangle2D.Double(5,5,this.bounds().getWidth()-10,this.bounds().getHeight()); origin = floorPoint(origin,axesRect); Line2D x = new Line2D.Double( getBounds().getMinX(), origin.getY(), getBounds().getMaxX(), origin.getY()); Line2D y = new Line2D.Double( origin.getX(), getBounds().getMinY(), origin.getX(), getBounds().getMaxY()); g.draw(x); g.draw(y); }
/***
This finds the closest point on a rectangle"s edge to a point outside * the rectangle or if that point is within the rectangle it is returned. *
* * @param point The point to rectangularly floor * @param rect The rectangle to floor within */ public static Point2D floorPoint(Point2D point, Rectangle2D rect) { double x = point.getX(); double y = point.getY(); if (x < rect.getMinX()) x = rect.getMinX(); if (x > rect.getMaxX()) x = rect.getMaxX(); if (y < rect.getMinY()) y = rect.getMinY(); if (y > rect.getMaxY()) y = rect.getMaxY(); return new Point2D.Double(x,y); }
/***
This draws the tick marks in the graph * */ protected void drawLines(Graphics2D g, AffineTransform transform) { g.setColor(Color.white); int REAL_TICK_SPACE = 40; int REAL_TICK_HEIGHT = 10; double graphTickSpaceX = (REAL_TICK_SPACE / transform.getScaleX()); double graphTickSpaceY = (REAL_TICK_SPACE / Math.abs(transform.getScaleY())); Point2D origin = transform.transform(new Point2D.Float(0,0),null); // If you want to have rubber banding axes (always visible) Rectangle2D axesRect = new Rectangle2D.Double(5,5,this.bounds().getWidth()-10,this.bounds().getHeight()); Point2D falseOrigin = floorPoint(origin,axesRect); double firstX = this.graphBounds.getMinX(); Point2D pt = new Point2D.Float(); for (double x = firstX; x <= (this.graphBounds.getMaxX()+graphTickSpaceX); x += graphTickSpaceX) { double tx = (Math.floor(x/graphTickSpaceX)) * graphTickSpaceX; pt.setLocation(tx,0); transform.transform(pt,pt); g.drawLine((int)pt.getX(),(int)falseOrigin.getY() - 5 ,(int)pt.getX(),(int)falseOrigin.getY() + 5); String label; if (tx > 10) label = this.bigNumberLabelFormat.format(tx); else label = this.labelFormat.format(tx); g.drawString(label, (float)pt.getX(),(float)falseOrigin.getY()-9); } double firstY = this.graphBounds.getMinY(); for (double y = firstY; y <= (this.graphBounds.getMaxY()+graphTickSpaceY); y += graphTickSpaceY) { double ty = (Math.floor(y/graphTickSpaceY)) * graphTickSpaceY; pt.setLocation(0,ty); transform.transform(pt,pt); g.drawLine((int)falseOrigin.getX() - 5,(int)pt.getY() ,(int)falseOrigin.getX() + 5,(int)pt.getY()); String label; if (ty > 10) label = this.bigNumberLabelFormat.format(ty); else label = this.labelFormat.format(ty); g.drawString(label, (float)falseOrigin.getX()+7,(float)pt.getY()); } } public static class Track { protected String name; protected Color color = Color.black; //Default to black protected GeneralPath path = new GeneralPath(); protected boolean started = false; protected NumberFormat keyFormat; public Track(String name) { super(); this.name = name; this.keyFormat = NumberFormat.getNumberInstance(); this.keyFormat.setMaximumFractionDigits(2); } public Track(String name, Color color) { this(name); this.color = color; } public void setPath(GeneralPath path) { this.path = path; } public GeneralPath getPath() { return this.path; } public void addPoint(Point2D point) { if (path.getCurrentPoint() == null) { this.path.moveTo((float)point.getX(),(float)point.getY()); this.started = true; } else { this.path.lineTo((float)point.getX(),(float)point.getY()); } } public Color getColor() { return this.color; } public void setColor(Color color) { this.color = color; } public String toString() { String value = null; if (this.path.getCurrentPoint() != null) { double val = this.path.getCurrentPoint().getY(); //NumberFormat nf = NumberFormat.getNumberInstance(); value = this.keyFormat.format(val); } return this.name + ": " + value; } } /** * <p>Bounds the graph to the limits of the tracks verticaly providing a * useful scaling. A more intelligent implementation could have minimum * bounds to limit the bouncyness to startup.
*/ public void verticalBound() { Rectangle2D rect = null; Rectangle2D orig = getGraphBounds(); Iterator trackIterator = this.tracks.values().iterator(); while(trackIterator.hasNext()) { Track track = (Track) trackIterator.next(); GeneralPath path = track.getPath(); if (rect == null) rect = path.getBounds2D(); else Rectangle.union(rect,path.getBounds2D(),rect); } Rectangle.union(rect,new Rectangle2D.Double(orig.getX(),0,1,1),rect); double border = rect.getHeight() * BORDER_PERCENT; setGraphBounds(new Rectangle2D.Double( orig.getMinX(), rect.getMinY()-border, orig.getWidth(), rect.getHeight()+(2d*border))); } public void clipOld() { Rectangle2D rect = getGraphBounds(); //Rectangle2D orig = AffineTransform.getScaleInstance(1.5,1.5).createTransformedShape(getGraphBounds()).getBounds(); Iterator trackIterator = this.tracks.values().iterator(); double[] cs = new double[6]; while(trackIterator.hasNext()) { Track track = (Track) trackIterator.next(); GeneralPath path = track.getPath(); GeneralPath newPath = new GeneralPath(); PathIterator pIter = path.getPathIterator(new AffineTransform()); while (!pIter.isDone()) { pIter.currentSegment(cs); //Point2D pt = new Point2D.Double(cs[0],cs[1]); if (cs[0] > rect.getMinX()) { if (newPath.getCurrentPoint() == null) newPath.moveTo((float)cs[0],(float)cs[1]); else newPath.lineTo((float)cs[0],(float)cs[1]); } /* System.out.println("Current Segment: " + cs[0] + ", " + cs[1] + ", " + cs[2] + ", " + cs[3] + ", " + cs[4] + ", " + cs[5]); **/ pIter.next(); } track.setPath(newPath); } } /***
Translates the main graph rect by x and y, horizontally and vertically * respectively.
*/ public void translate(double x, double y) {
Rectangle2D rect = getGraphBounds(); setGraphBounds( new Rectangle2D.Double(rect.getMinX()+x, rect.getMinY()+y,rect.getWidth(),rect.getHeight())); } public static void main(String[] args) throws Exception { GraphCanvas gc = new GraphCanvas(); gc.show(); JFrame frame = new JFrame("Memory Graph"); frame.getContentPane().add(gc); frame.setSize(600,200); // TODO: Add window exit listener frame.show(); gc.repaint(); gc.paint((Graphics2D)gc.getGraphics());
long start = System.currentTimeMillis(); gc.addTrack("test", Color.cyan); gc.addTrack("test2", Color.blue); gc.addTrack("test3", Color.red); gc.addTrack("test4", Color.yellow); gc.addTrack("test5", Color.green); gc.addTrack("test6", Color.orange); gc.addTrack("test7", Color.pink);
int i=0; while (true) { i++; Point2D pt = new Point2D.Float(i,((float)Math.cos(i/20f) + (float)Math.sin(i/40f)) * 3f); gc.addPoint("test",pt); Point2D pt2 = new Point2D.Float(i,(float)Math.cos(i/25.0f)*10f); gc.addPoint("test2",pt2); Point2D pt3 = new Point2D.Float(i,Math.min((float)Math.cos(Math.sin(i/4f))*13f - (float)Math.cos(i/80f)*20f,400f)); gc.addPoint("test3",pt3); Point2D pt4 = new Point2D.Float(i, (float) Math.sin(.31*i)*2f + ((float)2f*(float)Math.cos(.07f*i))*8f); gc.addPoint("test4",pt4); Point2D pt5 = new Point2D.Float(i, (float) Math.cos(.66*i)*1f + ((float)2f*(float)Math.cos(.07f*i))*3f); gc.addPoint("test5",pt5); Point2D pt6 = new Point2D.Float(i, (float) Math.sin(.31*i)*2f + ((float)2f*(float)Math.cos(.07f*Math.tan(i)))*5f); gc.addPoint("test6",pt6); Point2D pt7 = new Point2D.Float(i, (float) Math.sin(i)*2f + ((float)2f*(float)Math.sin(.25f*i))*0.5f); gc.addPoint("test7",pt7);
if (i > 150) gc.translate(1,0); gc.verticalBound(); //if(i%100 == 0) { gc.clipOld(); //} gc.repaint(); Thread.sleep(10); if (i % 100 == 0) { System.out.println("Framewrate: " + (100d / ((System.currentTimeMillis()-start)/1000d))); start = System.currentTimeMillis(); } } }
}
</source>
Swing Panel Group
<source lang="java">
(From http://swinglabs.org/downloads.jsp)
</source>
Swing Panel Group 2
<source lang="java">
(From http://swinglabs.org/downloads.jsp)
</source>
Time panel shows the current time.
<source lang="java">
/*
* Copyright (C) 2002-2003 Colin Bell * colbell@users.sourceforge.net * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
import java.awt.Dimension; import java.awt.FontMetrics; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.text.DateFormat; import java.util.Calendar; import javax.swing.JLabel; import javax.swing.Timer; import javax.swing.border.Border; /**
* Time panel. This will show the current time. * A timer to update the time is started when the component * is added to its parent and stopped when removed from its parent. * * @author */
public class TimePanel extends JLabel implements ActionListener {
/** Timer that updates time. */ private Timer _timer; /** Used to format the displayed date. */ private DateFormat _fmt = DateFormat.getTimeInstance(DateFormat.LONG); private Dimension _prefSize; private Calendar _calendar = Calendar.getInstance(); /** * Default ctor. */ public TimePanel() { super("", JLabel.CENTER); } /** * Add component to its parent. Start the timer for auto-update. */ public void addNotify() { super.addNotify(); _timer = new Timer(1000, this); _timer.start(); } /** * Remove component from its parent. Stop the timer. */ public void removeNotify() { super.removeNotify(); if (_timer != null) { _timer.stop(); _timer = null; } } /** * Update component with the current time. * * @param evt The current event. */ public void actionPerformed(ActionEvent evt) { _calendar.setTimeInMillis(System.currentTimeMillis()); setText(_fmt.format(_calendar.getTime())); } /** * Return the preferred size of this component. * * @return the preferred size of this component. */ public Dimension getPreferredSize() { if(null == _prefSize) { // This was originaly done every time. // and the count of instantiated objects was amazing _prefSize = new Dimension(); _prefSize.height = 20; FontMetrics fm = getFontMetrics(getFont()); Calendar cal = Calendar.getInstance(); cal.set(Calendar.HOUR_OF_DAY, 23); cal.set(Calendar.MINUTE, 59); cal.set(Calendar.SECOND, 59); _prefSize.width = fm.stringWidth(_fmt.format(cal.getTime())); Border border = getBorder(); if (border != null) { Insets ins = border.getBorderInsets(this); if (ins != null) { _prefSize.width += (ins.left + ins.right); } } Insets ins = getInsets(); if (ins != null) { _prefSize.width += (ins.left + ins.right) + 20; } } return _prefSize; }
}
</source>
Transfer focus from button to button with help of arrows keys.
<source lang="java">
/*
* Copyright 2006 Sun Microsystems, Inc., 4150 Network Circle, * Santa Clara, California 95054, U.S.A. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
import java.awt.BorderLayout; import java.awt.ruponent; import java.awt.Container; import java.awt.FocusTraversalPolicy; import java.awt.GridLayout; import java.awt.KeyboardFocusManager; import java.awt.LayoutManager; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import javax.swing.AbstractButton; import javax.swing.BorderFactory; import javax.swing.ButtonGroup; import javax.swing.ButtonModel; import javax.swing.DefaultButtonModel; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.KeyStroke; import javax.swing.LayoutFocusTraversalPolicy; import javax.swing.SwingUtilities; import javax.swing.border.TitledBorder; /**
* This is a JPanel subclass which provides a special functionality * for its children buttons components. * It makes it possible to transfer focus from button to button * with help of arrows keys.*
The following example shows how to enable cyclic focus transfer *
* import org.jdesktop.swinghelper.buttonpanel.*; * import javax.swing.*; * * public class SimpleDemo { * public static void main(String[] args) throws Exception { * SwingUtilities.invokeLater(new Runnable() { * public void run() { * final JFrame frame = new JFrame(); * frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); * * JXButtonPanel panel = new JXButtonPanel(); * panel.setCyclic(true); * * panel.add(new JButton("One")); * panel.add(new JButton("Two")); * panel.add(new JButton("Three")); * * frame.add(panel); * frame.setSize(200, 200); * frame.setLocationRelativeTo(null); * frame.setVisible(true); * } * }); * } * } *
* * If your buttons inside JXButtonPanel are added to one ButtonGroup * arrow keys will transfer selection between them as well as they do it for focus<p> * Note: you can control this behaviour with setGroupSelectionFollowFocus(boolean)*
* import org.jdesktop.swinghelper.buttonpanel.*; * import javax.swing.*; * * public class RadioButtonDemo { * public static void main(String[] args) throws Exception { * SwingUtilities.invokeLater(new Runnable() { * public void run() { * final JFrame frame = new JFrame(); * frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); * * JXButtonPanel panel = new JXButtonPanel(); * ButtonGroup group = new ButtonGroup(); * * JRadioButton rb1 = new JRadioButton("One"); * panel.add(rb1); * group.add(rb1); * JRadioButton rb2 = new JRadioButton("Two"); * panel.add(rb2); * group.add(rb2); * JRadioButton rb3 = new JRadioButton("Three"); * panel.add(rb3); * group.add(rb3); * * rb1.setSelected(true); * frame.add(panel); * * frame.setSize(200, 200); * frame.setLocationRelativeTo(null); * frame.setVisible(true); * } * }); * } * } *
* * @author Alexander Potochkin * * https://swinghelper.dev.java.net/ * http://weblogs.java.net/blog/alexfromsun/ */
public class JXButtonPanel extends JPanel {
private boolean isCyclic; private boolean isGroupSelectionFollowFocus; /** * {@inheritDoc} */ public JXButtonPanel() { super(); init(); } /** * {@inheritDoc} */ public JXButtonPanel(LayoutManager layout) { super(layout); init(); } /** * {@inheritDoc} */ public JXButtonPanel(boolean isDoubleBuffered) { super(isDoubleBuffered); init(); } /** * {@inheritDoc} */ public JXButtonPanel(LayoutManager layout, boolean isDoubleBuffered) { super(layout, isDoubleBuffered); init(); } private void init() { setFocusTraversalPolicyProvider(true); setFocusTraversalPolicy(new JXButtonPanelFocusTraversalPolicy()); ActionListener actionHandler = new ActionHandler(); registerKeyboardAction(actionHandler, ActionHandler.FORWARD, KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); registerKeyboardAction(actionHandler, ActionHandler.FORWARD, KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); registerKeyboardAction(actionHandler, ActionHandler.BACKWARD, KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); registerKeyboardAction(actionHandler, ActionHandler.BACKWARD, KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); setGroupSelectionFollowFocus(true); } /** * Returns whether arrow keys should support * cyclic focus traversal ordering for for this JXButtonPanel. */ public boolean isCyclic() { return isCyclic; } /** * Sets whether arrow keys should support * cyclic focus traversal ordering for this JXButtonPanel. */ public void setCyclic(boolean isCyclic) { this.isCyclic = isCyclic; } /** * Returns whether arrow keys should transfer button"s * selection as well as focus for this JXButtonPanel.<p> * * Note: this property affects buttons which are added to a ButtonGroup */ public boolean isGroupSelectionFollowFocus() { return isGroupSelectionFollowFocus; } /** * Sets whether arrow keys should transfer button"s * selection as well as focus for this JXButtonPanel.<p> * * Note: this property affects buttons which are added to a ButtonGroup */ public void setGroupSelectionFollowFocus(boolean groupSelectionFollowFocus) { isGroupSelectionFollowFocus = groupSelectionFollowFocus; } private static ButtonGroup getButtonGroup(AbstractButton button) { ButtonModel model = button.getModel(); if (model instanceof DefaultButtonModel) { return ((DefaultButtonModel) model).getGroup(); } return null; } private class ActionHandler implements ActionListener { private static final String FORWARD = "moveSelectionForward"; private static final String BACKWARD = "moveSelectionBackward"; public void actionPerformed(ActionEvent e) { FocusTraversalPolicy ftp = JXButtonPanel.this.getFocusTraversalPolicy(); if (ftp instanceof JXButtonPanelFocusTraversalPolicy) { JXButtonPanelFocusTraversalPolicy xftp = (JXButtonPanelFocusTraversalPolicy) ftp; String actionCommand = e.getActionCommand(); Component fo = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); Component next; xftp.setAlternativeFocusMode(true); if (FORWARD.equals(actionCommand)) { next = xftp.getComponentAfter(JXButtonPanel.this, fo); } else if (BACKWARD.equals(actionCommand)) { next = xftp.getComponentBefore(JXButtonPanel.this, fo); } else { throw new AssertionError("Unexpected action command: " + actionCommand); } xftp.setAlternativeFocusMode(false); if (fo instanceof AbstractButton) { AbstractButton b = (AbstractButton) fo; b.getModel().setPressed(false); } if (next != null) { if (fo instanceof AbstractButton && next instanceof AbstractButton) { ButtonGroup group = getButtonGroup((AbstractButton) fo); AbstractButton nextButton = (AbstractButton) next; if (group != getButtonGroup(nextButton)) { return; } if (isGroupSelectionFollowFocus() && group != null && group.getSelection() != null && !nextButton.isSelected()) { nextButton.setSelected(true); } next.requestFocusInWindow(); } } } } } private class JXButtonPanelFocusTraversalPolicy extends LayoutFocusTraversalPolicy { private boolean isAlternativeFocusMode; public boolean isAlternativeFocusMode() { return isAlternativeFocusMode; } public void setAlternativeFocusMode(boolean alternativeFocusMode) { isAlternativeFocusMode = alternativeFocusMode; } protected boolean accept(Component c) { if (!isAlternativeFocusMode() && c instanceof AbstractButton) { AbstractButton button = (AbstractButton) c; ButtonGroup group = JXButtonPanel.getButtonGroup(button); if (group != null && group.getSelection() != null && !button.isSelected()) { return false; } } return super.accept(c); } public Component getComponentAfter(Container aContainer, Component aComponent) { Component componentAfter = super.getComponentAfter(aContainer, aComponent); if (!isAlternativeFocusMode()) { return componentAfter; } if (JXButtonPanel.this.isCyclic()) { return componentAfter == null ? getFirstComponent(aContainer) : componentAfter; } if (aComponent == getLastComponent(aContainer)) { return aComponent; } return componentAfter; } public Component getComponentBefore(Container aContainer, Component aComponent) { Component componentBefore = super.getComponentBefore(aContainer, aComponent); if (!isAlternativeFocusMode()) { return componentBefore; } if (JXButtonPanel.this.isCyclic()) { return componentBefore == null ? getLastComponent(aContainer) : componentBefore; } if (aComponent == getFirstComponent(aContainer)) { return aComponent; } return componentBefore; } }
}
/**
* @author Alexander Potochkin * * https://swinghelper.dev.java.net/ * http://weblogs.java.net/blog/alexfromsun/ */
class JXButtonPanelDemo extends JFrame {
private ButtonGroup radioGroup = new ButtonGroup(); public JXButtonPanelDemo() { super("JXButtonPanel demo"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setResizable(false); JPanel topPanel = new JPanel(new GridLayout(1, 0)); final JXButtonPanel radioGroupPanel = createRadioJXButtonPanel(); topPanel.add(radioGroupPanel); final JXButtonPanel checkBoxPanel = createCheckBoxJXButtonPanel(); topPanel.add(checkBoxPanel); add(topPanel); add(createButtonJXButtonPanel(), BorderLayout.SOUTH); pack(); JMenuBar bar = new JMenuBar(); JMenu menu = new JMenu("Options"); JMenuItem item = new JMenuItem("Unselect radioButtons"); item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.ALT_MASK)); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { // hack for 1.5 // in 1.6 ButtonGroup.clearSelection added JRadioButton b = new JRadioButton(); radioGroup.add(b); b.setSelected(true); radioGroup.remove(b); } }); menu.add(item); bar.add(menu); setJMenuBar(bar); setSize(300, 300); setLocationRelativeTo(null); } private JXButtonPanel createRadioJXButtonPanel() { JXButtonPanel panel = new JXButtonPanel(); panel.setLayout(new GridLayout(0, 1)); JRadioButton one = new JRadioButton("One"); panel.add(one); radioGroup.add(one); JRadioButton two = new JRadioButton("Two"); panel.add(two); radioGroup.add(two); JRadioButton three = new JRadioButton("Three"); panel.add(three); radioGroup.add(three); JRadioButton four = new JRadioButton("Four"); panel.add(four); radioGroup.add(four); one.setSelected(true); panel.setBorder(BorderFactory.createTitledBorder("JXButtonPanel")); return panel; } private JXButtonPanel createCheckBoxJXButtonPanel() { JXButtonPanel panel = new JXButtonPanel(); panel.setLayout(new GridLayout(0, 1)); JCheckBox one = new JCheckBox("One"); panel.add(one); JCheckBox two = new JCheckBox("Two"); panel.add(two); JCheckBox three = new JCheckBox("Three"); panel.add(three); JCheckBox four = new JCheckBox("Four"); panel.add(four); panel.setBorder(BorderFactory.createTitledBorder("JXButtonPanel")); return panel; } private JPanel createButtonJXButtonPanel() { JPanel ret = new JPanel(new BorderLayout()); JLabel label = new JLabel("Does JXButtonPanel support arrow keys ?"); label.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0)); JPanel temp = new JPanel(); temp.add(label); ret.add(temp); JXButtonPanel panel = new JXButtonPanel(); panel.setCyclic(true); panel.add(new JButton("Yes")); panel.add(new JButton("Sure")); panel.add(new JButton("Absolutely !")); panel.setBorder(BorderFactory.createTitledBorder(null, "JXButtonPanel.setCyclic(true)", TitledBorder.CENTER, TitledBorder.BOTTOM)); ret.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); ret.add(panel, BorderLayout.SOUTH); return ret; } public static void main(String[] args) throws Exception { SwingUtilities.invokeLater(new Runnable() { public void run() { new JXButtonPanelDemo().setVisible(true); } }); }
}
</source>
Transparent Panel
<source lang="java">
(From http://swinglabs.org/downloads.jsp)
</source>
Yes / No Panel
<source lang="java">
/*
* Copyright (c) 2004 David Flanagan. All rights reserved. * This code is from the book Java Examples in a Nutshell, 3nd Edition. * It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied. * You may study, use, and modify it for any non-commercial purpose, * including teaching and use in open-source projects. * You may distribute it non-commercially as long as you retain this notice. * For a commercial use license, or to purchase the book, * please visit http://www.davidflanagan.ru/javaexamples3. */
import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JPanel; 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();
} /**
* A custom component that displays multiple lines of text with specified * margins and alignment. */
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; }
} class AnswerEvent extends java.util.EventObject {
public static final int YES = 0, NO = 1, CANCEL = 2; // Button constants protected int id; // Which button was pressed? public AnswerEvent(Object source, int id) { super(source); this.id = id; } public int getID() { return id; } // Return the button
} interface AnswerListener extends java.util.EventListener {
public void yes(AnswerEvent e); public void no(AnswerEvent e); public void cancel(AnswerEvent e);
} /**
* This JavaBean displays a multi-line message and up to three buttons. It fires * an AnswerEvent when the user clicks on one of the buttons */
public class YesNoPanel extends JPanel {
// Properties of the bean. protected String messageText; // The message to display protected Alignment alignment; // The alignment of the message protected String yesLabel; // Text for the yes, no, & cancel buttons protected String noLabel; protected String cancelLabel; // Internal components of the panel protected MultiLineLabel message; protected JPanel buttonbox; protected JButton yes, no, cancel; /** The no-argument bean constructor, with default property values */ public YesNoPanel() { this("Your\nMessage\nHere"); } public YesNoPanel(String messageText) { this(messageText, Alignment.LEFT, "Yes", "No", "Cancel"); } /** A constructor for programmers using this class "by hand" */ public YesNoPanel(String messageText, Alignment alignment, String yesLabel, String noLabel, String cancelLabel) { // Create the components for this panel setLayout(new BorderLayout(15, 15)); // Put the message label in the middle of the window. message = new MultiLineLabel(messageText, 20, 20, alignment); message.setOpaque(false); // allow background color to show through add(message, BorderLayout.CENTER); // Create a panel for the Panel buttons and put it at the bottom // of the Panel. Specify a FlowLayout layout manager for it. buttonbox = new JPanel(); buttonbox.setLayout(new FlowLayout(FlowLayout.CENTER, 25, 15)); buttonbox.setOpaque(false); // allow background color to show through add(buttonbox, BorderLayout.SOUTH); // Create each specified button, specifying the action listener // and action command for each, and adding them to the buttonbox yes = new JButton(); // Create buttons no = new JButton(); cancel = new JButton(); // Add the buttons to the button box buttonbox.add(yes); buttonbox.add(no); buttonbox.add(cancel); // Register listeners for each button yes.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { fireEvent(new AnswerEvent(YesNoPanel.this, AnswerEvent.YES)); } }); no.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { fireEvent(new AnswerEvent(YesNoPanel.this, AnswerEvent.NO)); } }); cancel.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { fireEvent(new AnswerEvent(YesNoPanel.this, AnswerEvent.CANCEL)); } }); // Now call property setter methods to set the message and button // components to contain the right text setMessageText(messageText); setAlignment(alignment); setYesLabel(yesLabel); setNoLabel(noLabel); setCancelLabel(cancelLabel); } // Methods to query all of the bean properties. public String getMessageText() { return messageText; } public Alignment getAlignment() { return alignment; } public String getYesLabel() { return yesLabel; } public String getNoLabel() { return noLabel; } public String getCancelLabel() { return cancelLabel; } public Font getMessageFont() { return message.getFont(); } public Color getMessageColor() { return message.getForeground(); } public Font getButtonFont() { return yes.getFont(); } // Methods to set all of the bean properties. public void setMessageText(String messageText) { this.messageText = messageText; message.setLabel(messageText); } public void setAlignment(Alignment alignment) { this.alignment = alignment; message.setAlignment(alignment); } public void setYesLabel(String l) { yesLabel = l; yes.setText(l); yes.setVisible((l != null) && (l.length() > 0)); } public void setNoLabel(String l) { noLabel = l; no.setText(l); no.setVisible((l != null) && (l.length() > 0)); } public void setCancelLabel(String l) { cancelLabel = l; cancel.setText(l); cancel.setVisible((l != null) && (l.length() > 0)); } public void setMessageFont(Font f) { message.setFont(f); } public void setMessageColor(Color c) { message.setForeground(c); } public void setButtonFont(Font f) { yes.setFont(f); no.setFont(f); cancel.setFont(f); } /** This field holds a list of registered ActionListeners. */ protected List listeners = new ArrayList(); /** Register an action listener to be notified when a button is pressed */ public void addAnswerListener(AnswerListener l) { listeners.add(l); } /** Remove an Answer listener from our list of interested listeners */ public void removeAnswerListener(AnswerListener l) { listeners.remove(l); } /** Send an event to all registered listeners */ public void fireEvent(AnswerEvent e) { // Make a copy of the list and fire the events using that copy. // This means that listeners can be added or removed from the original // list in response to this event. Object[] copy = listeners.toArray(); for (int i = 0; i < copy.length; i++) { AnswerListener listener = (AnswerListener) copy[i]; switch (e.getID()) { case AnswerEvent.YES: listener.yes(e); break; case AnswerEvent.NO: listener.no(e); break; case AnswerEvent.CANCEL: listener.cancel(e); break; } } } /** A main method that demonstrates the class */ public static void main(String[] args) { // Create an instance of YesNoPanel, with title and message specified: YesNoPanel p = new YesNoPanel("Do you really want to quit?"); // Register an action listener for the Panel. This one just prints // the results out to the console. p.addAnswerListener(new AnswerListener() { public void yes(AnswerEvent e) { System.exit(0); } public void no(AnswerEvent e) { System.out.println("No"); } public void cancel(AnswerEvent e) { System.out.println("Cancel"); } }); JFrame f = new JFrame(); f.getContentPane().add(p); f.pack(); f.setVisible(true); }
}
</source>