kezie
kezie

Reputation: 3

how to use the wait(long timeout) on jpanel

I am taking an introductory java class and I have an inheritance related problem. I have to implement a system that has classes for various figures. the superclass is Figures and subclasses are Circle, Box and Rectangle and I am supposed to output the figures in the JPanel. I have designed all the classes and my code is below but I need to define the center() method on the figure class which when called on an object should draw and also erase the object. so within the main method of the JPanel class, I want to use the center() method to draw the three shapes and use the wait(long timeout) method to make the shapes change to random positions after 15 seconds.

import java.awt.Graphics;
import javax.swing.JPanel;

public abstract class Figure extends JPanel {

protected int xCoord;
protected int yCoord;

public Figure() {
}

public void erase() {

}

public void draw() {

}

public void center() {

}
}

the rectangle sub class is:

import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;

public class Rectangle extends Figure {
int width;
int height;

public Rectangle() {

    this.width = 0;
    this.height = 0;
}

public Rectangle(int xCoord, int yCoord, int width, int height)


{
    this.xCoord = xCoord;
    this.yCoord = yCoord;
    this.width = width;
    this.height = height;
}

public void draw(Graphics g) {
    super.paintComponent(g);
    g.setColor(Color.BLACK);
    g.fillRect(xCoord, yCoord, width, height);
}

public void erase(Graphics g) {
    super.paintComponent(g);
    g.setColor(Color.BLACK);
    g.fillRect(0, 0, 0, 0);
}

}

the circle subclass:

public class Circle extends Figure {

private int radius;

 public Circle ()
  {
     this.radius = 0;
  }

 public Circle (int xCoord, int yCoord, int radius)          
  {
     this.xCoord = xCoord;
     this.yCoord = yCoord;
     this.radius = radius;
  }

 public void draw(Graphics g){
      super.paintComponent(g);
      g.setColor(Color.BLACK);
      g.fillOval(xCoord, yCoord, radius, radius);
  }

 public void erase(Graphics g){
      super.paintComponent(g);
      g.setColor(Color.BLACK);
      g.fillOval(0,0,0,0);
  }

}

the box subclass:

import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;

public class Box extends Figure {

private int edgeLength;

public Box() {
    this.edgeLength = 0;
}

public Box(int xCoord, int yCoord, int edgeLength)// Creating Rectangle
                                                    // Class given width and
                                                    // height
{
    this.xCoord = xCoord;
    this.yCoord = yCoord;
    this.edgeLength = edgeLength;
}

public void draw(Graphics g) {
    super.paintComponent(g);
    g.setColor(Color.BLACK);
    g.fillRect(xCoord, yCoord, edgeLength, edgeLength);
}

public void erase(Graphics g) {
    super.paintComponent(g);
    g.setColor(Color.BLACK);
    g.fillRect(0, 0, 0, 0);
}

}

the JPanel class

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.LayoutManager;
import java.awt.Point;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class SamplePanel extends JPanel {

private static final int PANEL_HEIGHT = 400;
private static final int PANEL_WIDTH = 400;
Rectangle rect = new Rectangle(75, 85, 50,30);
Circle circle = new Circle(275, 75, 50);
Box box = new Box (75, 275, 50);

public SamplePanel() {

    setPreferredSize(new Dimension(PANEL_HEIGHT, PANEL_WIDTH));
    setBackground(Color.WHITE);
    //Rectangle rect = new Rectangle(100, 100, 15,10);
}

public void paintComponent(Graphics g) {
    super.paintComponent(g);
    rect.draw(g);
    circle.draw(g);
    box.draw(g);
    g.drawLine(200, 0, 200, 400);
    g.drawLine(0, 200, 400, 200);




}

/**
 * @param layout
 */
public SamplePanel(LayoutManager layout) {
    super(layout);
}

/**
 * @param isDoubleBuffered
 */
public SamplePanel(boolean isDoubleBuffered) {
    super(isDoubleBuffered);
}

/**
 * @param layout
 * @param isDoubleBuffered
 */
public SamplePanel(LayoutManager layout, boolean isDoubleBuffered) {
    super(layout, isDoubleBuffered);
}

public static void main(String[] args) {
    JFrame frame = new JFrame("Window Title Here");
    SamplePanel panel = new SamplePanel();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(panel);
    frame.pack();
    frame.setVisible(true);
    Figure box = new Box(75, 275, 50);


}   

}

Upvotes: 0

Views: 237

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347314

Answer...

How to use Swing Timers

It is safe to use within the context of Swing as it won't block the Event Dispatching Thread while waiting and will generate notifications within the context of the Event Dispatching Thread, making it safe to update the UI from.

Observations...

Your basic design, while correct in concept, is implemented in correctly. I'd would strongly discourage you from using JPanel in this way. Components have a particular life cycle which you're not managing correctly, which could cause no end of issues.

Instead, go right back to basics. What is it the shape should be able to?

public interface Figure {
    public void draw(Graphics2D g2d);
    public Rectangle getBounds();
    public void setBounds(Rectangle bounds);
}

Here, it's capable of been painted and has a concept of size and position (yes, you can use an abstract class, but this removes all requirements on the base implementation, making it far more flexible)

Because I imagine most of the implementations are going to be basically the same, I can use an abstract class to implement the core functionality...

public abstract class AbstractFigure implements Figure {
    private Rectangle bounds;

    @Override
    public Rectangle getBounds() {
        return bounds;
    }

    @Override
    public void setBounds(Rectangle bounds) {
        this.bounds = bounds;
    }
    
}

Based on your needs, you might be able to create a few abstract classes which implement the functionality different, but the basic idea is to see what functionality is common to all the implementations and reduce the amount of duplicate code you generate.

Then you can start implementing your concrete classes...

public class RectangleFigure extends AbstractFigure {

    public RectangleFigure(Rectangle bounds) {
        setBounds(bounds);
    }

    @Override
    public void draw(Graphics2D g2d) {
        g2d.setColor(Color.BLACK);
        g2d.fill(getBounds());
    }

}

But where's the "erase" method you ask? Well, erase is just the absence of painting, so, when you want to "erase" a shape, remove it from the painting process and repaint the container, shape is erased

This is suggests to me that you need to have a look at Painting in AWT and Swing and Performing Custom Painting to better understand how painting works in Swing.

"Where's the center method?" I hear you ask. Okay, you "could" have a center method in the Figure, the problem is, Figure has no concept of the parent container, is you'd have to pass the size of the container to it. Not difficult, I'd argue, however, this really isn't a function of the Figure, but a function of the container, so I'd have the center method implemented there, since you want to change the position of the Figures anyway, it makes sense (to me) to all that wrapped up in the container

Upvotes: 1

Related Questions