Text Being Duplicated in a JLabel - java

I'm designing an application for configuring a pallet, and I've got a class that extends JLabel which I use to create JLabels with rotated text. I've found a few examples online of how to do this and my rotation is working well enough, its not perfect but it's a work in progress.
The problem I have at the moment is that the text in my rotated JLabels is duplicated, and I don't know why. Below is a picture showing the duplicate text in each label, its more prominent in some than in others, eg with the height label the duplication can clearly be seen.
Duplicate Label Text Image:
Here's the source code for my RotatableText class that extends JLabel.
public class RotatableText extends JLabel
{
private static final long serialVersionUID = 1L;
private String text;
private double angle;
public final static String DEGREES = "deg";
public final static String RADIANS = "rad";
private final static double TO_RADIANS = Math.PI/180;
private final static double TO_DEGREES = 180/Math.PI;
/**
* Creates text rotated by angle in a clockwise direction if clockwise is true,
* or anti-clockwise if it's false
* #param angle angle to be rotated by in degrees
* #param clockwise determines direction of rotation#exception Exception if angleUnit is not RotatableText.DEGREES or RotatableText.RADIANS
*/
public RotatableText(String text, double angle, boolean clockwise, final String angleUnit) throws IllegalAngleUnitException
{
if (!(angleUnit.equals(DEGREES) || angleUnit.equals(RADIANS)))
{
throw new IllegalAngleUnitException("Invalid Angle Selected");
}
else if (angleUnit.equals(DEGREES))
{
if (!clockwise)
{
this.angle = -angle * TO_RADIANS;
super.setText(text);
}
else
{
this.angle = angle * TO_RADIANS;
super.setText(text);
}
}
else if (angleUnit.equals(RADIANS))
{
if (!clockwise)
{
this.angle = -angle;
super.setText(text);
}
else
{
this.angle = angle;
super.setText(text);
}
}
setVerticalAlignment(JLabel.TOP);
setHorizontalAlignment(JLabel.LEFT);
}
/**
* Creates text rotated by angle in an anti-clockwise rotation
* #param angle angle to be rotated by in degrees
* #exception Exception if angleUnit is not RotatableText.DEGREES or RotatableText.RADIANS
*/
public RotatableText(String text, double angle, final String angleUnit) throws IllegalAngleUnitException
{
if (!(angleUnit.equals(DEGREES) || angleUnit.equals(RADIANS)))
{
throw new IllegalAngleUnitException("Invalid Angle Selected");
}
else if (angleUnit.equals(DEGREES))
{
this.angle = angle * TO_RADIANS;
super.setText(text);
}
else if (angleUnit.equals(RADIANS))
{
this.angle = angle;
super.setText(text);
}
setVerticalAlignment(JLabel.BOTTOM);
setHorizontalAlignment(JLabel.CENTER);
}
/**
* Draws the Component
*/
#Override
protected void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
g2.rotate(angle, getPreferredSize().width/2, getPreferredSize().height/2);
g2.drawString(super.getText(), 0, 0);
setBounds(getX(), getY());
super.paintComponent(g);
}
/**
* Gets the text of this RotatableText.
* #return text
*/
public String getText()
{
return super.getText();
}
/**
* Set's bounds with a fixed size
*/
public void setBounds(int x, int y)
{
super.setBounds(x, y, 100, 100);
}
public void setText(String text)
{
super.setText(text);
repaint();
}
/**
* Set the angle of this RotatableText in Radians
* #param angle
*/
public void setAngle(double angle)
{
this.angle = angle;
repaint();
}
/**
* Sets the angle of this RotatableText in the specified unit
* #param angle
* #param angleUnit
* #throws IllegalAngleUnitException
*/
public void setAngle(double angle, String angleUnit) throws IllegalAngleUnitException
{
if (!(angleUnit.equals(DEGREES) || angleUnit.equals(RADIANS)))
{
throw new IllegalAngleUnitException("Invalid Angle Selected");
}
else if (angleUnit.equals(DEGREES))
{
this.angle = angle * TO_RADIANS;
}
else if (angleUnit.equals(RADIANS))
{
this.angle = angle;
}
repaint();
}
/**
* Gets the angle of this RotatableText, anti-clockwise from the horizontal, in degrees.
* #return
*/
public double getAngle()
{
return angle * TO_DEGREES;
}
}
Each Label is generated as follows (this is the length label)
lengthLabel = new RotatableText("0", 14, true, RotatableText.DEGREES);
Each label is updated by passing getting the text from its respective text field and passing it as an argument for label.setText().
EDIT: printing System.out.println(heightLabel.getText()) prints just one copy of the text.
If anyone has an idea as to why this duplication is occuring, I'd love to hear them.
Thanks,
Sam.

You're drawing your text twice in your code as indicated below:
#Override
protected void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
g2.rotate(angle, getPreferredSize().width/2, getPreferredSize().height/2);
g2.drawString(super.getText(), 0, 0); // ****** here *****
setBounds(getX(), getY());
super.paintComponent(g); // ******* here ******
}
Also, I wouldn't set a component's bounds in a painting method, a dangerous thing to do, but do consider setting the Graphics2D clip there. Also I would do my rotation on a copy of the Graphics object, and then dispose of the copy when done. Otherwise you risk propagating rotational side effects downstream in the painting chain (if not desired)
e.g.,
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g.create();
g2.rotate(angle, getPreferredSize().width / 2, getPreferredSize().height / 2);
// g2.drawString(super.getText(), 0, 0);
// setBounds(getX(), getY());
// ***** This is a kludge and needs to be calculated better ****
Rectangle clipBounds = g2.getClipBounds();
int extraBounds = 10;
int x = clipBounds.x - extraBounds;
int y = clipBounds.y - extraBounds;
int width = clipBounds.width + 2 * extraBounds;
int height = clipBounds.height + 2 * extraBounds;
g2.setClip(x, y, width, height);
// ***** end kludge
super.paintComponent(g2);
g2.dispose();
}

Related

How to bounce text in a window without JFrame?

