Reputation: 53
So basically I need to make shapes put of asterisks as shown in this picture:
So this is my current solution.
import java.applet.Applet;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Stroke;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ThreePointTen extends Applet{
public void init(String[] a) {
}
public void paint(Graphics g){
char a = '*';
//square
g.drawString("**********", 25, 25);
g.drawString("* *", 25, 35);
g.drawString("* *", 25, 45);
g.drawString("* *", 25, 55);
g.drawString("* *", 25, 65);
g.drawString("* *", 25, 75);
g.drawString("* *", 25, 85);
g.drawString("* *", 25, 95);
g.drawString("**********", 25, 105);
//oval
g.drawString("***", 175, 25);
g.drawString("* * ", 165, 35);
g.drawString("* * ", 158, 45);
g.drawString("* * ", 158, 55);
g.drawString("* * ", 158, 65);
g.drawString("* * ", 158, 75);
g.drawString("* * ", 158, 85);
g.drawString("* * ", 165, 95);
g.drawString("***", 175, 105);
}
}
I'm basically just guessing how to make each shape and where they go. This method is extremely slow and inefficient. I was wondering if it was possible to make a shape using g.draw and then some how out line it with a character.
Upvotes: 0
Views: 2124
Reputation: 324157
For a basic implementation you need to create a "bitmap" of the pixels that you want painted. So you create a simple picture of your shapes and then create a little algorithm to paint each "x" in your shape.
Something like:
import java.awt.*;
import java.awt.event.*;
//import java.awt.image.*;
//import java.util.*;
import java.util.List;
import java.util.ArrayList;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
//import java.beans.*;
import javax.swing.border.*;
//import javax.swing.plaf.*;
//import javax.swing.text.*;
//import javax.swing.table.*;
//import java.io.*;
//import javax.imageio.*;
//import java.awt.geom.*;
public class PaintShape extends JPanel
{
private final static String[] SQUARE =
{
"xxxxxxxxx",
"x x",
"x x",
"x x",
"x x",
"x x",
"x x",
"x x",
"xxxxxxxxx"
};
private final static String[] ARROW =
{
" x ",
" xxx ",
" xxxxx ",
" x ",
" x ",
" x ",
" x ",
" x ",
" x "
};
private ArrayList<String[]> shapes = new ArrayList<String[]>();
private String outlineCharacter = "*";
public void addShape(String[] shape)
{
this.shapes.add( shape );
}
public void setOutlineCharacter(String outlineCharacter)
{
this.outlineCharacter = outlineCharacter;
}
@Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
int outlineCharacterWidth = 10;
int lineHeight = 10;
int shapeStart = 0;
int x = shapeStart;
int y = 0;
for (String[] shape: shapes)
{
y = lineHeight;
for (int row = 0; row < shape.length; row++)
{
String bitmap = shape[row];
x = shapeStart;
for (int column = 0; column < bitmap.length(); column++)
{
if (bitmap.charAt(column) == 'x')
{
g.drawString(outlineCharacter, x, y);
}
x += outlineCharacterWidth;
}
y += lineHeight;
}
x += 20; // gap between shapes
shapeStart = x;
}
}
private static void createAndShowGUI()
{
PaintShape paint = new PaintShape();
paint.addShape(PaintShape.SQUARE);
paint.addShape(PaintShape.ARROW);
paint.addShape(PaintShape.SQUARE);
JFrame frame = new JFrame("PaintShape");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(paint);
frame.setLocationByPlatform( true );
frame.setSize(200, 200);
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
}
Upvotes: 0
Reputation: 54679
You can create a special Stroke
that internally consists of these asterisks/stars. Then, you can use stroke.createStrokedShape(shape)
to create a new shape that represents another shape, painted with this stroke.
There is an (Apache-Licensed) implementation of such a stroke at http://www.jhlabs.com/java/java2d/strokes/ (also included in the code below, with link and copyright infos)
Thre result may look like this:
as created with the following standalone example:
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.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
import java.awt.geom.FlatteningPathIterator;
import java.awt.geom.GeneralPath;
import java.awt.geom.PathIterator;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class StarShapes
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
createAndShowGUI();
}
});
}
private static void createAndShowGUI()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(new StarShapesPanel());
f.setSize(600,400);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
class StarShapesPanel extends JPanel
{
@Override
protected void paintComponent(Graphics gr)
{
super.paintComponent(gr);
Graphics2D g = (Graphics2D)gr;
g.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
Font starFont = new Font("Monospaced", Font.BOLD, 20);
Shape starShape = createShape(starFont, "*");
Stroke stroke = new ShapeStroke(new Shape[] { starShape }, 12.0f);
Font textFont = new Font("Serif", Font.PLAIN, 250);
Shape textShape = createShape(textFont, "Stars!");
g.translate(10, 250);
Shape strokedTextShape =
stroke.createStrokedShape(textShape);
g.fill(strokedTextShape);
}
private static Shape createShape(Font font, String s)
{
FontRenderContext fontRenderContext =
new FontRenderContext(null,true,true);
GlyphVector glyphVector =
font.createGlyphVector(fontRenderContext, s);
return glyphVector.getOutline();
}
}
//============================================================================
// From http://www.jhlabs.com/java/java2d/strokes/
/*
Copyright 2006 Jerry Huxtable
Licensed under the Apache License, Version 2.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://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
class ShapeStroke implements Stroke {
private Shape shapes[];
private float advance;
private boolean stretchToFit = false;
private boolean repeat = true;
private AffineTransform t = new AffineTransform();
private static final float FLATNESS = 1;
public ShapeStroke( Shape shapes, float advance ) {
this( new Shape[] { shapes }, advance );
}
public ShapeStroke( Shape shapes[], float advance ) {
this.advance = advance;
this.shapes = new Shape[shapes.length];
for ( int i = 0; i < this.shapes.length; i++ ) {
Rectangle2D bounds = shapes[i].getBounds2D();
t.setToTranslation( -bounds.getCenterX(), -bounds.getCenterY() );
this.shapes[i] = t.createTransformedShape( shapes[i] );
}
}
public Shape createStrokedShape( Shape shape ) {
GeneralPath result = new GeneralPath();
PathIterator it = new FlatteningPathIterator( shape.getPathIterator( null ), FLATNESS );
float points[] = new float[6];
float moveX = 0, moveY = 0;
float lastX = 0, lastY = 0;
float thisX = 0, thisY = 0;
int type = 0;
boolean first = false;
float next = 0;
int currentShape = 0;
int length = shapes.length;
float factor = 1;
while ( currentShape < length && !it.isDone() ) {
type = it.currentSegment( points );
switch( type ){
case PathIterator.SEG_MOVETO:
moveX = lastX = points[0];
moveY = lastY = points[1];
result.moveTo( moveX, moveY );
first = true;
next = 0;
break;
case PathIterator.SEG_CLOSE:
points[0] = moveX;
points[1] = moveY;
// Fall into....
case PathIterator.SEG_LINETO:
thisX = points[0];
thisY = points[1];
float dx = thisX-lastX;
float dy = thisY-lastY;
float distance = (float)Math.sqrt( dx*dx + dy*dy );
if ( distance >= next ) {
float r = 1.0f/distance;
float angle = (float)Math.atan2( dy, dx );
while ( currentShape < length && distance >= next ) {
float x = lastX + next*dx*r;
float y = lastY + next*dy*r;
t.setToTranslation( x, y );
t.rotate( angle );
result.append( t.createTransformedShape( shapes[currentShape] ), false );
next += advance;
currentShape++;
if ( repeat )
currentShape %= length;
}
}
next -= distance;
first = false;
lastX = thisX;
lastY = thisY;
break;
}
it.next();
}
return result;
}
}
Upvotes: 3