Java/2D Graphics GUI/Stroke
Содержание
- 1 A component for choosing a stroke from a list of available strokes.
- 2 A dashed stroke
- 3 Basic stroke
- 4 Cancel the effects of the zoom on a particular Stroke
- 5 Changing the Thickness of the Stroking Pen
- 6 Custom Strokes
- 7 Dashed rectangle
- 8 Dashed stroke
- 9 Serialises a Stroke object
- 10 Smokey effect
- 11 Stroke with iron effect
- 12 Stroking or Filling with a Texture
- 13 Thick stroke demo
- 14 Tries to deduct the stroke-type from the given stroke object.
- 15 Tries to extract the stroke-width from the given stroke object.
A component for choosing a stroke from a list of available strokes.
<source lang="java"> /*
* JCommon : a free general purpose class library for the Java(tm) platform * * * (C) Copyright 2000-2009, 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.] * * ----------------------- * StrokeChooserPanel.java * ----------------------- * (C) Copyright 2000-2009, by Object Refinery Limited. * * Original Author: David Gilbert (for Object Refinery Limited); * Contributor(s): Dirk Zeitz; * * $Id: StrokeChooserPanel.java,v 1.8 2009/02/27 13:58:41 mungady Exp $ * * Changes (from 26-Oct-2001) * -------------------------- * 26-Oct-2001 : Changed package to com.jrefinery.ui.*; * 14-Oct-2002 : Fixed errors reported by Checkstyle (DG); * 16-Mar-2004 : Fix for focus problems (DZ); * 27-Feb-2009 : Fixed bug 2612649, NullPointerException (DG); * */
import java.awt.BorderLayout; import java.awt.ruponent; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Insets; import java.awt.RenderingHints; import java.awt.Stroke; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.geom.Ellipse2D; import java.awt.geom.Line2D; import java.awt.geom.Point2D; import javax.swing.DefaultComboBoxModel; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.ListCellRenderer; /**
* A component for choosing a stroke from a list of available strokes. * * @author David Gilbert */
public class StrokeChooserPanel extends JPanel {
/** A combo for selecting the stroke. */ private JComboBox selector; /** * Creates a panel containing a combo-box that allows the user to select * one stroke from a list of available strokes. * * @param current the current stroke sample. * @param available an array of "available" stroke samples. */ public StrokeChooserPanel(StrokeSample current, StrokeSample[] available) { setLayout(new BorderLayout()); // we"ve changed the behaviour here to populate the combo box // with Stroke objects directly - ideally we"d change the signature // of the constructor too...maybe later. DefaultComboBoxModel model = new DefaultComboBoxModel(); for (int i = 0; i < available.length; i++) { model.addElement(available[i].getStroke()); } this.selector = new JComboBox(model); this.selector.setSelectedItem(current.getStroke()); this.selector.setRenderer(new StrokeSample(null)); add(this.selector); // Changes due to focus problems!! DZ this.selector.addActionListener(new ActionListener() { public void actionPerformed(final ActionEvent evt) { getSelector().transferFocus(); } }); }
/**
* Returns the selector component.
*
* @return Returns the selector.
*/
protected final JComboBox getSelector() {
return this.selector;
}
/**
* Returns the selected stroke.
*
* @return The selected stroke (possibly null
).
*/
public Stroke getSelectedStroke() {
return (Stroke) this.selector.getSelectedItem();
}
} /*
* JCommon : a free general purpose class library for the Java(tm) platform * * * (C) Copyright 2000-2009, 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.] * * ----------------- * StrokeSample.java * ----------------- * (C) Copyright 2000-2009, by Object Refinery Limited. * * Original Author: David Gilbert (for Object Refinery Limited); * Contributor(s): -; * * $Id: StrokeSample.java,v 1.5 2009/02/27 13:58:41 mungady Exp $ * * Changes (from 26-Oct-2001) * -------------------------- * 26-Oct-2001 : Changed package to com.jrefinery.ui.*; * 14-Oct-2002 : Fixed errors reported by Checkstyle (DG); * 21-Mar-2003 : Fixed null pointer exception, bug 705126 (DG); * */
/**
* A panel that displays a stroke sample. * * @author David Gilbert */ class StrokeSample extends JComponent implements ListCellRenderer { /** The stroke being displayed (may be null). */ private Stroke stroke; /** The preferred size of the component. */ private Dimension preferredSize; /** * Creates a StrokeSample for the specified stroke. * * @param stroke the sample stroke (null
permitted). */ public StrokeSample(final Stroke stroke) { this.stroke = stroke; this.preferredSize = new Dimension(80, 18); setPreferredSize(this.preferredSize); } /** * Returns the current Stroke object being displayed. * * @return The stroke (possiblynull
). */ public Stroke getStroke() { return this.stroke; } /** * Sets the stroke object being displayed and repaints the component. * * @param stroke the stroke (null
permitted). */ public void setStroke(final Stroke stroke) { this.stroke = stroke; repaint(); } /** * Returns the preferred size of the component. * * @return the preferred size of the component. */ public Dimension getPreferredSize() { return this.preferredSize; } /** * Draws a line using the sample stroke. * * @param g the graphics device. */ public void paintComponent(final Graphics g) { final Graphics2D g2 = (Graphics2D) g; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); final Dimension size = getSize(); final Insets insets = getInsets(); final double xx = insets.left; final double yy = insets.top; final double ww = size.getWidth() - insets.left - insets.right; final double hh = size.getHeight() - insets.top - insets.bottom; // calculate point one final Point2D one = new Point2D.Double(xx + 6, yy + hh / 2); // calculate point two final Point2D two = new Point2D.Double(xx + ww - 6, yy + hh / 2); // draw a circle at point one final Ellipse2D circle1 = new Ellipse2D.Double(one.getX() - 5, one.getY() - 5, 10, 10); final Ellipse2D circle2 = new Ellipse2D.Double(two.getX() - 6, two.getY() - 5, 10, 10); // draw a circle at point two g2.draw(circle1); g2.fill(circle1); g2.draw(circle2); g2.fill(circle2); // draw a line connecting the points final Line2D line = new Line2D.Double(one, two); if (this.stroke != null) { g2.setStroke(this.stroke); g2.draw(line); } } /** * Returns a list cell renderer for the stroke, so the sample can be * displayed in a list or combo. * * @param list the list. * @param value the value. * @param index the index. * @param isSelected selected? * @param cellHasFocus focussed? * * @return the component for rendering. */ public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { if (value instanceof Stroke) { setStroke((Stroke) value); } else { setStroke(null); } return this; }
}
</source>
A dashed stroke
<source lang="java">
import java.awt.BasicStroke; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import javax.swing.JComponent; import javax.swing.JFrame; public class BasicDraw {
public static void main(String[] args) { JFrame frame = new JFrame(); frame.add(new MyComponent()); frame.setSize(300, 300); frame.setVisible(true); }
} class MyComponent extends JComponent {
public void paint(Graphics g) { Graphics2D g2d = (Graphics2D) g; float strokeThickness = 5.0f; float miterLimit = 10f; float[] dashPattern = { 10f }; float dashPhase = 5f; BasicStroke stroke = new BasicStroke(strokeThickness, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, miterLimit, dashPattern, dashPhase); g2d.setStroke(stroke); g2d.draw(new Rectangle(20,20,200,200)); }
}
</source>
Basic stroke
<source lang="java"> import java.awt.BasicStroke; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.JFrame; import javax.swing.JPanel; public class BasicStrokeDemo extends JPanel {
public void init() { setBackground(Color.white); } public void paint(Graphics g) { Graphics2D g2 = (Graphics2D) g; g2.setStroke(new BasicStroke(3.0f)); g2.setPaint(Color.blue); Rectangle r = new Rectangle(5,5,200,200); g2.draw(r); } public static void main(String s[]) { JFrame f = new JFrame(); f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); BasicStrokeDemo p = new BasicStrokeDemo(); f.getContentPane().add("Center", p); p.init(); f.pack(); f.setSize(new Dimension(250, 250)); f.show(); }
}
</source>
Cancel the effects of the zoom on a particular Stroke
<source lang="java"> /*
* Java2DUtils.java * * Created on Aug 30, 2007, 11:40:18 AM * * To change this template, choose Tools | Templates * and open the template in the editor. */
//Revised from jaspersoft ireport designer import java.awt.BasicStroke; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.Shape; import java.awt.Stroke; import java.awt.geom.AffineTransform; import java.util.Stack; /**
* * @author gtoffoli */
public class Java2DUtils {
/** * This function provides a way to cancel the effects of the zoom on a particular Stroke. * All the stroke values (as line width, dashes, etc...) are divided by the zoom factor. * This allow to have essentially a fixed Stroke independent by the zoom. * The returned Stroke is a copy. * Remember to restore the right stroke in the graphics when done. * * It works only with instances of BasicStroke * * zoom is the zoom factor. */ public static Stroke getInvertedZoomedStroke(Stroke stroke, double zoom) { if (stroke == null || !(stroke instanceof BasicStroke )) return stroke; BasicStroke bs = (BasicStroke)stroke; float[] dashArray = bs.getDashArray(); float[] newDashArray = null; if (dashArray != null) { newDashArray = new float[dashArray.length]; for (int i=0; i<newDashArray.length; ++i) { newDashArray[i] = (float)(dashArray[i] / zoom); } } BasicStroke newStroke = new BasicStroke( (float)(bs.getLineWidth() / zoom), bs.getEndCap(), bs.getLineJoin(), bs.getMiterLimit(), //(float)(bs.getMiterLimit() / zoom), newDashArray, (float)(bs.getDashPhase() / zoom) ); return newStroke; }
}
</source>
Changing the Thickness of the Stroking Pen
<source lang="java"> import java.awt.BasicStroke; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import javax.swing.JComponent; import javax.swing.JFrame; public class BasicDraw {
public static void main(String[] args) { new BasicDraw(); } BasicDraw() { JFrame frame = new JFrame(); frame.add(new MyComponent()); frame.setSize(300, 300); frame.setVisible(true); }
} class MyComponent extends JComponent {
public void paint(Graphics g) { Graphics2D g2d = (Graphics2D) g; float strokeThickness = 5.0f; BasicStroke stroke = new BasicStroke(strokeThickness); g2d.setStroke(stroke); g2d.draw(new Rectangle(20,20,200,200)); }
}
</source>
Custom Strokes
<source lang="java"> /*
* Copyright (c) 2000 David Flanagan. All rights reserved. * This code is from the book Java Examples in a Nutshell, 2nd 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. * You may distribute it non-commercially as long as you retain this notice. * For a commercial use license, or to purchase the book (recommended), * visit http://www.davidflanagan.ru/javaexamples2. */
import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.Shape; import java.awt.Stroke; import java.awt.font.GlyphVector; import java.awt.geom.GeneralPath; import java.awt.geom.PathIterator; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.JFrame; import javax.swing.JPanel; /** A demonstration of writing custom Stroke classes */ public class CustomStrokes extends JPanel{
static final int WIDTH = 750, HEIGHT = 200; // Size of our example public String getName() { return "Custom Strokes"; } public int getWidth() { return WIDTH; } public int getHeight() { return HEIGHT; } // These are the various stroke objects we"ll demonstrate Stroke[] strokes = new Stroke[] { new BasicStroke(4.0f), // The standard, // predefined // stroke new NullStroke(), // A Stroke that does nothing new DoubleStroke(8.0f, 2.0f), // A Stroke that strokes twice new ControlPointsStroke(2.0f), // Shows the vertices & control // points new SloppyStroke(2.0f, 3.0f) // Perturbs the shape before stroking }; /** Draw the example */ public void paint(Graphics g1) { Graphics2D g = (Graphics2D)g1; // Get a shape to work with. Here we"ll use the letter B Font f = new Font("Serif", Font.BOLD, 200); GlyphVector gv = f.createGlyphVector(g.getFontRenderContext(), "B"); Shape shape = gv.getOutline(); // Set drawing attributes and starting position g.setColor(Color.black); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.translate(10, 175); // Draw the shape once with each stroke for (int i = 0; i < strokes.length; i++) { g.setStroke(strokes[i]); // set the stroke g.draw(shape); // draw the shape g.translate(140, 0); // move to the right } } public static void main(String[] a) { JFrame f = new JFrame(); f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); f.setContentPane(new CustomStrokes()); f.setSize(750,200); f.setVisible(true); }
} /**
* This Stroke implementation does nothing. Its createStrokedShape() method * returns an unmodified shape. Thus, drawing a shape with this Stroke is the * same as filling that shape! */
class NullStroke implements Stroke {
public Shape createStrokedShape(Shape s) { return s; }
} /**
* This Stroke implementation applies a BasicStroke to a shape twice. If you * draw with this Stroke, then instead of outlining the shape, you"re outlining * the outline of the shape. */
class DoubleStroke implements Stroke {
BasicStroke stroke1, stroke2; // the two strokes to use public DoubleStroke(float width1, float width2) { stroke1 = new BasicStroke(width1); // Constructor arguments specify stroke2 = new BasicStroke(width2); // the line widths for the strokes } public Shape createStrokedShape(Shape s) { // Use the first stroke to create an outline of the shape Shape outline = stroke1.createStrokedShape(s); // Use the second stroke to create an outline of that outline. // It is this outline of the outline that will be filled in return stroke2.createStrokedShape(outline); }
} /**
* This Stroke implementation strokes the shape using a thin line, and also * displays the end points and Bezier curve control points of all the line and * curve segments that make up the shape. The radius argument to the constructor * specifies the size of the control point markers. Note the use of PathIterator * to break the shape down into its segments, and of GeneralPath to build up the * stroked shape. */
class ControlPointsStroke implements Stroke {
float radius; // how big the control point markers should be public ControlPointsStroke(float radius) { this.radius = radius; } public Shape createStrokedShape(Shape shape) { // Start off by stroking the shape with a thin line. Store the // resulting shape in a GeneralPath object so we can add to it. GeneralPath strokedShape = new GeneralPath(new BasicStroke(1.0f) .createStrokedShape(shape)); // Use a PathIterator object to iterate through each of the line and // curve segments of the shape. For each one, mark the endpoint and // control points (if any) by adding a rectangle to the GeneralPath float[] coords = new float[6]; for (PathIterator i = shape.getPathIterator(null); !i.isDone(); i .next()) { int type = i.currentSegment(coords); Shape s = null, s2 = null, s3 = null; switch (type) { case PathIterator.SEG_CUBICTO: markPoint(strokedShape, coords[4], coords[5]); // falls through case PathIterator.SEG_QUADTO: markPoint(strokedShape, coords[2], coords[3]); // falls through case PathIterator.SEG_MOVETO: case PathIterator.SEG_LINETO: markPoint(strokedShape, coords[0], coords[1]); // falls through case PathIterator.SEG_CLOSE: break; } } return strokedShape; } /** Add a small square centered at (x,y) to the specified path */ void markPoint(GeneralPath path, float x, float y) { path.moveTo(x - radius, y - radius); // Begin a new sub-path path.lineTo(x + radius, y - radius); // Add a line segment to it path.lineTo(x + radius, y + radius); // Add a second line segment path.lineTo(x - radius, y + radius); // And a third path.closePath(); // Go back to last moveTo position }
} /**
* This Stroke implementation randomly perturbs the line and curve segments that * make up a Shape, and then strokes that perturbed shape. It uses PathIterator * to loop through the Shape and GeneralPath to build up the modified shape. * Finally, it uses a BasicStroke to stroke the modified shape. The result is a * "sloppy" looking shape. */
class SloppyStroke implements Stroke {
BasicStroke stroke; float sloppiness; public SloppyStroke(float width, float sloppiness) { this.stroke = new BasicStroke(width); // Used to stroke modified shape this.sloppiness = sloppiness; // How sloppy should we be? } public Shape createStrokedShape(Shape shape) { GeneralPath newshape = new GeneralPath(); // Start with an empty shape // Iterate through the specified shape, perturb its coordinates, and // use them to build up the new shape. float[] coords = new float[6]; for (PathIterator i = shape.getPathIterator(null); !i.isDone(); i .next()) { int type = i.currentSegment(coords); switch (type) { case PathIterator.SEG_MOVETO: perturb(coords, 2); newshape.moveTo(coords[0], coords[1]); break; case PathIterator.SEG_LINETO: perturb(coords, 2); newshape.lineTo(coords[0], coords[1]); break; case PathIterator.SEG_QUADTO: perturb(coords, 4); newshape.quadTo(coords[0], coords[1], coords[2], coords[3]); break; case PathIterator.SEG_CUBICTO: perturb(coords, 6); newshape.curveTo(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]); break; case PathIterator.SEG_CLOSE: newshape.closePath(); break; } } // Finally, stroke the perturbed shape and return the result return stroke.createStrokedShape(newshape); } // Randomly modify the specified number of coordinates, by an amount // specified by the sloppiness field. void perturb(float[] coords, int numCoords) { for (int i = 0; i < numCoords; i++) coords[i] += (float) ((Math.random() * 2 - 1.0) * sloppiness); }
}
</source>
Dashed rectangle
<source lang="java"> import java.awt.BasicStroke; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.FontMetrics; import java.awt.GradientPaint; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.geom.Arc2D; import java.awt.geom.Ellipse2D; import java.awt.geom.GeneralPath; import java.awt.geom.Line2D; import java.awt.geom.Rectangle2D; import java.awt.geom.RoundRectangle2D; import javax.swing.JApplet; import javax.swing.JFrame; public class DashedRectangleDemo2D extends JApplet {
final static float dash1[] = { 10.0f }; final static BasicStroke dashed = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f, dash1, 0.0f); public void init() { setBackground(Color.white); setForeground(Color.white); }
public void paint(Graphics g) { Graphics2D g2 = (Graphics2D) g; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setPaint(Color.gray); int x = 5; int y = 7; g2.setStroke(dashed); g2.draw(new RoundRectangle2D.Double(x, y, 200, 200, 10, 10)); g2.drawString("RoundRectangle2D", x, 250); } public static void main(String s[]) { JFrame f = new JFrame(""); f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); JApplet applet = new DashedRectangleDemo2D(); f.getContentPane().add("Center", applet); applet.init(); f.pack(); f.setSize(new Dimension(300, 300)); f.show(); }
}
</source>
Dashed stroke
<source lang="java"> import java.awt.BasicStroke; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.JFrame; import javax.swing.JPanel; public class DashedStrokeDemo extends JPanel {
public void init() { setBackground(Color.white); } public void paint(Graphics g) { Graphics2D g2 = (Graphics2D) g; float dash[] = { 10.0f }; g2.setStroke(new BasicStroke(3.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f, dash, 0.0f)); g2.setPaint(Color.blue); Rectangle r = new Rectangle(5,5,200,200); g2.draw(r); } public static void main(String s[]) { JFrame f = new JFrame(); f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); DashedStrokeDemo p = new DashedStrokeDemo(); f.getContentPane().add("Center", p); p.init(); f.pack(); f.setSize(new Dimension(250, 250)); f.show(); }
}
</source>
Serialises a Stroke object
<source lang="java">
import java.awt.BasicStroke; import java.awt.Stroke; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; /*
* 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.] * * ------------ * IOUtils.java * ------------ * (C)opyright 2002-2004, by Thomas Morgner and Contributors. * * Original Author: Thomas Morgner; * Contributor(s): David Gilbert (for Object Refinery Limited); * * $Id: IOUtils.java,v 1.8 2009/01/22 08:34:58 taqua Exp $ * * Changes * ------- * 26-Jan-2003 : Initial version * 23-Feb-2003 : Documentation * 25-Feb-2003 : Fixed Checkstyle issues (DG); * 29-Apr-2003 : Moved to jcommon * 04-Jan-2004 : Fixed JDK 1.2.2 issues with createRelativeURL; * added support for query strings within these urls (TM); */
public class Main {
/** * Returnstrue
if a class implementsSerializable
* andfalse
otherwise. * * @param c the class. * * @return A boolean. */ public static boolean isSerializable(final Class c) { /** final Class[] interfaces = c.getInterfaces(); for (int i = 0; i < interfaces.length; i++) { if (interfaces[i].equals(Serializable.class)) { return true; } } Class cc = c.getSuperclass(); if (cc != null) { return isSerializable(cc); } */ return (Serializable.class.isAssignableFrom(c)); } /** * Reads aStroke
object that has been serialised by the * {@link SerialUtilities#writeStroke(Stroke, ObjectOutputStream)} method. * * @param stream the input stream (null
not permitted). * * @return The stroke object (possiblynull
). * * @throws IOException if there is an I/O problem. * @throws ClassNotFoundException if there is a problem loading a class. */ public static Stroke readStroke(final ObjectInputStream stream) throws IOException, ClassNotFoundException { if (stream == null) { throw new IllegalArgumentException("Null "stream" argument."); } Stroke result = null; final boolean isNull = stream.readBoolean(); if (!isNull) { final Class c = (Class) stream.readObject(); if (c.equals(BasicStroke.class)) { final float width = stream.readFloat(); final int cap = stream.readInt(); final int join = stream.readInt(); final float miterLimit = stream.readFloat(); final float[] dash = (float[]) stream.readObject(); final float dashPhase = stream.readFloat(); result = new BasicStroke( width, cap, join, miterLimit, dash, dashPhase ); } else { result = (Stroke) stream.readObject(); } } return result; } /** * Serialises aStroke
object. This code handles the *BasicStroke
class which is the onlyStroke
* implementation provided by the JDK (and isn"t directly *Serializable
). * * @param stroke the stroke object (null
permitted). * @param stream the output stream (null
not permitted). * * @throws IOException if there is an I/O error. */ public static void writeStroke(final Stroke stroke, final ObjectOutputStream stream) throws IOException { if (stream == null) { throw new IllegalArgumentException("Null "stream" argument."); } if (stroke != null) { stream.writeBoolean(false); if (stroke instanceof BasicStroke) { final BasicStroke s = (BasicStroke) stroke; stream.writeObject(BasicStroke.class); stream.writeFloat(s.getLineWidth()); stream.writeInt(s.getEndCap()); stream.writeInt(s.getLineJoin()); stream.writeFloat(s.getMiterLimit()); stream.writeObject(s.getDashArray()); stream.writeFloat(s.getDashPhase()); } else { stream.writeObject(stroke.getClass()); stream.writeObject(stroke); } } else { stream.writeBoolean(true); } }
}
</source>
Smokey effect
<source lang="java"> import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.geom.Ellipse2D; import javax.swing.JFrame; import javax.swing.JPanel; public class Overlap extends JPanel {
public static void main(String[] args) { JFrame f = new JFrame(); f.getContentPane().add(new Overlap()); f.setSize(300, 200); f.setVisible(true); } public void paint(Graphics g) { Graphics2D g2 = (Graphics2D) g; double x = 15, y = 50, w = 70, h = 70; Ellipse2D e = new Ellipse2D.Double(x, y, w, h); g2.setStroke(new BasicStroke(8)); Color smokeyColor = new Color(128, 128, 128, 128); g2.setPaint(smokeyColor); g2.fill(e); g2.draw(e); e.setFrame(x + 100, y, w, h); g2.setPaint(Color.black); g2.draw(e); g2.setPaint(Color.gray); g2.fill(e); e.setFrame(x + 200, y, w, h); g2.setPaint(Color.gray); g2.fill(e); g2.setPaint(Color.black); g2.draw(e); }
}
</source>
Stroke with iron effect
<source lang="java"> import java.awt.BasicStroke; import java.awt.Color; import java.awt.GradientPaint; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.geom.Ellipse2D; import javax.swing.JFrame; import javax.swing.JPanel; public class PaintingAndStroking extends JPanel{
public void paint(Graphics g) { Graphics2D g2 = (Graphics2D) g; double x = 15, y = 50, w = 70, h = 70; Ellipse2D e = new Ellipse2D.Double(x, y, w, h); GradientPaint gp = new GradientPaint(75, 75, Color.white, 95, 95, Color.gray, true); // Fill with a gradient. g2.setPaint(gp); g2.fill(e); // Stroke with a solid color. e.setFrame(x + 100, y, w, h); g2.setPaint(Color.black); g2.setStroke(new BasicStroke(8)); g2.draw(e); // Stroke with a gradient. e.setFrame(x + 200, y, w, h); g2.setPaint(gp); g2.draw(e); } public static void main(String[] args) { JFrame f = new JFrame(); f.getContentPane().add(new PaintingAndStroking()); f.setSize(350, 250); f.show(); }
}
</source>
Stroking or Filling with a Texture
<source lang="java"> import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.TexturePaint; import java.awt.image.BufferedImage; import javax.swing.JComponent; import javax.swing.JFrame; public class BasicDraw {
public static void main(String[] args) { JFrame frame = new JFrame(); frame.add(new MyComponent()); frame.setSize(300, 300); frame.setVisible(true); }
} class MyComponent extends JComponent {
public void paint(Graphics g) { Graphics2D g2d = (Graphics2D) g; int x = 10; int y = 10; int width = 50; int height = 25; BufferedImage bi = new BufferedImage(20,20,BufferedImage.TYPE_INT_RGB); TexturePaint texture = new TexturePaint(bi, new Rectangle(x, y, width, height)); g2d.setPaint(texture); }
}
</source>
Thick stroke demo
<source lang="java"> import java.awt.BasicStroke; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.JFrame; import javax.swing.JPanel; public class ThickStrokeDemo extends JPanel {
public void init() { setBackground(Color.white); } public void paint(Graphics g) { Graphics2D g2 = (Graphics2D) g; g2.setStroke(new BasicStroke(8.0f)); g2.setPaint(Color.blue); Rectangle r = new Rectangle(5,5,200,200); g2.draw(r); } public static void main(String s[]) { JFrame f = new JFrame(); f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); ThickStrokeDemo p = new ThickStrokeDemo(); f.getContentPane().add("Center", p); p.init(); f.pack(); f.setSize(new Dimension(250, 250)); f.show(); }
}
</source>
Tries to deduct the stroke-type from the given stroke object.
<source lang="java"> /**
* * JFreeReport : a free Java reporting library * * * Project Info: http://reporting.pentaho.org/ * * (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors. * * 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. * * [Java is a trademark or registered trademark of Sun Microsystems, Inc. * in the United States and other countries.] * * ------------ * StrokeUtility.java * ------------ * (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors. */
import java.awt.BasicStroke; import java.awt.Stroke; import java.util.Arrays; /**
* This class provides helper methods to work with Strokes and line-styles. * * @author Thomas Morgner */
public class StrokeUtility {
/** A constant defining a stroke-type. */ public static final int STROKE_SOLID = 0; /** A constant defining a stroke-type. */ public static final int STROKE_DASHED = 1; /** A constant defining a stroke-type. */ public static final int STROKE_DOTTED = 2; /** A constant defining a stroke-type. */ public static final int STROKE_DOT_DASH = 3; /** A constant defining a stroke-type. */ public static final int STROKE_DOT_DOT_DASH = 4; /** A constant defining a stroke-type. */ public static final int STROKE_NONE = 5; /** * Default Constructor. Private to prevent Object-creation. */ private StrokeUtility() { } /** * Creates a new Stroke-Object for the given type and with. * * @param type * the stroke-type. (Must be one of the constants defined in this * class.) * @param width * the stroke"s width. * @return the stroke, never null. */ public static Stroke createStroke(final int type, final float width) { final boolean useWidthForStrokes = true; final float effectiveWidth; if (useWidthForStrokes) { effectiveWidth = width; } else { effectiveWidth = 1; } switch (type) { case STROKE_DASHED: return new BasicStroke(width, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10.0f, new float[] { 6 * effectiveWidth, 6 * effectiveWidth }, 0.0f); case STROKE_DOTTED: return new BasicStroke(width, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 5.0f, new float[] { 0.0f, 2 * effectiveWidth }, 0.0f); case STROKE_DOT_DASH: return new BasicStroke(width, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10.0f, new float[] { 0, 2 * effectiveWidth, 6 * effectiveWidth, 2 * effectiveWidth }, 0.0f); case STROKE_DOT_DOT_DASH: return new BasicStroke(width, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10.0f, new float[] { 0, 2 * effectiveWidth, 0, 2 * effectiveWidth, 6 * effectiveWidth, 2 * effectiveWidth }, 0.0f); default: return new BasicStroke(width); } } /** * Tries to extract the stroke-width from the given stroke object. * * @param s * the stroke. * @return the stroke"s width. */ public static float getStrokeWidth(final Stroke s) { if (s instanceof BasicStroke) { final BasicStroke bs = (BasicStroke) s; return bs.getLineWidth(); } return 1; } /** * Tries to deduct the stroke-type from the given stroke object. This will * result in funny return values if the stroke was not created by the * {@link #createStroke(int, float)} method. * * @param s * the stroke. * @return the stroke"s width. */ public static int getStrokeType(final Stroke s) { if (s instanceof BasicStroke == false) { return STROKE_SOLID; } final BasicStroke bs = (BasicStroke) s; if (bs.getLineWidth() <= 0) { return STROKE_NONE; } final float[] dashes = bs.getDashArray(); if (dashes == null) { return STROKE_SOLID; } if (dashes.length < 2) { return STROKE_SOLID; } if (dashes.length == 3 || dashes.length == 5) { return STROKE_SOLID; } if (dashes.length == 2) { // maybe dashed or dotted ... // if (dashes[0] < 2 && dashes[1] < 2) { // return STROKE_DOTTED; // } final float factor = dashes[0] / dashes[1]; if (factor > 0.9 && factor < 1.1) { return STROKE_DASHED; } else if (factor < 0.1) { return STROKE_DOTTED; } // else ... not recognized ... return STROKE_SOLID; } else if (dashes.length == 4) { // maybe a dot-dashed stroke ... final float[] copyDashes = (float[]) dashes.clone(); Arrays.sort(copyDashes); // the first value should be near zero .. if (Math.abs(copyDashes[0] / bs.getLineWidth()) > 0.5) { // not recognized .. return STROKE_SOLID; } // test that the first two values have the same size final float factor1 = (2 * bs.getLineWidth()) / copyDashes[1]; final float factor2 = (2 * bs.getLineWidth()) / copyDashes[2]; final float factorBig = (2 * bs.getLineWidth()) / copyDashes[3]; if ((factor1 < 0.9 || factor1 > 1.1) || (factor2 < 0.9 || factor2 > 1.1)) { // not recognized ... return STROKE_SOLID; } if (factorBig < 0.4 || factorBig > 2.5) { return STROKE_DOT_DASH; } if (factorBig < 0.9 || factorBig > 1.1) { return STROKE_DOTTED; } return STROKE_DASHED; } else if (dashes.length == 6) { // maybe a dot-dashed stroke ... final float[] copyDashes = (float[]) dashes.clone(); Arrays.sort(copyDashes); // test that the first three values have the same size // the first two values should be near zero .. if (Math.abs(copyDashes[0] / bs.getLineWidth()) > 0.5) { // not recognized .. return STROKE_SOLID; } if (Math.abs(copyDashes[1] / bs.getLineWidth()) > 0.5) { // not recognized .. return STROKE_SOLID; } final float factor2 = (2 * bs.getLineWidth()) / copyDashes[2]; final float factor3 = (2 * bs.getLineWidth()) / copyDashes[3]; final float factor4 = (2 * bs.getLineWidth()) / copyDashes[4]; final float factorBig = (2 * bs.getLineWidth()) / copyDashes[5]; if ((factor2 < 0.9 || factor2 > 1.1) || (factor3 < 0.9 || factor3 > 1.1) || (factor4 < 0.9 || factor4 > 1.1)) { return STROKE_SOLID; } if (factorBig < 0.4 || factorBig > 2.5) { return STROKE_DOT_DOT_DASH; } if ((factorBig < 0.9 || factorBig > 1.1)) { return STROKE_DOTTED; } return STROKE_DASHED; } // not recognized ... return STROKE_SOLID; }
}
</source>
Tries to extract the stroke-width from the given stroke object.
<source lang="java"> /**
* * JFreeReport : a free Java reporting library * * * Project Info: http://reporting.pentaho.org/ * * (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors. * * 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. * * [Java is a trademark or registered trademark of Sun Microsystems, Inc. * in the United States and other countries.] * * ------------ * StrokeUtility.java * ------------ * (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors. */
import java.awt.BasicStroke; import java.awt.Stroke; import java.util.Arrays; /**
* This class provides helper methods to work with Strokes and line-styles. * * @author Thomas Morgner */
public class StrokeUtility {
/** A constant defining a stroke-type. */ public static final int STROKE_SOLID = 0; /** A constant defining a stroke-type. */ public static final int STROKE_DASHED = 1; /** A constant defining a stroke-type. */ public static final int STROKE_DOTTED = 2; /** A constant defining a stroke-type. */ public static final int STROKE_DOT_DASH = 3; /** A constant defining a stroke-type. */ public static final int STROKE_DOT_DOT_DASH = 4; /** A constant defining a stroke-type. */ public static final int STROKE_NONE = 5; /** * Default Constructor. Private to prevent Object-creation. */ private StrokeUtility() { } /** * Creates a new Stroke-Object for the given type and with. * * @param type * the stroke-type. (Must be one of the constants defined in this * class.) * @param width * the stroke"s width. * @return the stroke, never null. */ public static Stroke createStroke(final int type, final float width) { final boolean useWidthForStrokes = true; final float effectiveWidth; if (useWidthForStrokes) { effectiveWidth = width; } else { effectiveWidth = 1; } switch (type) { case STROKE_DASHED: return new BasicStroke(width, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10.0f, new float[] { 6 * effectiveWidth, 6 * effectiveWidth }, 0.0f); case STROKE_DOTTED: return new BasicStroke(width, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 5.0f, new float[] { 0.0f, 2 * effectiveWidth }, 0.0f); case STROKE_DOT_DASH: return new BasicStroke(width, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10.0f, new float[] { 0, 2 * effectiveWidth, 6 * effectiveWidth, 2 * effectiveWidth }, 0.0f); case STROKE_DOT_DOT_DASH: return new BasicStroke(width, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10.0f, new float[] { 0, 2 * effectiveWidth, 0, 2 * effectiveWidth, 6 * effectiveWidth, 2 * effectiveWidth }, 0.0f); default: return new BasicStroke(width); } } /** * Tries to extract the stroke-width from the given stroke object. * * @param s * the stroke. * @return the stroke"s width. */ public static float getStrokeWidth(final Stroke s) { if (s instanceof BasicStroke) { final BasicStroke bs = (BasicStroke) s; return bs.getLineWidth(); } return 1; } /** * Tries to deduct the stroke-type from the given stroke object. This will * result in funny return values if the stroke was not created by the * {@link #createStroke(int, float)} method. * * @param s * the stroke. * @return the stroke"s width. */ public static int getStrokeType(final Stroke s) { if (s instanceof BasicStroke == false) { return STROKE_SOLID; } final BasicStroke bs = (BasicStroke) s; if (bs.getLineWidth() <= 0) { return STROKE_NONE; } final float[] dashes = bs.getDashArray(); if (dashes == null) { return STROKE_SOLID; } if (dashes.length < 2) { return STROKE_SOLID; } if (dashes.length == 3 || dashes.length == 5) { return STROKE_SOLID; } if (dashes.length == 2) { // maybe dashed or dotted ... // if (dashes[0] < 2 && dashes[1] < 2) { // return STROKE_DOTTED; // } final float factor = dashes[0] / dashes[1]; if (factor > 0.9 && factor < 1.1) { return STROKE_DASHED; } else if (factor < 0.1) { return STROKE_DOTTED; } // else ... not recognized ... return STROKE_SOLID; } else if (dashes.length == 4) { // maybe a dot-dashed stroke ... final float[] copyDashes = (float[]) dashes.clone(); Arrays.sort(copyDashes); // the first value should be near zero .. if (Math.abs(copyDashes[0] / bs.getLineWidth()) > 0.5) { // not recognized .. return STROKE_SOLID; } // test that the first two values have the same size final float factor1 = (2 * bs.getLineWidth()) / copyDashes[1]; final float factor2 = (2 * bs.getLineWidth()) / copyDashes[2]; final float factorBig = (2 * bs.getLineWidth()) / copyDashes[3]; if ((factor1 < 0.9 || factor1 > 1.1) || (factor2 < 0.9 || factor2 > 1.1)) { // not recognized ... return STROKE_SOLID; } if (factorBig < 0.4 || factorBig > 2.5) { return STROKE_DOT_DASH; } if (factorBig < 0.9 || factorBig > 1.1) { return STROKE_DOTTED; } return STROKE_DASHED; } else if (dashes.length == 6) { // maybe a dot-dashed stroke ... final float[] copyDashes = (float[]) dashes.clone(); Arrays.sort(copyDashes); // test that the first three values have the same size // the first two values should be near zero .. if (Math.abs(copyDashes[0] / bs.getLineWidth()) > 0.5) { // not recognized .. return STROKE_SOLID; } if (Math.abs(copyDashes[1] / bs.getLineWidth()) > 0.5) { // not recognized .. return STROKE_SOLID; } final float factor2 = (2 * bs.getLineWidth()) / copyDashes[2]; final float factor3 = (2 * bs.getLineWidth()) / copyDashes[3]; final float factor4 = (2 * bs.getLineWidth()) / copyDashes[4]; final float factorBig = (2 * bs.getLineWidth()) / copyDashes[5]; if ((factor2 < 0.9 || factor2 > 1.1) || (factor3 < 0.9 || factor3 > 1.1) || (factor4 < 0.9 || factor4 > 1.1)) { return STROKE_SOLID; } if (factorBig < 0.4 || factorBig > 2.5) { return STROKE_DOT_DOT_DASH; } if ((factorBig < 0.9 || factorBig > 1.1)) { return STROKE_DOTTED; } return STROKE_DASHED; } // not recognized ... return STROKE_SOLID; }
}
</source>