I am trying to bounce my text in a window, inserted from a text file without modifying the inputs from the text. I have the code to create and bounce the text, but some of it is lost when trying to bounce on the wall. The code consists of 3 classes.
This creates the text:
public class MyShape extends ClosedShape {
//The width and height of the text (major and minor axis)
private int width, height;
private String bouncingText;
private double textFont;
/**
* Creates an oval.
* #param x The display component's x position.
* #param y The display component's y position.
* #param vx The display component's x velocity.
* #param vy The display component's y velocity.
* #param width The width of the text (in pixels).
* #param height The height of the text (in pixels).
* #param colour The line colour or fill colour.
* #param isFilled True if the oval is filled with colour, false if opaque.
*/
public MyShape (int insertionTime, int x, int y, int vx, int vy, String bouncingText, int width, int height, Color colour, boolean isFilled, double textFont) {
super (insertionTime, x, y, vx, vy, colour, isFilled);
this.width = width;
this.height = height;
this.bouncingText = bouncingText;
this.textFont = textFont;
}
/**
* Method to convert a text to a string.
*/
public String toString () {
String result = "This is a text shape\n";
result += super.toString ();
result += "Its width is " + this.width + " and its height is " + this.height + "\n";
return result;
}
/**
* #param width Resets the width.
*/
public void setWidth (int width) {
this.width = width;
}
/**
* #param height Resets the height.
*/
public void setHeight (int height) {
this.height = height;
}
public void setBouncingText (String bouncingText) {
this.bouncingText = bouncingText;
}
public void setTextFont (double textFont) {
this.textFont = textFont;
}
/**
* #return The width of the text.
*/
public int getWidth() {
return width;
}
/**
* #return The height of the text.
*/
public int getHeight() {
return height;
}
public String getBouncingText() {
return bouncingText;
}
public double getTextFont() {
return textFont;
}
public void pulsing() {
if (textFont > 20) {
textFont = 10;
}else {
textFont = 50;
}
}
/**
* Draw the text.
* #param g The graphics object of the drawable component.
*/
public void draw (GraphicsContext g) {
Font bouncingTextFont = new Font ("TimesNew", textFont);
g.setFill (colour);
g.setStroke( colour );
if (isFilled) {
g.fillText(bouncingText, xPos, yPos );
g.setFont(bouncingTextFont);
}
else {
g.strokeText(bouncingText, xPos, yPos );
g.setFont(bouncingTextFont);
}
}
}
This is the bouncing code:
import java.util.ArrayList;
import javafx.animation.Animation;
import javafx.animation.AnimationTimer;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
import javafx.scene.shape.ArcType;
import javafx.stage.Stage;
import javafx.util.Duration;
public class BouncingShapesWindow {
private static final int ANIMATION_DELAY = 10;
private static final String FRAME_TITLE = "Shape Booooiiinggg Frame";
private GraphicsContext gc;
private Queue shapesToAdd;
private ArrayList<ClosedShape> activeShapes;
private int currentTime = 0;
private boolean flag=true;
private String filename;
public BouncingShapesWindow(GraphicsContext gc,String filename) {
this.gc=gc;
activeShapes=new ArrayList<ClosedShape>();
this.initShapes(filename);
this.insertShapes ();
drawShapes();
actionPerformed();
}
private void drawShapes () {
for (ClosedShape s : activeShapes)
{
s.draw(gc);
}
}
private void initShapes (String filename) {
shapesToAdd = ReadShapeFile.readFile(filename);
}
private void insertShapes() {
//no more shapes to add, we are done
if (shapesToAdd.isEmpty ()) {
return;
}
//add shapes if needed
ClosedShape current = (ClosedShape) shapesToAdd.peek ();
while (!shapesToAdd.isEmpty () && (current.getInsertionTime() <= currentTime*ANIMATION_DELAY)) {
activeShapes.add(current);
shapesToAdd.dequeue();
if (!shapesToAdd.isEmpty ()) {
current = (ClosedShape) shapesToAdd.peek();
}
}
}
public void actionPerformed()
{
Timeline timeline = new Timeline(new KeyFrame(Duration.millis(5), ae -> onTime()));
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
}
private void onTime() {
currentTime++;
double h =gc.getCanvas().getHeight();
double w = gc.getCanvas().getWidth();
gc.clearRect(0, 0, w, h);
moveShapes();
insertShapes ();
drawShapes();
}
public void moveShapes()
{
double dimsY = gc.getCanvas().getHeight() ;
double dimsX = gc.getCanvas().getWidth() ;
for (ClosedShape s : activeShapes)
{
s.move();
// Move us back in and bounce if we went outside the drawing area.
if (s.outOfBoundsX(dimsX))
{
s.putInBoundsX(dimsX);
s.bounceX();
}
if (s.outOfBoundsY(dimsY))
{
s.putInBoundsY(dimsY);
s.bounceY();
}
}
}
}
and this is the super class:
import javafx.scene.paint.Color;
import javafx.scene.canvas.GraphicsContext;
/**
* A ClosedShape is any shape that can be drawn without
* taking a pencil off a piece of paper.
* It's representation on computer has a line colour
* and a position on the drawable screen component.
* It can be filled in with colour or opaque.
* This class is a super class for all shapes.
*/
public class ClosedShape {
/**
* The x position of the Shape.
*/
protected int xPos;
/**
* The y position of the Shape.
*/
protected int yPos = 20;
/**
* The x position of the Shape.
*/
protected int xVec;
/**
* The y position of the Shape.
*/
protected int yVec;
/**
* The line colour of the shape, or the filled in
* colour if the Shape has fill.
*/
protected Color colour;
/**
* Determines if the Shape has a fill colour or not.
*/
protected boolean isFilled;
/**
* Encodes the insertion time into the scene
*/
private int insertionTime;
/**
* Creates a closed shape object.
* #param x The x position.
* #param y the y position.
* #param colour The line or fill colour.
* #param isFilled True if the shape is filled, false if not.
*/
protected ClosedShape (int insertionTime, int x, int y, int vx, int vy, Color colour, boolean isFilled) {
this.xPos = x;
this.yPos = y;
this.xVec = vx;
this.yVec = vy;
this.colour = colour;
this.isFilled = isFilled;
this.insertionTime = insertionTime;
}
/**
* The method returns a string suitable for printing.
* #return string to print out shape.
*/
public String toString () {
String result = "";
result += "Its position is " + xPos + " " + yPos + "\n";
result += "Its velocity is " + xVec + " " + yVec + "\n";
result += "Its colour is " + colour + "\n";
if (isFilled)
result += "It is filled" + "\n";
else
result += "It is not filled" + "\n";
result += "It should be inserted at " + insertionTime + "\n";
return result;
}
/**
* Resets the x position.
*/
public void setX (int x) {
this.xPos = x;
}
/**
* Resets the y position.
*/
public void setY (int y) {
this.yPos = y;
}
/**
* Resets the x vector
*/
public void setVecX (int x) {
this.xVec = x;
}//end setVecX
/**
* Resets the y position.
*/
public void setVecY (int y) {
this.yVec = y;
}//end setVecY
/**
* Resets the colour.
*/
public void setColour (Color colour) {
this.colour = colour;
}
/**
* Sets the shape to filled.
*/
public void setFilled () {
isFilled = true;
}
/**
* Sets the shape to unfilled.
*/
public void unsetFilled () {
isFilled = false;
}
/**
* Sets the insertion time.
*/
public void setInsertionTime (int time) {
insertionTime = time;
}
/**
* #return The x position value.
*/
public int getX() {
return xPos;
}
/**
* #return The y position value.
*/
public int getY() {
return yPos;
}
/**
* #return The colour.
*/
public Color getColour() {
return colour;
}
/**
* #return True if the shape is filled, false if not.
*/
public boolean isFilled() {
return isFilled;
}
/**
* #return the insertion time.
*/
public int getInsertionTime () {
return insertionTime;
}
/**
* Puts the shape back in bounds in X
*/
public void putInBoundsX (double winX) {
if (xPos < 0) xPos = 0;
if (xPos + this.getWidth() > winX) {
xPos = (int) (winX - Math.ceil (this.getWidth ()));
}
}//end inBoundsX;
/**
* Puts the shape back in bounds
*/
public void putInBoundsY (double winY) {
if (yPos < 0) yPos = 0;
if (yPos + this.getHeight() > winY) {
yPos = (int) (winY - Math.ceil (this.getHeight ()));
}
}//end inBoundsY;
/**
* Bounces the shape off a vertical wall
*/
public void bounceX () {
xVec = -xVec;
}
/**
* Bounces the shape off a horizontal wall
*/
public void bounceY () {
yVec = -yVec;
}
/**
* Returns true if the shapes have gone out of bounds in X
*/
public boolean outOfBoundsX (double winX) {
return (xPos + this.getWidth()> winX) || (xPos < 0);
}
/**
* Returns true if the shapes have gone out of bounds in Y
*/
public boolean outOfBoundsY (double winY) {
return (yPos + this.getHeight() > winY) || (yPos < 0);
}
/**
* Takes in a direction and a velocity and moves the shape
* in that direction on unit
*/
public void move () {
xPos += xVec;
yPos += yVec;
}
/**
* Draws the object to the current component.
* #param g The graphics object associated with the drawing component.
*/
public void draw (GraphicsContext g) {
System.out.println ("You forgot to override this method! (draw)");
System.out.println ("Don't modify this method.");
}
/**
* Get the width of the current component
*/
public int getWidth () {
System.out.println ("You forgot to override this method! (getWidth)");
System.out.println ("Don't modify this method.");
return 1;
}
/**
* Get the width of the current component
*/
public int getHeight () {
System.out.println ("You forgot to override a method! (getHeight)");
System.out.println ("Don't modify this method.");
return 1;
}
public int getSide () {
System.out.println ("You forgot to override this method! (getSide)");
System.out.println ("Don't modify this method.");
return 1;
}
}
I tried reversing it, but nothing works. Using other shapes like circle or rect is OK, but with text it bounces under the head of the window and if I change the font size it loses its boundaries. I tried searching for solutions and it seems that everything uses JFrame and JPanel. I hope the code I provided leads to a useful solution.

