I was working on an issue where I was getting a cast problem trying to cast from Shape to Area (see previous post cast exception question). Now it seems that my shape that is create is not getting created correctly. Instead of posting all of my source code here I am attaching a link to all the source files here.
Essentially I create the shape as follows with a standard call of
YingYang shape = new YingYang();
shape = shape.moveTo(x, y);
shape = shape.scaleBy(size);
shape.setColor(getNextColor());
and the calls to the Area Class are:
public YingYang()
{
Area mainCircle = new Area(new Ellipse2D.Double(...)
...
yingYang.add(mainCircle);
}
The MoveTo call:
public YingYang moveTo(double x, double y)
{
at.translate(x, y);
at.setToTranslation(x, y);
yingYang.transform(at);
return new YingYang(at.createTransformedShape(yingYang));
}
The ScaleBy:
public YingYang scaleBy(double scale)
{
double cx = this.getBounds2D().getCenterX();
double cy = this.getBounds2D().getCenterY();
at.translate(cx, cy);
at.setToTranslation(cx, cy);
at.scale(scale, scale);
at.translate(-cx, -cy);
return new YingYang(at.createTransformedShape(yingYang));
}
When I call the paintComponent() in my drawing panel:
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
for(YingYang s : shapes)
{
System.out.println(s.getBounds2D());
g2.setColor(s.getColor());
g2.fill(s);
}
}
The print statement prints out:
java.awt.geom.Rectangle2D$Double[x=0.0,y=0.0,w=0.0,h=0.0]
I'm at a loss... Any Ideas?
It looks like you have combined both my recommendations into one piece of code. If you are going to use your variable yingYang then you should implement the shape on the class. However if you are going to extend the area you need to remove the yingYang variable and use the class as the area eg: yingYang.add(mainCircle); becomes add(mainCircle);... essentially remove all references of the yingYang variable.
So instead of the "yingYang" variable you are using "this". heres is a modified version of your YingYang class with the references removed.
import java.awt.Color;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
public class YingYang extends Area
{
AffineTransform at = new AffineTransform();
private boolean movingRight = true;
private boolean movingUp = true;
private Color color = Color.BLACK;
private int dx = 10, dy = 10;
public YingYang(Shape shape)
{
super(shape);
}
public YingYang()
{
// Construct the Outer Circle & Lower Dot
Area mainCircle = new Area(new Ellipse2D.Double(-210, -210, 420, 420));
Area lowerDot = new Area(new Ellipse2D.Double(-10, 90, 40, 40));
mainCircle.subtract(lowerDot);
// Begin Construction of the whit side of symbol
Area whiteSide = new Area(new Ellipse2D.Double(-200, -200, 400, 400));
Area rect = new Area(new Rectangle2D.Double(0, -200, 200, 400));
whiteSide.subtract(rect);
// Construct the upper white Circle
Area upperCircle = new Area(new Ellipse2D.Double(-100, -200, 200, 200));
whiteSide.add(upperCircle);
// Construct the Upper Dot
Area upperDot = new Area(new Ellipse2D.Double(-10, -110, 40, 40));
whiteSide.subtract(upperDot);
// Remove the lower circle portion
Area lowerCircle = new Area(new Ellipse2D.Double(-100, 0, 200, 200));
whiteSide.subtract(lowerCircle);
// Add Main Circle
add(mainCircle);
// Subtract the white side
subtract(whiteSide);
}
//------------------------ Methods -----------------------------------------
/**
* Sets this shapes color
* (must call getColor before drawing this shape)
* #param color
*/
public void setColor(Color color)
{
this.color = color;
}
/**
* Gets this shapes current color
* #return color
*/
public Color getColor()
{
return this.color;
}
/**
* Determines if the shape is moving left to right
* #return - boolean
*/
public boolean isMovingRight()
{
return movingRight;
}
/**
* Determines if the shape is moving from down to up
* #return - boolean
*/
public boolean isMovingUp()
{
return movingUp;
}
/**
* Changes the Horizontal Path that this shape is traveling
*/
public void changeHorizonalMovement()
{
if(isMovingRight())
{
movingRight = false;
}
else
{
movingRight = true;
}
}
/**
* Changes the Vertical Path that this shape is traveling
*/
public void changeVerticalMovement()
{
if(isMovingUp())
{
movingUp = false;
}
else
{
movingUp = true;
}
}
/**
* Sets the direction of the Horizontal Path of this shape
* true = left to right : false = right to left
* #param dir - boolean
*/
public void setHorizonalMovement(boolean dir)
{
this.movingRight = dir;
}
/**
* Sets the direction of the Vertical Path of this shape
* true = down to up : false = up to down
* #param dir - boolean
*/
public void setVerticalMovement(boolean dir){
this.movingUp = dir;
}
/**
* Moves the current shape by the amount x,y
* #param x - double
* #param y - double
*/
public YingYang moveTo(double x, double y)
{
at.translate(x, y);
at.setToTranslation(x, y);
transform(at);
return new YingYang(at.createTransformedShape(this));
}
/**
* Rotate this shape
* #param theta - amount to rotate shape by
* #return
*/
public YingYang rotate(double theta)
{
double cx = getBounds2D().getCenterX();
double cy = getBounds2D().getCenterY();
at.translate(cx, cy);
at.setToTranslation(cx, cy);
at.rotate(Math.toRadians(theta));
at.translate(-cx, -cy);
return new YingYang(at.createTransformedShape(this));
}
public YingYang moveToAndRotate(double x, double y, double theta)
{
double cx = getBounds2D().getCenterX();
double cy = getBounds2D().getCenterY();
at.translate(cx, cy);
at.setToTranslation(cx, cy);
at.translate(x, y);
at.rotate(Math.toRadians(theta));
at.translate(-cx, -cy);
return new YingYang(at.createTransformedShape(this));
}
/**
* Scales this shape uniformly by the amount of scale
* about the origin
* #param scale - double
*/
public YingYang scaleBy(double scale)
{
double cx = this.getBounds2D().getCenterX();
double cy = this.getBounds2D().getCenterY();
at.translate(cx, cy);
at.setToTranslation(cx, cy);
at.scale(scale, scale);
at.translate(-cx, -cy);
return new YingYang(at.createTransformedShape(this));
}
/**
* Rotates this shape theta degrees about the origin
*/
public YingYang rotate(Double theta)
{
double cx = this.getBounds2D().getCenterX();
double cy = this.getBounds2D().getCenterY();
at.translate(cx, cy);
at.setToTranslation(cx, cy);
at.rotate(Math.toRadians(theta));
at.translate(-cx, -cy);
return new YingYang(at.createTransformedShape(this));
}
public int getDx()
{
return this.dx;
}
public void setDx(int x)
{
this.dx = x;
}
public int getDy()
{
return this.dy;
}
public void setDy(int y)
{
this.dy = y;
}
}
Related
I made a this test program for a project im working on. It draws a car, and moves it across the JFrame from left to right. What I am trying to do is make it so once the car object has completely passed the other side of the frame it will loop back on the other side. I think I have to use an outside loop for the timer in the main class called animationTester but Im not entirely sure what I want to put in the loop. Also Ive been told that I cannot hard code the size of the window into the program. anyway here are my classes.
ShapeIcon class
import java.awt.*;
import java.util.*;
import javax.swing.*;
/**
An icon that contains a moveable shape.
*/
public class ShapeIcon implements Icon
{
private int width;
private int height;
private MoveableShape shape;
public ShapeIcon(MoveableShape shape,
int width, int height)
{
this.shape = shape;
this.width = width;
this.height = height;
}
public int getIconWidth()
{
return width;
}
public int getIconHeight()
{
return height;
}
public void paintIcon(Component c, Graphics g, int x, int y)
{
Graphics2D g2 = (Graphics2D) g;
shape.draw(g2); // has draw method since it implements MoveableShape
}
}
CarShape Class
import java.awt.*;
import java.awt.geom.*;
import java.util.*;
/**
A car that can be moved around.
*/
public class CarShape implements MoveableShape
{
private int x;
private int y;
private int width;
/**
Constructs a car item.
#param x the left of the bounding rectangle
#param y the top of the bounding rectangle
#param width the width of the bounding rectangle
*/
public CarShape(int x, int y, int width)
{
this.x = x;
this.y = y;
this.width = width;
}
public void translate(int dx, int dy)
{
x += dx;
y += dy;
}
public void draw(Graphics2D g2)
{
Rectangle2D.Double body
= new Rectangle2D.Double(x, y + width / 6,
width - 1, width / 6);
Ellipse2D.Double frontTire
= new Ellipse2D.Double(x + width / 6, y + width / 3,
width / 6, width / 6);
Ellipse2D.Double rearTire
= new Ellipse2D.Double(x + width * 2 / 3, y + width / 3,
width / 6, width / 6);
// The bottom of the front windshield
Point2D.Double r1
= new Point2D.Double(x + width / 6, y + width / 6);
// The front of the roof
Point2D.Double r2
= new Point2D.Double(x + width / 3, y);
// The rear of the roof
Point2D.Double r3
= new Point2D.Double(x + width * 2 / 3, y);
// The bottom of the rear windshield
Point2D.Double r4
= new Point2D.Double(x + width * 5 / 6, y + width / 6);
Line2D.Double frontWindshield
= new Line2D.Double(r1, r2);
Line2D.Double roofTop
= new Line2D.Double(r2, r3);
Line2D.Double rearWindshield
= new Line2D.Double(r3, r4);
g2.draw(body);
g2.draw(frontTire);
g2.draw(rearTire);
g2.draw(frontWindshield);
g2.draw(roofTop);
g2.draw(rearWindshield);
}
}
MoveableShape class
import java.awt.*;
/**
A shape that can be moved around.
*/
public interface MoveableShape
{
/**
Draws the shape.
#param g2 the graphics context
*/
void draw(Graphics2D g2);
/**
Moves the shape by a given amount.
#param dx the amount to translate in x-direction
#param dy the amount to translate in y-direction
*/
void translate(int dx, int dy);
}
Main class
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/**
This program implements an animation that moves
a car shape.
*/
public class AnimationTester
{
private static final int ICON_WIDTH = 400;
private static final int ICON_HEIGHT = 100;
private static final int CAR_WIDTH = 100;
public static void main(String[] args)
{
JFrame frame = new JFrame();
final MoveableShape shape
= new CarShape(0, 0, CAR_WIDTH);
ShapeIcon icon = new ShapeIcon(shape,
ICON_WIDTH, ICON_HEIGHT);
final JLabel label = new JLabel(icon);
frame.setLayout(new FlowLayout());
frame.add(label);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
final int DELAY = 100;
// Milliseconds between timer ticks
Timer t = new Timer(DELAY, new
ActionListener()
{
public void actionPerformed(ActionEvent event)
{
shape.translate(1, 0);
label.repaint();
}
});
t.start();
}
}
You may modify translate method to allow an end parameter, so the car start again when it gets to the end of the frame:
public void translate(int dx, int dy, int end) {
x += dx;
y += dy;
if (end == x) {
x = -100;
}
}
Then pass the frame.getWidth() to the translate call on AnimationTester.class:
Timer t = new Timer(DELAY, new ActionListener() {
public void actionPerformed(ActionEvent event) {
car.translate(1, 0, frame.getWidth());
label.repaint();
}
});
I hope it helps :)
I have a Canvas.java class where I have a mousemove code to track the mouse position, and have it saved to an array. If I print this code out from this class itself, the mouse position is correctly printed. However, is there any way I can access this array from another class, and have it printed still (eg. I want it to appear as a Vaadin label in MainLayout.java)? It seems that the label is only showing '[]' in place of the coordinates I want printed.
Canvas.java:
package com.vaadin.starter.beveragebuddy.ui.components;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.HasSize;
import com.vaadin.flow.component.HasStyle;
import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.dom.Element;
import com.vaadin.flow.dom.ElementFactory;
import elemental.json.JsonObject;
import java.util.ArrayList;
/**
* Canvas component that you can draw shapes and images on. It's a Java wrapper
* for the
* <a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API">HTML5
* canvas</a>.
* <p>
* Use {#link #getContext()} to get API for rendering shapes and images on the
* canvas.
* <p>
*/
#Tag("canvas")
#SuppressWarnings("serial")
public class Canvas extends Component implements HasStyle, HasSize {
private CanvasRenderingContext2D context;
private Element element;
private boolean isDrawing = false;
private boolean mouseIsDown = false;
private double endX;
private double endY;
public static ArrayList <BoundingBox> arrayBoxes = new ArrayList<BoundingBox>();
public static ArrayList <MousePosition> mousePosArray = new ArrayList<MousePosition>();
public static ArrayList<BoundingBox> getArrayBoxes() {
return arrayBoxes;
}
public static ArrayList<MousePosition> getMousePosArray() {
return mousePosArray;
}
public static void setMousePosArray(ArrayList<MousePosition> mousePosArray) {
Canvas.mousePosArray = mousePosArray;
}
/**
* Creates a new canvas component with the given size.
* <p>
* Use the API provided by {#link #getContext()} to render graphics on the
* canvas.
* <p>
* The width and height parameters will be used for the canvas' coordinate
* system. They will determine the size of the component in pixels, unless
* you explicitly set the component's size with {#link #setWidth(String)} or
* {#link #setHeight(String)}.
*
* #param width
* the width of the canvas
* #param height
* the height of the canvas
*/
public Canvas(int width, int height) {
context = new CanvasRenderingContext2D(this);
element = getElement();
element.getStyle().set("border", "1px solid");
getElement().setAttribute("width", String.valueOf(width));
getElement().setAttribute("height", String.valueOf(height));
element.addEventListener("mousedown", event -> { // Retrieve Starting Position on MouseDown
Element boundingBoxResult = ElementFactory.createDiv();
element.appendChild(boundingBoxResult);
JsonObject evtData = event.getEventData();
double xBox = evtData.getNumber("event.x");
double yBox = evtData.getNumber("event.y");
boundingBoxResult.setAttribute("data-x", String.format("%f", xBox));
boundingBoxResult.setAttribute("data-y", String.format("%f", yBox));
BoundingBox newBox = new BoundingBox(0, xBox, yBox, 0.0, 0.0);
arrayBoxes.add(newBox);
isDrawing = true;
mouseIsDown=true;
}).addEventData("event.x").addEventData("event.y");
element.addEventListener("mouseup", event -> { // Draw Box on MouseUp
Element boundingBoxResult2 = ElementFactory.createDiv();
element.appendChild(boundingBoxResult2);
JsonObject evtData2 = event.getEventData();
endX = evtData2.getNumber("event.x");
endY = evtData2.getNumber("event.y");
boundingBoxResult2.setAttribute("end-x", String.format("%f", endX));
boundingBoxResult2.setAttribute("end-y", String.format("%f", endY));
double xcoordi = 0;
double ycoordi = 0;
double boxWidth = 0;
double boxHeight = 0;
for (int i = 0; i < arrayBoxes.size(); i++) {
arrayBoxes.get(i).setName(i + 1);
arrayBoxes.get(i).setWidth(endX, arrayBoxes.get(i).xcoordi);
arrayBoxes.get(i).setHeight(endY, arrayBoxes.get(i).ycoordi);
xcoordi = arrayBoxes.get(i).getXcoordi();
ycoordi = arrayBoxes.get(i).getYcoordi();
boxWidth = arrayBoxes.get(i).getWidth();
boxHeight = arrayBoxes.get(i).getHeight();
}
mouseIsDown=false;
context.beginPath();
context.setFillStyle("limegreen");
context.setLineWidth(2);
context.strokeRect(xcoordi, ycoordi, boxWidth, boxHeight);
context.fill();
System.out.println(arrayBoxes.toString());
}).addEventData("event.x").addEventData("event.y");
element.addEventListener("mousemove", event -> { // Retrieve Mouse Position when Moving
JsonObject mousePos = event.getEventData();
double mouseX = mousePos.getNumber("event.x");
double mouseY = mousePos.getNumber("event.y");
MousePosition currentPos = new MousePosition(mouseX, mouseY);
mousePosArray.add(0, currentPos);
setMousePosArray(mousePosArray);
System.out.println(mousePosArray.get(0));
// System.out.println(mousePosArray.get(mousePosArray.size() -1));
}).addEventData("event.x").addEventData("event.y");
}
MainLayout.java:
package com.vaadin.starter.beveragebuddy.backend;
import com.vaadin.flow.component.dependency.HtmlImport;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.H2;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.html.NativeButton;
import com.vaadin.flow.router.Route;
import com.vaadin.starter.beveragebuddy.ui.components.BoundingBox;
import com.vaadin.starter.beveragebuddy.ui.components.Canvas;
import com.vaadin.starter.beveragebuddy.ui.components.CanvasRenderingContext2D;
import com.vaadin.starter.beveragebuddy.ui.components.MousePosition;
import com.vaadin.flow.component.textfield.TextField;
import java.util.ArrayList;
#HtmlImport("frontend://styles/shared-styles.html")
#Route("")
public class MainLayout extends Div {
private CanvasRenderingContext2D ctx;
private Canvas canvas;
ArrayList<MousePosition> mousePosArray = Canvas.getMousePosArray();
ArrayList<BoundingBox> bb = Canvas.getArrayBoxes();
public MainLayout() {
H2 title = new H2("Annotation UI");
title.addClassName("main-layout__title");
canvas = new Canvas(1580, 700);
ctx = canvas.getContext();
Label label = new Label("Coordinates: " + mousePosArray);
canvas.addComponent(label);
add(label);
}
}
CanvasRenderingContext2D.java:
package com.vaadin.starter.beveragebuddy.ui.components;
import java.io.Serializable;
import java.util.ArrayList;
/**
* The context for rendering shapes and images on a canvas.
* <p>
* This is a Java wrapper for the <a href=
* "https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D">same
* client-side API</a>.
*/
public class CanvasRenderingContext2D {
private Canvas canvas;
public static ArrayList<BoundingBox> arrayBoxes = new ArrayList<BoundingBox>();
protected CanvasRenderingContext2D(Canvas canvas) {
this.canvas = canvas;
}
public void setFillStyle(String fillStyle) {
setProperty("fillStyle", fillStyle);
}
public void setStrokeStyle(String strokeStyle) {
setProperty("fillStyle", strokeStyle);
}
public void setLineWidth(double lineWidth) {
setProperty("lineWidth", lineWidth);
}
public void setFont(String font) {
setProperty("font", font);
}
public void arc(double x, double y, double radius, double startAngle,
double endAngle, boolean antiClockwise) {
callJsMethod("arc", x, y, radius, startAngle, endAngle, antiClockwise);
}
public void beginPath() {
callJsMethod("beginPath");
}
public void clearRect(double x, double y, double width, double height) {
callJsMethod("clearRect", x, y, width, height);
Canvas.arrayBoxes.clear();
}
public void closePath() {
callJsMethod("closePath");
}
/**
* Fetches the image from the given location and draws it on the canvas.
* <p>
* <b>NOTE:</b> The drawing will happen asynchronously after the browser has
* received the image.
*
* #param src
* the url of the image to draw
* #param x
* the x-coordinate of the top-left corner of the image
* #param y
* the y-coordinate of the top-left corner of the image
*/
public void drawImage(String src, double x, double y) {
runScript(String.format(
"var zwKqdZ = new Image();" + "zwKqdZ.onload = function () {"
+ "$0.getContext('2d').drawImage(zwKqdZ, %s, %s);};"
+ "zwKqdZ.src='%s';",
x, y, src));
}
/**
* Fetches the image from the given location and draws it on the canvas.
* <p>
* <b>NOTE:</b> The drawing will happen asynchronously after the browser has
* received the image.
*
* #param src
* the url of the image to draw
* #param x
* the x-coordinate of the top-left corner of the image
* #param y
* the y-coordinate of the top-left corner of the image
* #param width
* the width for the image
* #param height
* the height for the image
*/
public void drawImage(String src, double x, double y, double width,
double height) {
runScript(String.format("var zwKqdZ = new Image();"
+ "zwKqdZ.onload = function () {"
+ "$0.getContext('2d').drawImage(zwKqdZ, %s, %s, %s, %s);};"
+ "zwKqdZ.src='%s';", x, y, width, height, src));
}
public void fill() {
callJsMethod("fill");
}
public void fillRect(double x, double y, double width, double height) {
callJsMethod("fillRect", x, y, width, height);
}
public void fillText(String text, double x, double y) {
callJsMethod("fillText", text, x, y);
}
public void lineTo(double x, double y) {
callJsMethod("lineTo", x, y);
}
public void moveTo(double x, double y) {
callJsMethod("moveTo", x, y);
}
public void rect(double x, double y, double width, double height) {
callJsMethod("rect", x, y, width, height);
}
public void restore() {
callJsMethod("restore");
}
public void rotate(double angle) {
callJsMethod("rotate", angle);
}
public void save() {
callJsMethod("save");
}
public void scale(double x, double y) {
callJsMethod("scale", x, y);
}
public void stroke() {
callJsMethod("stroke");
}
public void strokeRect(double x, double y, double width, double height) {
callJsMethod("strokeRect", x, y, width, height);
}
public void strokeText(String text, double x, double y) {
callJsMethod("strokeText", text, x, y);
}
public void translate(double x, double y) {
callJsMethod("translate", x, y);
}
protected void setProperty(String propertyName, Serializable value) {
runScript(String.format("$0.getContext('2d').%s='%s'", propertyName,
value));
}
/**
* Runs the given js so that the execution order works with callJsMethod().
* Any $0 in the script will refer to the canvas element.
*/
private void runScript(String script) {
canvas.getElement().getNode().runWhenAttached(
// This structure is needed to make the execution order work
// with Element.callFunction() which is used in callJsMethod()
ui -> ui.getInternals().getStateTree().beforeClientResponse(
canvas.getElement().getNode(),
context -> ui.getPage().executeJavaScript(script,
canvas.getElement())));
}
protected void callJsMethod(String methodName, Serializable... parameters) {
canvas.getElement().callFunction("getContext('2d')." + methodName,
parameters);
}
}
BoundingBox.java:
package com.vaadin.starter.beveragebuddy.ui.components;
public class BoundingBox {
public double xcoordi = 0;
public double ycoordi = 0;
public double boxWidth = 0;
public double boxHeight = 0;
public int name;
public BoundingBox(int name, double xcoordi, double ycoordi, double boxWidth, double boxHeight) {
this.name = name;
this.xcoordi = xcoordi;
this.ycoordi = ycoordi;
this.boxWidth = boxWidth;
this.boxHeight = boxHeight;
}
public int getName() {
return name;
}
public void setName(int name) {
this.name = name;
}
public double getXcoordi() {
return xcoordi;
}
public void setXcoordi(double xcoordi) {
this.xcoordi = xcoordi;
}
public double getYcoordi() {
return ycoordi;
}
public void setYcoordi(double ycoordi) {
this.ycoordi = ycoordi;
}
public double getWidth() {
return boxWidth;
}
public void setWidth(double endX, double xcoordi) {
boxWidth = endX - xcoordi;
}
public double getHeight() {
return boxHeight;
}
public void setHeight(double endY, double ycoordi) {
boxHeight = endY - ycoordi;
}
#Override
public String toString() {
return "{" +
"Box=" + name +
", X=" + xcoordi +
", Y=" + ycoordi +
", Width=" + boxWidth +
", Height=" + boxHeight +
'}';
}
}
MousePosition.java:
package com.vaadin.starter.beveragebuddy.ui.components;
public class MousePosition {
public double mouseX;
public double mouseY;
public MousePosition(double mouseX, double mouseY) {
this.mouseX = mouseX;
this.mouseY = mouseY;
}
public double getMouseX() {
return mouseX;
}
public void setMouseX(double mouseX) {
this.mouseX = mouseX;
}
public double getMouseY() {
return mouseY;
}
public void setMouseY(double mouseY) {
this.mouseY = mouseY;
}
#Override
public String toString() {
return "MousePosition{" +
"mouseX=" + mouseX +
", mouseY=" + mouseY +
'}';
}
}
Any help is much appreciated, thank you!
Alright, with the updated code it seems your problem is that you never update the label.
You set the label text initially, but it will not be automatically updated when the array changes. What you can do is allow adding a listener to the canvas, and notify it when the value changes.
In the simplest case, a listener can be just a Java Runnable (or Supplier if you want to pass a value). My example returns a Vaadin Registration, which can be used to remove the listener by calling registration.remove().
In Canvas.java
private List<Runnable> mouseMoveListeners = new ArrayList<>(0);
...
public Registration addMouseMoveListener(Runnable listener) {
mouseMoveListeners.add(listener);
return () -> mouseMoveListeners.remove(listener);
}
And in your current mousemove listener
// Your current code in the mousemove listener
MousePosition currentPos = new MousePosition(mouseX, mouseY);
mousePosArray.add(0, currentPos);
setMousePosArray(mousePosArray);
System.out.println(mousePosArray.get(0));
// Add this to run all the listeners that have been added to the canvas
mouseMoveListeners.forEach(Runnable::run);
Then at the end of your MainLayout constructor, something like this
canvas.addMouseMoveListener(() -> label.setValue("Coordinates: " + mousePosArray));
This is untested code, but an approach similar to this should work. The point being that you somehow must notify the MainLayout when the array has changed.
Here's my touchpad.
What I want is this: when I touch background of touchpad (not knob), knob move to this position. Code, which I use for touchpad from github/libgdx/gdx/src/com/badlogic/gdx/scenes/scene2d/ui/Touchpad.java
package com.liketurbo.funnyGame;
/*******************************************************************************
* Copyright 2011 See AUTHORS file.
*
* 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.
******************************************************************************/
import com.badlogic.gdx.scenes.scene2d.Event;
import com.badlogic.gdx.scenes.scene2d.EventListener;
import com.badlogic.gdx.scenes.scene2d.ui.Widget;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.math.Circle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener.ChangeEvent;
import com.badlogic.gdx.scenes.scene2d.utils.Drawable;
import com.badlogic.gdx.utils.Pools;
/** An on-screen joystick. The movement area of the joystick is circular, centered on the touchpad, and its size determined by the
* smaller touchpad dimension.
* <p>
* The preferred size of the touchpad is determined by the background.
* <p>
* {#link ChangeEvent} is fired when the touchpad knob is moved. Cancelling the event will move the knob to where it was
* previously.
* #author Josh Street */
public class Touchpad extends Widget {
private TouchpadStyle style;
boolean touched;
boolean resetOnTouchUp = true;
private float deadzoneRadius;
private final Circle knobBounds = new Circle(0, 0, 0);
private final Circle touchBounds = new Circle(0, 0, 0);
private final Circle deadzoneBounds = new Circle(0, 0, 0);
private final Vector2 knobPosition = new Vector2();
private final Vector2 knobPercent = new Vector2();
/** #param deadzoneRadius The distance in pixels from the center of the touchpad required for the knob to be moved. */
public Touchpad (float deadzoneRadius, Skin skin) {
this(deadzoneRadius, skin.get(TouchpadStyle.class));
}
/** #param deadzoneRadius The distance in pixels from the center of the touchpad required for the knob to be moved. */
public Touchpad (float deadzoneRadius, Skin skin, String styleName) {
this(deadzoneRadius, skin.get(styleName, TouchpadStyle.class));
}
/** #param deadzoneRadius The distance in pixels from the center of the touchpad required for the knob to be moved. */
public Touchpad (float deadzoneRadius, TouchpadStyle style) {
if (deadzoneRadius < 0) throw new IllegalArgumentException("deadzoneRadius must be > 0");
this.deadzoneRadius = deadzoneRadius;
knobPosition.set(getWidth() / 2f, getHeight() / 2f);
setStyle(style);
setSize(getPrefWidth(), getPrefHeight());
addListener(new InputListener() {
#Override
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
if (touched) return false;
touched = true;
calculatePositionAndValue(x, y, false);
return true;
}
#Override
public void touchDragged (InputEvent event, float x, float y, int pointer) {
calculatePositionAndValue(x, y, false);
}
#Override
public void touchUp (InputEvent event, float x, float y, int pointer, int button) {
touched = false;
calculatePositionAndValue(x, y, resetOnTouchUp);
}
});
}
void calculatePositionAndValue (float x, float y, boolean isTouchUp) {
float oldPositionX = knobPosition.x;
float oldPositionY = knobPosition.y;
float oldPercentX = knobPercent.x;
float oldPercentY = knobPercent.y;
float centerX = knobBounds.x;
float centerY = knobBounds.y;
y = centerY;
knobPosition.set(centerX, centerY);
knobPercent.set(0f, 0f);
if (!isTouchUp) {
if (!deadzoneBounds.contains(x, y)) {
knobPercent.set((x - centerX) / knobBounds.radius*3.5f, 0);
float length = knobPercent.len();
if (length > 1) knobPercent.scl(1 / length);
if (knobBounds.contains(x, y)) {
knobPosition.set(x, y);
} else {
knobPosition.set(knobPercent).nor().scl(knobBounds.radius*3.5f).add(knobBounds.x, knobBounds.y);
}
}
}
if (oldPercentX != knobPercent.x || oldPercentY != knobPercent.y) {
ChangeEvent changeEvent = Pools.obtain(ChangeEvent.class);
if (fire(changeEvent)) {
knobPercent.set(oldPercentX, oldPercentY);
knobPosition.set(oldPositionX, oldPositionY);
}
Pools.free(changeEvent);
}
}
public void setStyle (TouchpadStyle style) {
if (style == null) throw new IllegalArgumentException("style cannot be null");
this.style = style;
invalidateHierarchy();
}
/** Returns the touchpad's style. Modifying the returned style may not have an effect until {#link #setStyle(TouchpadStyle)} is
* called. */
public TouchpadStyle getStyle () {
return style;
}
#Override
public Actor hit (float x, float y, boolean touchable) {
return touchBounds.contains(x, y) ? this : null;
}
#Override
public void layout () {
// Recalc pad and deadzone bounds
float halfWidth = getWidth() / 2;
float halfHeight = getHeight() / 2;
float radius = Math.min(halfWidth, halfHeight);
touchBounds.set(halfWidth, halfHeight, radius);
if (style.knob != null) radius -= Math.max(style.knob.getMinWidth(), style.knob.getMinHeight()) / 2;
knobBounds.set(halfWidth, halfHeight, radius);
deadzoneBounds.set(halfWidth, halfHeight, deadzoneRadius);
// Recalc pad values and knob position
knobPosition.set(halfWidth, halfHeight);
knobPercent.set(0, 0);
}
#Override
public void draw (Batch batch, float parentAlpha) {
validate();
Color c = getColor();
batch.setColor(c.r, c.g, c.b, c.a * parentAlpha);
float x = getX();
float y = getY();
float w = getWidth();
float h = getHeight();
final Drawable bg = style.background;
if (bg != null) bg.draw(batch, x, y, w, h);
final Drawable knob = style.knob;
if (knob != null) {
x += knobPosition.x - (knob.getMinWidth()*2) / 2f;
y += knobPosition.y - (knob.getMinHeight()*2) / 2f;
knob.draw(batch, x, y, knob.getMinWidth()*2, knob.getMinHeight()*2);
}
}
#Override
public float getPrefWidth () {
return style.background != null ? style.background.getMinWidth() : 0;
}
#Override
public float getPrefHeight () {
return style.background != null ? style.background.getMinHeight() : 0;
}
public boolean isTouched () {
return touched;
}
public boolean getResetOnTouchUp () {
return resetOnTouchUp;
}
/** #param reset Whether to reset the knob to the center on touch up. */
public void setResetOnTouchUp (boolean reset) {
this.resetOnTouchUp = reset;
}
/** #param deadzoneRadius The distance in pixels from the center of the touchpad required for the knob to be moved. */
public void setDeadzone (float deadzoneRadius) {
if (deadzoneRadius < 0) throw new IllegalArgumentException("deadzoneRadius must be > 0");
this.deadzoneRadius = deadzoneRadius;
invalidate();
}
/** Returns the x-position of the knob relative to the center of the widget. The positive direction is right. */
public float getKnobX () {
return knobPosition.x;
}
/** Returns the y-position of the knob relative to the center of the widget. The positive direction is up. */
public float getKnobY () {
return knobPosition.y;
}
/** Returns the x-position of the knob as a percentage from the center of the touchpad to the edge of the circular movement
* area. The positive direction is right. */
public float getKnobPercentX () {
return knobPercent.x;
}
/** Returns the y-position of the knob as a percentage from the center of the touchpad to the edge of the circular movement
* area. The positive direction is up. */
public float getKnobPercentY () {
return knobPercent.y;
}
/** The style for a {#link Touchpad}.
* #author Josh Street */
public static class TouchpadStyle {
/** Stretched in both directions. Optional. */
public Drawable background;
/** Optional. */
public Drawable knob;
public TouchpadStyle () {
}
public TouchpadStyle (Drawable background, Drawable knob) {
this.background = background;
this.knob = knob;
}
public TouchpadStyle (TouchpadStyle style) {
this.background = style.background;
this.knob = style.knob;
}
}
}
Line addListener(new InputListener() {...} works only for knob, if I can figure out how make it work for touchpad's background too, it solved my problem. Does somebody know how solve this problem? Thank you in advance.
You shouldn't add listener to your touchpad. Just limit touch area of the screen where touchpad can be used.
Here is code to activate only on right half of a screen:
private Touchpad touchpad;
private Vector2 screenPos = new Vector2(); // position where touch occurs
private Vector2 localPos = new Vector2(); // position in local coordinates
private InputEvent fakeTouchDownEvent = new InputEvent(); // fake touch for correct work
private Vector2 stagePos; // position to fire touch event
private void getDirection() {
if (Gdx.input.justTouched()) {
// Get the touch point in screen coordinates.
screenPos.set(Gdx.input.getX(), Gdx.input.getY());
if (screenPos.x > Gdx.graphics.getWidth() / 2) { // right half of a screen
// Convert the touch point into local coordinates, place the touchpad and show it.
localPos.set(screenPos);
localPos = touchpad.getParent().screenToLocalCoordinates(localPos);
touchpad.setPosition(localPos.x - touchpad.getWidth() / 2, localPos.y - touchpad.getHeight() / 2);
// Fire a touch down event to get the touchpad working.
Vector2 stagePos = touchpad.getStage().screenToStageCoordinates(screenPos);
fakeTouchDownEvent.setStageX(stagePos.x);
fakeTouchDownEvent.setStageY(stagePos.y);
touchpad.fire(fakeTouchDownEvent);
}
}
}
Hi I'm trying to create heart shape for my application and
I could do the hollow one and it's working good, now I need to draw it with filled method but it's created by two Arc2D.Double and two Line2D.Double so because of this just the Arc's filling and two lines not.I've tried to add these two lines in two different 'Area' and add these two areas in one but also not worked.
There is a any way to do this (filling between two lines)?Thanks advance.
My codes : Class Heart
`public class HeartShape {
private ArrayList<Shape> shapes;
public HeartShape() {
}
public ArrayList<Shape> Heart(double x, double y, double HEART_RADIUS) {
shapes = new ArrayList<>();
double r = HEART_RADIUS;
double root2 = Math.sqrt(2);
double cx = x;
double cy = y;
double dx = r / root2;
double heights = 3 * dx + r;
double top = cy - heights / 2;
double bottom = cy + heights / 2;
Shape s = new Arc2D.Double(cx - dx - r, top, 2 * r, 2 * r, 45, 180, Arc2D.OPEN);
shapes.add(s);
s = new Arc2D.Double(cx + dx - r, top, 2 * r, 2 * r, -45, 180, Arc2D.OPEN);
shapes.add(s);
s = new Line2D.Double(cx, bottom, cx - 2 * dx, bottom - 2 * dx);
shapes.add(s);
s = new Line2D.Double(cx, bottom, cx + 2 * dx, bottom - 2 * dx);
shapes.add(s);
if (shapes != null) {
return shapes;
} else {
return null;
}
}
public void drawHeart(Graphics2D g2d, boolean isFilled) {
if (isFilled == true) {
shapes.forEach((ss) -> {
g2d.fill(ss);
});
} else {
shapes.forEach((ss) -> {
g2d.draw(ss);
});
}
}`
And DrawinTest :
public class DrawinTest extends JPanel{
private int HEART_RADIUS;
private Point startpoint;
private int x, y, width, height;
private HeartShape heartShape = new HeartShape();
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
new DrawinTest();
}
public DrawinTest() {
JFrame f = new JFrame("Test Area");
f.setPreferredSize(new Dimension(600, 500));
f.setLocationRelativeTo(null);
f.setLayout(new BorderLayout(0, 1));
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.addMouseListener(new MyMouseListener());
this.addMouseMotionListener(new MyMouseListener());
this.setBackground(Color.WHITE);
f.setContentPane(this);
f.setVisible(true);
f.pack();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setStroke(new BasicStroke(3));
g2d.setColor(Color.RED);
if(heartShape != null) {
heartShape.Heart(x, y, HEART_RADIUS);
heartShape.drawHeart(g2d, false);
}
g2d.dispose();
}
class MyMouseListener implements MouseListener,MouseMotionListener {
#Override
public void mouseClicked(MouseEvent e) {}
#Override
public void mousePressed(MouseEvent e) {
startpoint = new Point(e.getPoint());
}
#Override
public void mouseReleased(MouseEvent e) {}
#Override
public void mouseEntered(MouseEvent e) {}
#Override
public void mouseExited(MouseEvent e) {}
#Override
public void mouseDragged(MouseEvent e) {
x = Math.min(startpoint.x, e.getX());
y = Math.min(startpoint.y, e.getY());
width = Math.abs(startpoint.x - e.getX());
height = Math.abs(startpoint.y - e.getY());
HEART_RADIUS = Math.min(width, height);
repaint();
}
#Override
public void mouseMoved(MouseEvent e) {}
}
}
So far its looking like this :
The Shapes API has a number of really interesting APIs, one of my favorites is Path2D
Basically, what it allows you to do is append other Shapes, making it very useful in this situation.
public class HeartShape {
private Shape shape;
public HeartShape() {
}
public Shape Heart(double x, double y, double HEART_RADIUS) {
double r = HEART_RADIUS;
double root2 = Math.sqrt(2);
double cx = x;
double cy = y;
double dx = r / root2;
double heights = 3 * dx + r;
double top = cy - heights / 2;
double bottom = cy + heights / 2;
Path2D base = new Path2D.Double();
Shape s = new Arc2D.Double(cx - dx - r, top, 2 * r, 2 * r, 45, 180, Arc2D.OPEN);
base.append(s, false);
s = new Line2D.Double(cx, bottom, cx - 2 * dx, bottom - 2 * dx);
base.append(s, true);
s = new Line2D.Double(cx, bottom, cx + 2 * dx, bottom - 2 * dx);
base.append(s, true);
s = new Arc2D.Double(cx + dx - r, top, 2 * r, 2 * r, -45, 180, Arc2D.OPEN);
base.append(s, true);
base.closePath();
shape = base;
return base;
}
public void drawHeart(Graphics2D g2d, boolean isFilled) {
System.out.println("...");
if (isFilled) {
g2d.fill(shape);
} else {
g2d.draw(shape);
}
}
}
As shown in this example, you don't need to re-create the shape when you want to change it's size, you can simply create an instance of it at a "default" size and use a AffineTransform to resize it, much easier ;)
I think that instead of using an arrayList of shapes you should use a GenericPath and append each individual shape to it with GenericPath.append(). One you're done add the pieces of the heart use GenericPath.closePath() to make it a close it up so that it can be filled. Then you should be able to use the new GenericPath object as the path to be drawn with g2d.draw
Trying the exercise in lesson2 of the Udacity course. Despite importing the classes (I'm at java.awt.* now, but I also tried java.awt.Color and java.awt.Canvas separately (also need Shape))..
package com.jul.udacity.lesson2;
public class TestRectangle {
public static void main(String[] args) {
// TODO Auto-generated method stub
Rectangle rect1 = new Rectangle(100.0, 100.0, 200.0, 100.0);
rect1.draw();
}
}
And the class is copied from there and java.awt import added. Any help will be great. Thanks!
package com.jul.udacity.lesson2;
//HIDE
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
//import java.awt.Color;
//import java.awt.Shape;
//import java.awt.Canvas;
import java.awt.*;
public class Rectangle implements Shape
{
private Color color = Color.BLACK;
private boolean filled = false;
private double x;
private double y;
private double width;
private double height;
/**
Constructs an empty rectangle.
*/
public Rectangle()
{
x = 0;
y = 0;
width = 0;
height = 0;
}
/**
Constructs a rectangle.
#param x the leftmost x-coordinate
#param y the topmost y-coordinate
#param width the width
#param height the height
*/
public Rectangle(double x, double y, double width, double height)
{
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
/**
Gets the leftmost x-position of this rectangle.
#return the leftmost x-position
*/
public int getX()
{
return (int) Math.round(x);
}
/**
Gets the topmost y-position of this rectangle.
#return the topmost y-position
*/
public int getY()
{
return (int) Math.round(y);
}
/**
Gets the width of this rectangle.
#return the width
*/
public int getWidth()
{
return (int) Math.round(width);
}
/**
Gets the height of this rectangle.
#return the height
*/
public int getHeight()
{
return (int) Math.round(height);
}
/**
Moves this rectangle by a given amount.
#param dx the amount by which to move in x-direction
#param dy the amount by which to move in y-direction
*/
public void translate(double dx, double dy)
{
x += dx;
y += dy;
Canvas.getInstance().repaint();
}
/**
Resizes this rectangle both horizontally and vertically.
#param dw the amount by which to resize the width on each side
#param dw the amount by which to resize the height on each side
*/
public void grow(double dw, double dh)
{
width += 2 * dw;
height += 2 * dh;
x -= dw;
y -= dh;
Canvas.getInstance().repaint();
}
/**
Sets the color of this rectangle.
#param newColor the new color
*/
public void setColor(Color newColor)
{
color = newColor;
Canvas.getInstance().repaint();
}
/**
Draws this rectangle.
*/
public void draw()
{
filled = false;
Canvas.getInstance().show(this);
}
/**
Fills this rectangle.
*/
public void fill()
{
filled = true;
Canvas.getInstance().show(this);
}
public String toString()
{
return "Rectangle[x=" + getX() + ",y=" + getY() + ",width=" + getWidth() + ",height=" + getHeight() + "]";
}
public void paintShape(Graphics2D g2)
{
Rectangle2D.Double rect = new Rectangle2D.Double(getX(), getY(),
getWidth(), getHeight());
g2.setColor(new java.awt.Color((int) color.getRed(), (int) color.getGreen(), (int) color.getBlue()));
if (filled)
{
g2.fill(rect);
}
else
{
g2.draw(rect);
}
}
}
You might want to check the lesson directions carefully. java.awt.Canvas has no getInstance() method. You just use new to make a Canvas. So you either didn't read carefully and are using the wrong Canvas, or there's something else going on.
Also the show() methods are deprecated, so I'm leaning towards you are supposed to be using a different Canvas class.
Also, Swing is not thread safe. Read up on how to use Swing objects
markspace is correct: Canvas here is not the class from java.awt - the Udacity instructors are using their own class called Canvas. I suggest grabbing the lesson files and using those. Here's the Canvas class from that Intro To Java Course:
import java.awt.image.BufferedImage;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.RescaleOp;
import java.io.IOException;
import java.io.File;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
public class Canvas
{
private static Canvas canvas = new Canvas();
private ArrayList<Shape> shapes = new ArrayList<Shape>();
private BufferedImage background;
private JFrame frame;
private CanvasComponent component;
private static final int MIN_SIZE = 100;
private static final int MARGIN = 10;
private static final int LOCATION_OFFSET = 120;
class CanvasComponent extends JComponent
{
public void paintComponent(Graphics g)
{
g.setColor(java.awt.Color.WHITE);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(java.awt.Color.BLACK);
if (background != null)
{
g.drawImage(background, 0, 0, null);
}
for (Shape s : new ArrayList<Shape>(shapes))
{
Graphics2D g2 = (Graphics2D) g.create();
s.paintShape(g2);
g2.dispose();
}
}
public Dimension getPreferredSize()
{
int maxx = MIN_SIZE;
int maxy = MIN_SIZE;
if (background != null)
{
maxx = Math.max(maxx, background.getWidth());
maxy = Math.max(maxx, background.getHeight());
}
for (Shape s : shapes)
{
maxx = (int) Math.max(maxx, s.getX() + s.getWidth());
maxy = (int) Math.max(maxy, s.getY() + s.getHeight());
}
return new Dimension(maxx + MARGIN, maxy + MARGIN);
}
}
private Canvas()
{
component = new CanvasComponent();
if (System.getProperty("com.horstmann.codecheck") == null)
{
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(component);
frame.pack();
frame.setLocation(LOCATION_OFFSET, LOCATION_OFFSET);
frame.setVisible(true);
}
else
{
final String SAVEFILE ="canvas.png";
final Thread currentThread = Thread.currentThread();
Thread watcherThread = new Thread()
{
public void run()
{
try
{
final int DELAY = 10;
while (currentThread.getState() != Thread.State.TERMINATED)
{
Thread.sleep(DELAY);
}
saveToDisk(SAVEFILE);
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
};
watcherThread.start();
}
}
public static Canvas getInstance()
{
return canvas;
}
public void show(Shape s)
{
if (!shapes.contains(s))
{
shapes.add(s);
}
repaint();
}
public void repaint()
{
if (frame == null) return;
Dimension dim = component.getPreferredSize();
if (dim.getWidth() > component.getWidth()
|| dim.getHeight() > component.getHeight())
{
frame.pack();
}
else
{
frame.repaint();
}
}
/**
* Pauses so that the user can see the picture before it is transformed.
*/
public void pause()
{
if (frame == null) return;
JOptionPane.showMessageDialog(frame, "Click Ok to continue");
}
/**
* Takes a snapshot of the screen, fades it, and sets it as the background.
*/
public static void snapshot()
{
Dimension dim = getInstance().component.getPreferredSize();
java.awt.Rectangle rect = new java.awt.Rectangle(0, 0, dim.width, dim.height);
BufferedImage image = new BufferedImage(rect.width, rect.height, BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
g.setColor(java.awt.Color.WHITE);
g.fillRect(0, 0, rect.width, rect.height);
g.setColor(java.awt.Color.BLACK);
getInstance().component.paintComponent(g);
float factor = 0.8f;
float base = 255f * (1f - factor);
RescaleOp op = new RescaleOp(factor, base, null);
BufferedImage filteredImage
= new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
op.filter(image, filteredImage);
getInstance().background = filteredImage;
getInstance().component.repaint();
}
public void saveToDisk(String fileName)
{
Dimension dim = component.getPreferredSize();
java.awt.Rectangle rect = new java.awt.Rectangle(0, 0, dim.width, dim.height);
BufferedImage image = new BufferedImage(rect.width, rect.height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = (Graphics2D) image.getGraphics();
g.setColor(java.awt.Color.WHITE);
g.fill(rect);
g.setColor(java.awt.Color.BLACK);
component.paintComponent(g);
String extension = fileName.substring(fileName.lastIndexOf('.') + 1);
try
{
ImageIO.write(image, extension, new File(fileName));
}
catch(IOException e)
{
System.err.println("Was unable to save the image to " + fileName);
}
g.dispose();
}
}