I'm using Swing to create a small GUI in Java. All I am trying to get it to do is take an ArrayListof Circles and draw them. I've run into two problems:
1) I have to call my draw method repeatedly before it draws the circle. If I just call my draw method once nothing happens, I get a blank drawing. If I call it in a loop that runs for less than 30 milliseconds it only draws the first of two circles that I want to draw. Finally, if I call it for more than 30 milliseconds it draws both circles I am trying to draw.
and
2) When I move one of the circles, I get a "flicker" on the drawing.
I'm not too familiar with Swing programming. I've looked at sample code and watched a few videos - and what I have looks right to me. But I figure I must have messed something up, because it doesn't look like this in the videos I've watched.
Here is my GUI class:
package gui;
import draw.*;
import java.util.List;
import javax.swing.*;
public class GUI extends JFrame {
private CirclePainter drawingBoard = new CirclePainter();
public GUI()
{
setSize(500, 500);
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
this.setVisible(true);
this.add(drawingBoard);
drawingBoard.setVisible(true);
}
public void draw(List<Circle> circles)
{
drawingBoard.paintComponent(drawingBoard.getGraphics(), circles);
}
}
my CirclePainter class
package gui;
import draw.Circle;
import javax.swing.*;
import java.awt.*;
import java.util.List;
class CirclePainter extends JPanel
{
public void paintComponent(Graphics graphics, List<Circle> circles)
{
super.paintComponent(graphics);
for(Circle circle : circles)
graphics.fillOval(circle.getX(), circle.getY(), circle.getRadius() * 2, circle.getRadius() * 2);
}
}
EDIT: redacted some code since this is for a school project. The remaining code should be enough for someone visiting in the future to still understand the question.
paintComponent(...) directly as you're doing.repaint() on a component when necessary.getGraphics() call on a component. Instead, draw with the Graphics object provided in the paintComponent method.while (true) loops in a Swing GUI as you risk tying up the Swing event thread and freezing the GUI. Use a Swing Timer for simple animations.contains(Point p) method that will help you determine if a mouse click lands inside of your circle.g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON); where g2 is your Graphics2D object.paintComponent method is not a true paintComponent override and thus won't work correctly. It should be a protected method, not public, it should have one parameter, a Graphics object, and nto a second parameter, and you should place the @Override annotation above it.For example, please have a look at this answer of mine to a similar problem.
An example of a paintComponent method that centers the circles on _x and _y and that uses rendering hints:
class CirclePainter extends JPanel implements Iterable<Circle> {
private static final int PREF_W = 500;
private static final int PREF_H = PREF_W;
private CircleList circleList = new CircleList();
@Override
protected void paintComponent(Graphics graphics) {
super.paintComponent(graphics);
Graphics2D g2 = (Graphics2D) graphics;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
for (Circle circle : circleList) {
// if x and y are the center points, then you must subtract the radius.
int x = circle.getX() - circle.getRadius();
int y = circle.getY() - circle.getRadius();
int width = circle.getRadius() * 2;
int height = width;
g2.fillOval(x, y, width, height);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With