Java-Accessing value of parent class from child class

Hey I am trying to figure a confusion with accessing a variable's value from parent class in child class.
Scenario #1
Below is the code for the class DrawingPanel():
public class DrawingPanel extends JPanel implements MouseListener
{
private ArrayList<Balloon> balloons;
private Balloon activeBalloon;
private boolean picked;
private int offsetX, offsetY;
private double offsetR;
int rotate;
// Constructor:
public DrawingPanel()
{
setBackground(Color.WHITE);
addMouseListener(this);
balloons = new ArrayList<Balloon>();
activeBalloon = null;
picked = false;
rotate = 0;
}
// Called from controlPanel when the "Add balloon" button is clicked.
// Places a new balloon with a random radius and the current color
// at the center of the drawing panel.
public void addBalloon(int shape)
{
int w = getWidth();
int h = getHeight();
int radius = 10 + (int) (Math.random() * w / 2);
switch (shape)
{
case 1:
activeBalloon = new SquareBalloon(w / 2, h / 2, radius);
break;
default:
activeBalloon = new SquareBalloon(w / 2, h / 2, radius);
break;
}
balloons.add(activeBalloon);
repaint();
}
// Repaints this panel. If activeBalloon is set, paints it on top.
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
for (Balloon b : balloons)
{
if (!picked || b != activeBalloon)
{
b.draw(g, true);
}
}
if (picked && activeBalloon != null)
activeBalloon.draw(g, false);
}
// Called when the mouse is clicked on the drawing panel.
// If inside a balloon, makes it "active", remembers the offsets
// of the click from the center.
// If on the border of a balloon, makes it "active", remembers the
// distance of the click from the center.
#Override
public void mousePressed(MouseEvent e)
{
// Value for parameter rotate is set here on mouse click
rotate = 2;
int x = e.getX();
int y = e.getY();
picked = false;
for (int k = balloons.size() - 1; k >= 0 && !picked; k--)
{
Balloon b = balloons.get(k);
if (b.isInside(x, y))
{
picked = true;
offsetX = x - b.getX();
offsetY = y - b.getY();
activeBalloon = b;
} else if (b.isOnBorder(x, y))
{
picked = true;
offsetR = b.distance(x, y) - b.getRadius();
activeBalloon = b;
}
}
if (picked)
repaint();
}
// "Drops" the picked balloon, if any.
#Override
public void mouseReleased(MouseEvent e)
{
}
// Not used:
#Override
public void mouseEntered(MouseEvent e)
{
}
#Override
public void mouseExited(MouseEvent e)
{
}
#Override
public void mouseClicked(MouseEvent e)
{
}
}
Below is the SquareBalloon() class which inherits the parent class Balloon. The Balloon class inherits the DrawingPanel() class.
public class SquareBalloon extends Balloon implements MouseListener
{
public SquareBalloon()
{
}
/**
* Constructs a balloon with a given center, radius and color
*
* #param x
* x-coordinate of the center
* #param y
* y-coordinate of the center
* #param r
* radius of the balloon
*/
public SquareBalloon(int x, int y, int r)
{
super(x, y, r);
}
/**
* Draws a solid circle if makeItFilled is true and outline only if
* makeItFilled is false
*
* #param g
* graphics context
* #param makeItFilled
* draws a solid circle if true
*/
#Override
public void draw(Graphics g, boolean makeItFilled)
{
Graphics2D g2d = (Graphics2D) g;
g.setColor(color);
System.out.println("This is the value of rotate" + rotate + "from the draw() method of SquareBalloon() class.");
if (makeItFilled)
{
Rectangle rect2 = new Rectangle(xCenter - radius, yCenter - radius, radius, radius);
if (rotate == 2)
{
System.out.println("This is the value of rotate" + rotate
+ "from the makedItFilled if statement in draw() method of SquareBalloon() class.");
g2d.rotate(45 * (Math.PI / 180));
}
g2d.fill(rect2);
} else
{
Rectangle rect2 = new Rectangle(xCenter - radius, yCenter - radius, radius, radius);
if (rotate == 2)
{
System.out.println("This is the value of rotate" + rotate
+ "from the other if statement in draw() method of SquareBalloon() class.");
g2d.rotate(45 * (Math.PI / 180));
}
g2d.draw(rect2);
}
}
}
Scenario #2
Below is the code for the class DrawingPanel():
public class DrawingPanel extends JPanel implements MouseListener
{
private ArrayList<Balloon> balloons;
private Balloon activeBalloon;
private boolean picked;
private int offsetX, offsetY;
private double offsetR;
int rotate;
// Constructor:
public DrawingPanel()
{
setBackground(Color.WHITE);
addMouseListener(this);
balloons = new ArrayList<Balloon>();
activeBalloon = null;
picked = false;
rotate = 0;
}
// Called from controlPanel when the "Add balloon" button is clicked.
// Places a new balloon with a random radius and the current color
// at the center of the drawing panel.
public void addBalloon(int shape)
{
int w = getWidth();
int h = getHeight();
int radius = 10 + (int) (Math.random() * w / 2);
switch (shape)
{
case 1:
activeBalloon = new SquareBalloon(w / 2, h / 2, radius);
break;
default:
activeBalloon = new SquareBalloon(w / 2, h / 2, radius);
break;
}
balloons.add(activeBalloon);
repaint();
}
// Repaints this panel. If activeBalloon is set, paints it on top.
#Override
public void paintComponent(Graphics g)
{
// to restore original angle of balloon objects
if (rotate > 2)
rotate = 0;
super.paintComponent(g);
for (Balloon b : balloons)
{
if (!picked || b != activeBalloon)
{
b.draw(g, true, rotate);
}
}
if (picked && activeBalloon != null)
activeBalloon.draw(g, false, rotate);
}
// Called when the mouse is clicked on the drawing panel.
// If inside a balloon, makes it "active", remembers the offsets
// of the click from the center.
// If on the border of a balloon, makes it "active", remembers the
// distance of the click from the center.
#Override
public void mousePressed(MouseEvent e)
{
// Value for parameter rotate is set here on mouse click
rotate++;
int x = e.getX();
int y = e.getY();
picked = false;
for (int k = balloons.size() - 1; k >= 0 && !picked; k--)
{
Balloon b = balloons.get(k);
if (b.isInside(x, y))
{
picked = true;
offsetX = x - b.getX();
offsetY = y - b.getY();
activeBalloon = b;
} else if (b.isOnBorder(x, y))
{
picked = true;
offsetR = b.distance(x, y) - b.getRadius();
activeBalloon = b;
}
}
if (picked)
repaint();
}
// "Drops" the picked balloon, if any.
#Override
public void mouseReleased(MouseEvent e)
{
}
// Not used:
#Override
public void mouseEntered(MouseEvent e)
{
}
#Override
public void mouseExited(MouseEvent e)
{
}
#Override
public void mouseClicked(MouseEvent e)
{
}
}
Below is the SquareBalloon() class which inherits the parent class Balloon. The Balloon class inherits the DrawingPanel() class.
public class SquareBalloon extends Balloon implements MouseListener
{
public SquareBalloon()
{
}
/**
* Constructs a balloon with a given center, radius and color
*
* #param x
* x-coordinate of the center
* #param y
* y-coordinate of the center
* #param r
* radius of the balloon
*/
public SquareBalloon(int x, int y, int r)
{
super(x, y, r);
}
/**
* Draws a solid circle if makeItFilled is true and outline only if
* makeItFilled is false
*
* #param g
* graphics context
* #param makeItFilled
* draws a solid circle if true
* #param rotate
* receives rotate variable value set in mousePressed() method of
* DrawingPanel() class
*/
#Override
public void draw(Graphics g, boolean makeItFilled, int rotate)
{
Graphics2D g2d = (Graphics2D) g;
g.setColor(color);
System.out.println("This is the value of rotate" + rotate + "from the draw() method of SquareBalloon() class.");
if (makeItFilled)
{
Rectangle rect2 = new Rectangle(xCenter - radius, yCenter - radius, radius, radius);
if (rotate == 2)
{
System.out.println("This is the value of rotate" + rotate
+ "from the makedItFilled if statement in draw() method of SquareBalloon() class.");
g2d.rotate(45 * (Math.PI / 180));
}
g2d.fill(rect2);
} else
{
Rectangle rect2 = new Rectangle(xCenter - radius, yCenter - radius, radius, radius);
if (rotate == 2)
{
System.out.println("This is the value of rotate" + rotate
+ "from the other if statement in draw() method of SquareBalloon() class.");
g2d.rotate(45 * (Math.PI / 180));
}
g2d.draw(rect2);
}
}
}
Can someone please explain why in Scenario #1, the change in value of variable int rotate after the mousePressed method initiates is not being passed to the subclasses of Balloon class so that the if statements with condition rotate == 2 in the draw method of class SquareBalloon executes? Because in Scenario #2 it does work.
Thank you!

Canvas shows content only by minimizing and resizing the window

im using the Canvas class to make a screensaver as a schoolproject.
But the window generated by Canvas doesnt show my objects on it (current time)
until i minimize it an resize it again. After that all things works fine.
so what is wrong?
thank you for coming answers!
with kind regards
leon
those are the classes, i peronally think that the problem is in the class Start or BufferedCanvas
import java.awt.*;
import java.util.Date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
public class Start
{
int fensterX = 900;
int fensterY = 700;
Farbengenerator fg = new Farbengenerator();
BufferedCanvas c =newBufferedCanvas("Bild",fensterX,fensterY);
Zeit z = new Zeit();
SchriftParameter sp = new SchriftParameter();
public void zeichneText(){
double x = 100;
double y = 100;
double fy =0.01;
double fx =0.02;
int red=0;
int green=0;
int blue=0;
double colourGrowRate=0.05;
String uhr;
c.setFont(sp.setzteSchrift());
c.setForegroundColour(Color.BLACK);
c.setBackgroundColour(Color.WHITE);
for(int i=0;i<100;i++){
c.drawString("Starting...",(int)x,(int)y);
c.updateAndShow();
try{Thread.sleep(50);}
catch(Exception e){};
c.updateAndShow();
}
CreateButton d = new CreateButton();
d.run();
while(true) {
c.erase();
uhr = z.erstelleZeit();
c.drawString(uhr,(int)x,(int)y);
if((int)x >fensterX-93 || (int)x <5){
fx = fx * (-1);
red=fg.gibROT();
green=fg.gibGRUEN();
blue=fg.gibBLAU();
Color colour = new Color(red,green,blue);
c.setForegroundColour(colour);
}
if((int)y > fensterY-1 || (int)y < 46){
fy = fy * (-1);
red=fg.gibROT();
green=fg.gibGRUEN();
blue=fg.gibBLAU();
Color colour = new Color(red,green,blue);
c.setForegroundColour(colour);
}
if((int)colourGrowRate>=1){
fg.generiereFarbe();
colourGrowRate = 0.05;
}
colourGrowRate=colourGrowRate+colourGrowRate;
x = x + fx;
y = y + fy;
c.updateAndShow();
}
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferStrategy;
public class BufferedCanvas
{
private JFrame frame;
private CanvasPane canvas;
private Graphics2D graphic;
private Color backgroundColour;
private Image canvasImage;
BufferStrategy buff;
/**
* Create a BufferedCanvas with default height,
width and background colour
* (300, 300, white).
* #param title title to appear in Canvas Frame
*/
public BufferedCanvas(String title)
{
this(title, 300, 300, Color.white);
}
/**
* Create a BufferedCanvas with default background colour (white).
* #param title title to appear in Canvas Frame
* #param width the desired width for the canvas
* #param height the desired height for the canvas
*/
public BufferedCanvas(String title, int width, int height)
{
this(title, width, height, Color.white);
}
/**
* Create a BufferedCanvas.
* #param title title to appear in Canvas Frame
* #param width the desired width for the canvas
* #param height the desired height for the canvas
* #param bgClour the desired background colour of the canvas
*/
public BufferedCanvas(String title, int width, int height, Color bgColour)
{
frame = new JFrame();
canvas = new CanvasPane();
frame.setContentPane(canvas);
frame.setTitle(title);
canvas.setPreferredSize(new Dimension(width, height));
backgroundColour = bgColour;
frame.pack();
frame.createBufferStrategy(2);
buff = frame.getBufferStrategy();
graphic = (Graphics2D)buff.getDrawGraphics();
setVisible(true);
}
/**
* Set the canvas visibility and brings canvas to the front of screen
* when made visible. This method can also be used to bring an already
* visible canvas to the front of other windows.
* #param visible boolean value representing the desired visibility of
* the canvas (true or false)
*/
public void setVisible(boolean visible)
{
if(graphic == null) {
// first time: instantiate the offscreen image and fill it with
// the background colour
Dimension size = canvas.getSize();
canvasImage = canvas.createImage(size.width, size.height);
graphic = (Graphics2D)canvasImage.getGraphics();
graphic.setColor(backgroundColour);
graphic.fillRect(0, 0, size.width, size.height);
graphic.setColor(Color.black);
}
frame.setVisible(true);
}
/**
* Update the canvas and show the new image.
*/
public void updateAndShow(){
buff.show();
}
/**
* Provide information on visibility of the Canvas.
* #return true if canvas is visible, false otherwise
*/
public boolean isVisible()
{
return frame.isVisible();
}
/**
* Draw a given shape onto the canvas.
* #param shape the shape object to be drawn on the canvas
*/
public void draw(Shape shape)
{
graphic.draw(shape);
//canvas.repaint();
}
/**
* Fill the internal dimensions of a given shape with the current
* foreground colour of the canvas.
* #param shape the shape object to be filled
*/
public void fill(Shape shape)
{
graphic.fill(shape);
//canvas.repaint();
}
/**
* Erase the whole canvas.
*/
public void erase()
{
Color original = graphic.getColor();
graphic.setColor(backgroundColour);
Dimension size = canvas.getSize();
graphic.fill(new Rectangle(0, 0, size.width, size.height));
graphic.setColor(original);
//canvas.repaint();
}
/**
* Erase a given shape's interior on the screen.
* #param shape the shape object to be erased
*/
public void erase(Shape shape)
{
Color original = graphic.getColor();
graphic.setColor(backgroundColour);
graphic.fill(shape); // erase by filling background colour
graphic.setColor(original);
//canvas.repaint();
}
/**
* Erases a given shape's outline on the screen.
* #param shape the shape object to be erased
*/
public void eraseOutline(Shape shape)
{
Color original = graphic.getColor();
graphic.setColor(backgroundColour);
graphic.draw(shape); // erase by drawing background colour
graphic.setColor(original);
//canvas.repaint();
}
/**
* Draws an image onto the canvas.
* #param image the Image object to be displayed
* #param x x co-ordinate for Image placement
* #param y y co-ordinate for Image placement
* #return returns boolean value representing whether the image was
* completely loaded
*/
public boolean drawImage(Image image, int x, int y)
{
boolean result = graphic.drawImage(image, x, y, null);
//canvas.repaint();
return result;
}
/**
* Draws a String on the Canvas.
* #param text the String to be displayed
* #param x x co-ordinate for text placement
* #param y y co-ordinate for text placement
*/
public void drawString(String text, int x, int y)
{
graphic.drawString(text, x, y);
//canvas.repaint();
}
/**
* Erases a String on the Canvas.
* #param text the String to be displayed
* #param x x co-ordinate for text placement
* #param y y co-ordinate for text placement
*/
public void eraseString(String text, int x, int y)
{
Color original = graphic.getColor();
graphic.setColor(backgroundColour);
graphic.drawString(text, x, y);
graphic.setColor(original);
//canvas.repaint();
}
/**
* Draws a line on the Canvas.
* #param x1 x co-ordinate of start of line
* #param y1 y co-ordinate of start of line
* #param x2 x co-ordinate of end of line
* #param y2 y co-ordinate of end of line
*/
public void drawLine(int x1, int y1, int x2, int y2)
{
graphic.drawLine(x1, y1, x2, y2);
//canvas.repaint();
}
/**
* Draws a dot/pixel on the Canvas.
* #param x x co-ordinate of dot
* #param y y co-ordinate of dot
*/
public void drawDot(int x, int y)
{
graphic.drawLine(x, y, x, y);
//canvas.repaint();
}
/**
* Sets the foreground colour of the Canvas.
* #param newColour the new colour for the foreground of the Canvas
*/
public void setForegroundColour(Color newColour)
{
graphic.setColor(newColour);
}
/**
* Returns the current colour of the foreground.
* #return the colour of the foreground of the Canvas
*/
public Color getForegroundColour()
{
return graphic.getColor();
}
/**
* Sets the background colour of the Canvas.
* #param newColour the new colour for the background of the Canvas
*/
public void setBackgroundColour(Color newColour)
{
backgroundColour = newColour;
graphic.setBackground(newColour);
}
/**
* Returns the current colour of the background
* #return the colour of the background of the Canvas
*/
public Color getBackgroundColour()
{
return backgroundColour;
}
/**
* changes the current Font used on the Canvas
* #param newFont new font to be used for String output
*/
public void setFont(Font newFont)
{
graphic.setFont(newFont);
}
/**
* Returns the current font of the canvas.
* #return the font currently in use
**/
public Font getFont()
{
return graphic.getFont();
}
/**
* Sets the size of the canvas.
* #param width new width
* #param height new height
*/
public void setSize(int width, int height)
{
canvas.setPreferredSize(new Dimension(width, height));
Image oldImage = canvasImage;
canvasImage = canvas.createImage(width, height);
graphic = (Graphics2D)canvasImage.getGraphics();
graphic.drawImage(oldImage, 0, 0, null);
frame.pack();
}
/**
* Returns the size of the canvas.
* #return The current dimension of the canvas
*/
public Dimension getSize()
{
return canvas.getSize();
}
/**
* Waits for a specified number of milliseconds before finishing.
* This provides an easy way to specify a small delay which can be
* used when producing animations.
* #param milliseconds the number
*/
public void wait(int milliseconds)
{
try
{
Thread.sleep(milliseconds);
}
catch (Exception e)
{
// ignoring exception at the moment
}
}
/************************************************************************
* Nested class CanvasPane - the actual canvas component contained in the
* Canvas frame. This is essentially a JPanel with added capability to
* refresh the image drawn on it.
*/
private class CanvasPane extends JPanel
{
public void paint(Graphics g)
{
g.drawImage(canvasImage, 0, 0, null);
}
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
public class CreateButton extends JFrame implements ActionListener{
public void run() {
createAndShowGUI();
}
public CreateButton() {
// set layout for the frame
this.getContentPane().setLayout(new FlowLayout());
JButton button1 = new JButton();
button1.setText("closeApp");
//set actionlisteners for the buttons
button1.addActionListener(this);
// define a custom short action command for the button
button1.setActionCommand("closeApp");
// add buttons to frame
add(button1);
}
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new CreateButton();
//Display the window.
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void actionPerformed(ActionEvent ae) {
String action = ae.getActionCommand();
if (action.equals("closeApp")) {
System.exit(1);
}
}
}
import java.awt.*;
public class SchriftParameter
{
public Font setzteSchrift(){
Font f = new Font("Fixed",1,24);
return (f);
}
}
public class Farbengenerator
{
int r=0;
int g=0;
int b=0;
public void generiereFarbe(){
if (r<255&&g==0&&b==0){
r++;
}
else if (r==255&&g<255&&b==0){
g++;
}
else if (r>0&&g==255&&b==0){
r= r-1;
}
else if (r==0&&g==255&&b<255){
b++;
}
else if (r==0&&g>0&&b==255){
g=g-1;
}
else if (r<255&&g==0&&b==255){
r++;
}
else if (r==255&&g==0&&b>0){
b=b-1;
}
}
public int gibROT () {
return(r);
}
public int gibGRUEN () {
return(g);
}
public int gibBLAU () {
return(b);
}
}
import java.util.Date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
public class Zeit
{
public String erstelleZeit(){
DateFormat df = new SimpleDateFormat("HH:mm:ss");
Date d = new Date();
String uhr = df.format(d);
return (uhr);
}
}

Implement multiple bouncing balls

I've messed around with Java a little bit and I decided to take a course to learn some more and I have been assigned a fairly easy assignment. I have it mostly done and I know what's left must be simple, but I cannot seem to quite get it. So far I have been able to successfully create a program that has 1 bouncing ball, but I would now like to allow the user to input the amount of balls to bounce. I have tried a few different loops in my Ball class, but none of them work. Would anyone be willing to give a quick hand? I am almost sure it would require either an Array or ArrayList and just storing the balls in it but I have yet to find a solution that works. I have looked at other problems like this on the website but none have quite solved my problem. Thank you if you can help!
Main Class :
public class mainClass {
/**
/**
* Frame to hold a bouncing ball panel, implemented in the BallPanel class.
* Controls the animation of the ball via pauses and calls to BallPanel's move
* method.
*
* #author Michael Peterson modified by Mr O Aug 2012
*/
public static class BallTest extends JFrame {
// size of the window
private static final int WINDOW_WIDTH = 500;
private static final int WINDOW_HEIGHT = 300;
// panel containing the bouncing ball
private BallPanel ballPanel;
/**
* Pause command used to control the speed of the bouncing ball animation.
* Currently pauses for 20 ms. Use smaller values for faster animation and
* vice versa.
*/
public static void pause() {
try {
Thread.sleep(20); // pause for 20 ms
} catch (Exception e) {
System.out.println(e);
e.printStackTrace();
}//end of catch
}//end of pause method
/**
* Creates a new instance of BallTest
*/
public BallTest() {
super("Bouncing Ball"); // set frame name
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
setLayout(new BorderLayout());
ballPanel = new BallPanel();
add(ballPanel);
center(this);
setVisible(true);
// infinite animation loop, program halts when window is closed.
while (true) {
pause();
ballPanel.move(ballPanel);
}//end of while loop of animation
} //end of BallTest Constructor
/**
* Helper routine to center a frame on the screen (will cause problems if
* frame is bigger than the screen!)
*/
public static void center(JFrame frame) {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
Point center = ge.getCenterPoint();
int w = frame.getWidth();
int h = frame.getHeight();
int x = center.x - w / 2, y = center.y - h / 2;
frame.setBounds(x, y, w, h);
frame.validate();
}//end of center method
}//end of BallPanel Class
public static void main(String[] args) {
BallTest t = new BallTest(); //make a BallTest object
}//end of main method
}//end of Fall2012Lab11StarterCode class
Ball Class :
public class Ball extends JPanel {
private int bxCoord; //the ball's x coordinate
private int byCoord; //the ball's y coordinate
private int bHeight; //the ball's height
private int bWidth; //the ball's weight
private int bRise; //the ball's y change
private int bRun; //the ball's x change
private Color bColor; //the ball's color
//Constructor
public Ball() {
bxCoord = setStartBxCoord();
byCoord = setStartByCoord();
bHeight = setStartBHeight();
bWidth = setStartBWidth();
bRise = setStartBRise();
bRun = setStartBRun();
bColor = setStartColor();
}
/**
* The setters, getters, and initial value for the ball's x coordinate
*/
public void setBxCoord(int xCoord) {
bxCoord = xCoord;
}
public int setStartBxCoord() {
int xCoord;
xCoord = (int) (Math.random() * 51);
return xCoord;
}
public int getBxCoord() {
return bxCoord;
}
/**
* The setters, getters, and initial value for the ball's y coordinate
*/
public void setByCoord(int yCoord) {
bxCoord = yCoord;
}
public int setStartByCoord() {
int yCoord;
yCoord = (int) (Math.random() * 51);
return yCoord;
}
public int getByCoord() {
return byCoord;
}
/**
* The setters, getters, and initial value for the ball's x height
*/
public void setBHeight(int height) {
bHeight = height;
}
public int setStartBHeight() {
int height;
height = (int) (10 + Math.random() * 11);
return height;
}
public int getBHeight() {
return bHeight;
}
public void setBWidth(int width) {
bWidth = width;
}
/**
* The setters, getters, and initial value for the ball's x width
*/
public int setStartBWidth() {
int width;
width = (int) (10 + Math.random() * 11);
return width;
}
public int getBWidth() {
return bWidth;
}
/**
* The setters, getters, and initial value for the ball's rise
*/
public void setBRise(int rise) {
bRise = rise;
}
public int setStartBRise() {
int rise;
rise = (int) (Math.random() * 11);
return rise;
}
public int getBRise() {
return bRise;
}
/**
* The setters, getters, and initial value for the ball's run
*/
public void setBRun(int run) {
bRun = run;
}
public int setStartBRun() {
int run;
run = (int) (Math.random() * 11);
return run;
}
public int getBRun() {
return bRun;
}
/**
* The movement of the ball in the x and y direction
*/
public void moveX(){
bxCoord += bRun;
}
public void moveY(){
byCoord += bRise;
}
/**
* The setters, getters, and initial value for the ball's color
*/
public void setColor(Color color) {
bColor = color;
}
public Color setStartColor() {
int red = (int) (Math.random() * 256);
int green = (int) (Math.random() * 256);
int blue = (int) (Math.random() * 256);
Color ranColor = new Color(red, green, blue);
return ranColor;
}
public Color getbColor() {
return bColor;
}
/**
* Computes the next position for the balls and updates their positions.
*/
public void move(BallPanel ballPanel) {
// If ball is approaching a wall, reverse direction
if ((getBxCoord() < (0 - getBRun())) || (getBxCoord() > (ballPanel.getWidth() - getBWidth()))) {
setBRun(-getBRun());
}
if ((getByCoord() < (0 - getBRise())) || (getByCoord() > (ballPanel.getHeight() - getBHeight()))) {
setBRise(-getBRise());
}
// "Move" ball according to values in rise and run
moveX();
moveY();
} // end method move
}//end of Ball Class
Ball Panel Class :
public class BallPanel extends JPanel {
Ball ball = new Ball(); //creat a ball.
/**
* Creates a new instance of BallPanel
*/
public BallPanel() {
super();
}
/**
* The move method moves the ball and repaints the panel
* PreCondtion: A panel containing a ball has been created
* PostCondition: The position of a ball on the panel has moved. The panell
* is repainted with the ball in the new position.
* #param ballPanel The name of the panel on which the ball is found
*/
public void move(BallPanel ballPanel) {
ball.move(ballPanel);
repaint();
}
/**
* Paints the balls at their current positions within the panel.
* PreCondition: A graphics object has been created and needs to be displayed
* PostCondition: The graphics object g has been displayed
* #param g The graphic object to be displayed
*/
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.black); // set color black
g.fillRect(0, 0, getWidth(), getHeight()); // paint background
// Paint the Ball
g.setColor(ball.getbColor());
g.fillOval(ball.getBxCoord(), ball.getByCoord(),
ball.getBWidth(), ball.getBHeight());
}//end of paintComponent method
}//end of BallPanel class
Well I'm answering you purely on previous codes i have done similar to this, because I didn't have the time to test out yours.
Your ballPanel class should look something more like this:
import java.util.ArrayList;
public class BallPanel extends JPanel{
private ArrayList<Ball> BallList = new ArrayList<Ball>();
private int num;
public BallPanel(int numberOfBalls){
super();
num = numberOfBalls;
for(int i = 0; i<num; i++){BallList.add(new Ball());}
}
//the rest of your methods, using for loops for the balls
Also I think you can use this instead of ArrayList (this is easier):
Ball[] BallList = new Ball[numberOfBalls];
then an example of your move method should look like this:
public void move(BallPanel ballPanel){
for(int i = 0; i<num; i++){
BallList[i].move(ballPanel);
}
repaint();
}
I had a similar issues with a Bouncing Ball program. Tried the previously posted code, but the public void move(BallPanel area isn't working. When I access an array in that location the ball stops moving. Here is my current code for move:
public void move(BallPanel ballPanel, ArrayList<Ball> ballList) {
for(int i = 0; i<1; i++){
System.out.println("mmm" + i);
ballList.get(i).move(ballPanel);
}
repaint();
Secondly as shown the paintComponent area above, only ball is used to paint the ball. Is that OK that paintComponent is called multiple times but only has a variable ball in it. Here is what that section looks like:
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.black); // set color black
g.fillRect(0, 0, getWidth(), getHeight()); // paint background
// Paint the Ball
g.setColor(ball.getbColor());
g.fillOval(ball.getBxCoord(), ball.getByCoord(),
ball.getBWidth(), ball.getBHeight());

Why is the class CanvasPane not included in the Java API?

** Why is the class CanvasPane not included in the Java API?.
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
/**
* Class Canvas - a class to allow for simple graphical
* drawing on a canvas.
*
* #author Michael Kolling (mik)
* #author Bruce Quig
*
* #version 2008.03.30
*/
public class Canvas
{
private JFrame frame;
private CanvasPane canvas;
private Graphics2D graphic;
private Color backgroundColor;
private Image canvasImage;
/**
* Create a Canvas with default height, width and background color
* (300, 300, white)
* #param title title to appear in Canvas Frame
*/
public Canvas(String title)
{
this(title, 300, 300, Color.white);
}
/**
* Create a Canvas with default background color (white).
* #param title title to appear in Canvas Frame
* #param width the desired width for the canvas
* #param height the desired height for the canvas
*/
public Canvas(String title, int width, int height)
{
this(title, width, height, Color.white);
}
/**
* Create a Canvas.
* #param title title to appear in Canvas Frame
* #param width the desired width for the canvas
* #param height the desired height for the canvas
* #param bgClour the desired background color of the canvas
*/
public Canvas(String title, int width, int height, Color bgColor)
{
frame = new JFrame();
canvas = new CanvasPane();
frame.setContentPane(canvas);
frame.setTitle(title);
canvas.setPreferredSize(new Dimension(width, height));
backgroundColor = bgColor;
frame.pack();
}
/**
* Set the canvas visibility and brings canvas to the front of screen
* when made visible. This method can also be used to bring an already
* visible canvas to the front of other windows.
* #param visible boolean value representing the desired visibility of
* the canvas (true or false)
*/
public void setVisible(boolean visible)
{
if(graphic == null) {
// first time: instantiate the offscreen image and fill it with
// the background color
Dimension size = canvas.getSize();
canvasImage = canvas.createImage(size.width, size.height);
graphic = (Graphics2D)canvasImage.getGraphics();
graphic.setColor(backgroundColor);
graphic.fillRect(0, 0, size.width, size.height);
graphic.setColor(Color.black);
}
frame.setVisible(true);
}
/**
* Provide information on visibility of the Canvas.
* #return true if canvas is visible, false otherwise
*/
public boolean isVisible()
{
return frame.isVisible();
}
/**
* Draw the outline of a given shape onto the canvas.
* #param shape the shape object to be drawn on the canvas
*/
public void draw(Shape shape)
{
graphic.draw(shape);
canvas.repaint();
}
/**
* Fill the internal dimensions of a given shape with the current
* foreground color of the canvas.
* #param shape the shape object to be filled
*/
public void fill(Shape shape)
{
graphic.fill(shape);
canvas.repaint();
}
/**
* Fill the internal dimensions of the given circle with the current
* foreground color of the canvas.
*/
public void fillCircle(int xPos, int yPos, int diameter)
{
Ellipse2D.Double circle = new Ellipse2D.Double(xPos, yPos, diameter, diameter);
fill(circle);
}
/**
* Fill the internal dimensions of the given rectangle with the current
* foreground color of the canvas. This is a convenience method. A similar
* effect can be achieved with the "fill" method.
*/
public void fillRectangle(int xPos, int yPos, int width, int height)
{
fill(new Rectangle(xPos, yPos, width, height));
}
/**
* Erase the whole canvas.
*/
public void erase()
{
Color original = graphic.getColor();
graphic.setColor(backgroundColor);
Dimension size = canvas.getSize();
graphic.fill(new Rectangle(0, 0, size.width, size.height));
graphic.setColor(original);
canvas.repaint();
}
/**
* Erase the internal dimensions of the given circle. This is a
* convenience method. A similar effect can be achieved with
* the "erase" method.
*/
public void eraseCircle(int xPos, int yPos, int diameter)
{
Ellipse2D.Double circle = new Ellipse2D.Double(xPos, yPos, diameter, diameter);
erase(circle);
}
/**
* Erase the internal dimensions of the given rectangle. This is a
* convenience method. A similar effect can be achieved with
* the "erase" method.
*/
public void eraseRectangle(int xPos, int yPos, int width, int height)
{
erase(new Rectangle(xPos, yPos, width, height));
}
/**
* Erase a given shape's interior on the screen.
* #param shape the shape object to be erased
*/
public void erase(Shape shape)
{
Color original = graphic.getColor();
graphic.setColor(backgroundColor);
graphic.fill(shape); // erase by filling background color
graphic.setColor(original);
canvas.repaint();
}
/**
* Erases a given shape's outline on the screen.
* #param shape the shape object to be erased
*/
public void eraseOutline(Shape shape)
{
Color original = graphic.getColor();
graphic.setColor(backgroundColor);
graphic.draw(shape); // erase by drawing background color
graphic.setColor(original);
canvas.repaint();
}
/**
* Draws an image onto the canvas.
* #param image the Image object to be displayed
* #param x x co-ordinate for Image placement
* #param y y co-ordinate for Image placement
* #return returns boolean value representing whether the image was
* completely loaded
*/
public boolean drawImage(Image image, int x, int y)
{
boolean result = graphic.drawImage(image, x, y, null);
canvas.repaint();
return result;
}
/**
* Draws a String on the Canvas.
* #param text the String to be displayed
* #param x x co-ordinate for text placement
* #param y y co-ordinate for text placement
*/
public void drawString(String text, int x, int y)
{
graphic.drawString(text, x, y);
canvas.repaint();
}
/**
* Erases a String on the Canvas.
* #param text the String to be displayed
* #param x x co-ordinate for text placement
* #param y y co-ordinate for text placement
*/
public void eraseString(String text, int x, int y)
{
Color original = graphic.getColor();
graphic.setColor(backgroundColor);
graphic.drawString(text, x, y);
graphic.setColor(original);
canvas.repaint();
}
/**
* Draws a line on the Canvas.
* #param x1 x co-ordinate of start of line
* #param y1 y co-ordinate of start of line
* #param x2 x co-ordinate of end of line
* #param y2 y co-ordinate of end of line
*/
public void drawLine(int x1, int y1, int x2, int y2)
{
graphic.drawLine(x1, y1, x2, y2);
canvas.repaint();
}
/**
* Sets the foreground color of the Canvas.
* #param newColor the new color for the foreground of the Canvas
*/
public void setForegroundColor(Color newColor)
{
graphic.setColor(newColor);
}
/**
* Returns the current color of the foreground.
* #return the color of the foreground of the Canvas
*/
public Color getForegroundColor()
{
return graphic.getColor();
}
/**
* Sets the background color of the Canvas.
* #param newColor the new color for the background of the Canvas
*/
public void setBackgroundColor(Color newColor)
{
backgroundColor = newColor;
graphic.setBackground(newColor);
}
/**
* Returns the current color of the background
* #return the color of the background of the Canvas
*/
public Color getBackgroundColor()
{
return backgroundColor;
}
/**
* changes the current Font used on the Canvas
* #param newFont new font to be used for String output
*/
public void setFont(Font newFont)
{
graphic.setFont(newFont);
}
/**
* Returns the current font of the canvas.
* #return the font currently in use
**/
public Font getFont()
{
return graphic.getFont();
}
/**
* Sets the size of the canvas.
* #param width new width
* #param height new height
*/
public void setSize(int width, int height)
{
canvas.setPreferredSize(new Dimension(width, height));
Image oldImage = canvasImage;
canvasImage = canvas.createImage(width, height);
graphic = (Graphics2D)canvasImage.getGraphics();
graphic.drawImage(oldImage, 0, 0, null);
frame.pack();
}
/**
* Returns the size of the canvas.
* #return The current dimension of the canvas
*/
public Dimension getSize()
{
return canvas.getSize();
}
/**
* Waits for a specified number of milliseconds before finishing.
* This provides an easy way to specify a small delay which can be
* used when producing animations.
* #param milliseconds the number
*/
public void wait(int milliseconds)
{
try
{
Thread.sleep(milliseconds);
}
catch (InterruptedException e)
{
// ignoring exception at the moment
}
}
/************************************************************************
* Inner class CanvasPane - the actual canvas component contained in the
* Canvas frame. This is essentially a JPanel with added capability to
* refresh the image drawn on it.
*/
private class CanvasPane extends JPanel
{
public void paint(Graphics g)
{
g.drawImage(canvasImage, 0, 0, null);
}
}
}
Why it should be? I mean its a BlueJ extension class, AFAIK. Similar questions may come to the mind regarding StringUtils, or NumberUtils. IMHO, these two really qualifies to be there in the original Java API. :)
One huge reason is that it has one of the worst named methods I have ever seen in a Java class:
public void wait(int milliseconds)
Try calling wait(100) on it and watch it work without synchronisation and obviously do something completely different from java.lang.Object.wait(long). This would be a nightmare to do in production.
What on earth is such a method doing in a class named Canvas?

Categories