I'm currently trying to make a game with a GUI that needs to paint new things on the screen on button clicks. For example:
public class GUI() extends JPanel {
public void paintComponent() {
/*
*Basic initial set up here
*/
// ***** Call method here on mouse click *****
}
public void setUpGUI() {
JFrame mainFrame = new JFrame();
GUI paintGUI = new GUI();
clickDetector click = new clickDetector();
mainFrame.addMouseListener(click);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setSize(500, 500);
mainFrame.getContentPane().add(paintGUI);
mainFrame.setVisible(true);
}
public static void main(String args[]) {
GUI gui = new GUI();
gui.setUpGUI();
}
}
I need to implement a method in the // ***** Call method here on mouse click ***** that will paint on the new additions to the frame (in my case these are circles that represent pieces on the board) but I'm unsure of how to do this on a button click. How can I repaint the frame each time the mouse is clicked so that I can modify my game board?
----EDIT----
Here is my paintComponent code, along with the listener being used to repaint.
public void paintComponent(Graphics g) {
super.paintComponent(g);
System.out.println("Method called");
g.setColor(Color.red);
for(int y = 0; y < 6; y++) {
for(int x = 0; x < 7; x++) {
g.fillOval(x*70 + 10, y*70 + 10, 50, 50);
}
}
g.setColor(Color.BLACK);
g.fillRect(0, 430, 500, 50);
g.setColor(Color.white);
g.drawString("CONNECT FOUR", 250, 450);
g.setColor(Color.LIGHT_GRAY);
click.paintPiece(g);
}
public void mouseClicked(MouseEvent e) {
this.repaint();
}
Here is the method that paintComponent should be calling, but is not
public void paintPiece(Graphics g) {
int x = getMouseX() + 10;
int y = mover.getRow() + 10;
g.fillOval(x, y, 50, 50);
}
Just create a mouse listener:
MouseListener listen = new MouseListener()
{
void mouseClicked(MouseEvent e){}
void mouseReleased(MouseEvent e){}
void mousePressed(MouseEvent e){paintGUI.repaint();}
void mouseExited(MouseEvent e){}
void mouseEntered(MouseEvent e){}
};
paintGUI.addMouseListener(listen);
Every time you click inside of the JPanel, you should now see it repaint. Likewise, if you want to update when a JButton is pressed, just use ActionListener instead:
ActionListener listen = new ActionListener()
{
public void actionPerformed(ActionEvent e){paintGUI.repaint();}
}
button.addActionListener(listen);
This should be placed in your setUpGUI() method.
Add a Action Event listener to the button.
Oracle Docs Action Event Listener
In the actionPerformed method add whatever needs to be added then call
repaint();
This changes will let you paint a rectangle each time you click on the frame
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GUI extends JPanel implements MouseListener{
private Rectangle rect;
private int width = 100;
private int height = 100;
public GUI(int x, int y, int width, int height)
{
rect = new Rectangle(x, y, width, height);
}
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D)g;
g2d.draw(rect);
}
public void mouseClicked(MouseEvent e) {
rect = new Rectangle(e.getX(), e.getY(), width, height);
repaint();
}
#Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
public void setUpGUI() {
JFrame mainFrame = new JFrame();
mainFrame.addMouseListener(this);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setSize(500, 500);
mainFrame.getContentPane().add(this);
mainFrame.setVisible(true);
}
public static void main(String args[]) {
GUI gui = new GUI(0,0,100,100);
gui.setUpGUI();
}
}
Notice the MouseListener was implemented by the GUI class and when you are trying to initialize the MouseListener for the frame, you are just putting this as parameter, which will refer to the GUI class and therefore to your JPanel
I have to draw some ovals in Java, and at click to change their color.
For the beginning I tried to change the color after 20 ms, but it doesn't work.
My code is:
public class MyComponentNew extends Frame {
public Graphics2D g2d;
public MyComponentNew(String title) {
super(title);
setSize(400, 550);
}
#Override
public void paint(Graphics g) {
this.g2d = (Graphics2D) g;
this.g2d.setColor(Color.red);
this.g2d.fillOval(10, 55, 50, 100);
}
public void changeColor () {
this.g2d.setColor(Color.blue);
this.g2d.fillOval(10, 55, 50, 100);
}
}
And in the class with main method I have:
MyComponentNew m;
m = new MyComponentNew("Fereastra cu baloane");
m.setVisible(true);
m.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent we) {
System.exit(0);
}
});
try {
Thread.sleep(20);
} catch(InterruptedException e) {}
m.changeColor();
The color of the oval remains red.
You need to look at Performing Custom Painting. You kinda have the concept, but your changeColor method isn't going to do anything for you.
Some things to note.
First you need to add a MouseListener. See more at How to Write MouseListeners
Second what you want to do is just have a Color color variable. You use that variable to set the color. Your method changeColor should only change the color and repaint(). Something like
public class MyComponentNew extends JPanel {
private Color color = Color.BLUE;
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(color);
}
public void changeColor() {
if (color == Color.BLUE) {
color = Color.RED:
} else {
color = color.BLUE;
}
repaint();
}
}
Third notice how I use JPanel instead of JFrame. This is the preferred approach.
Fourth you should be using Swing and not AWT.
Here's a full example, with those points above
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class CircleChangeColor extends JPanel {
private Ellipse2D circle = new Ellipse2D.Double(0, 0, 200, 200);
private Color color = Color.blue;
public CircleChangeColor() {
addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent e) {
if (circle.contains(e.getPoint())) {
changeColor();
}
}
});
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setColor(color);
g2.fill(circle);
}
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
public void changeColor() {
if (color == Color.BLUE) {
color = Color.RED;
} else {
color = color.BLUE;
}
repaint();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
JFrame frame = new JFrame();
frame.add(new CircleChangeColor());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
});
}
}
The reason is that your paint method will be called periodically by AWT and it will quickly draw over your new blue oval with the original red one. You can get the behavior you want by storing the oval color in a member variable, reading it in the paint method, and changing it in your changeColor method.
public class MyComponentNew extends Frame {
private Color ovalColor;
public MyComponentNew(String title) {
super(title);
setSize(400, 550);
ovalColor = Color.red; // initial oval color
}
#Override
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D)g;
g2d.setColor(ovalColor); // use whatever the current color is
g2d.fillOval(10, 55, 50, 100);
}
public void changeColor() {
ovalColor = Color.blue; // change color
repaint(); // force redraw with new color
}
}
You need to call the repaint() method on the JFrame, but as the code is, the red oval will be drawn again since the paint-method will be called. You need to alter it something like this:
import java.awt.Graphics2D;
public class MyComponentNew extends Frame{
public Graphics2D g2d;
public Color color = Color.red;
public MyComponentNew(String title) {
super(title);
setSize(400, 550);
}
#Override
public void paint(Graphics g) {
this.g2d = (Graphics2D) g;
this.g2d.setColor(color);
this.g2d.fillOval(10, 55, 50, 100);
//this.g2d.drawLine (WIDTH, WIDTH, WIDTH, WIDTH);
}
public void changeColor (){
color = Color.blue;
this.repaint();
}
}
The color is now an instance variable which is set during the changeColor method.
/Nick
I have this simple paint code that should draw but instead it moves the oval around the panel.
When I remove super.paintComponent(g) line the program works it paints and not just move the oval, but I keep reading that we should not remove this line, so what can I do to leave the line in but still get the desired results?
class OraclePaint extends JFrame {
public static void main(String[] args) {
OraclePaint ss = new OraclePaint();
ss.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ss.add(new MyPanel());
ss.setSize(250, 200);
ss.setVisible(true);
}
}
class MyPanel extends JPanel {
private int x = -10, y = -10;
public MyPanel() {
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent event) {
x = event.getX();
y = event.getY();
repaint();
}
}); // end call to addMouseMotionListener
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.fillOval(x, y, 22, 22);
}
}
Based on the description, I assume that you want something like "a simple paint program".
It is correct to invoke super.paintComponent(g) as the first line of an overridden paintComponent. And it is true that this erases the background (that is, everything that was painted before will be deleted).
In Swing, everything that you want to paint has to be painted in the paintComponent method (or in any method that is called from there, and receives the same Graphics object).
If you want to "save" everything that you have painted, you have to paint everything into an image (that is, into a BufferedImage), and paint this image in your paintComponent method.
There are some other issues with the code, but without changing too much of the remaining code, this could roughly (!) be achieved like this:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
class OraclePaint extends JFrame {
public static void main(String[] args) {
OraclePaint ss = new OraclePaint();
ss.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ss.add(new MyPanel());
ss.setSize(250, 200);
ss.setVisible(true);
}
}
class MyPanel extends JPanel {
private BufferedImage image = null;
public MyPanel() {
addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent event) {
if (image != null) {
// Paint into the image
Graphics g = image.getGraphics();
g.setColor(Color.BLACK);
g.fillOval(event.getX(), event.getY(), 22, 22);
g.dispose();
repaint();
}
}
}); // end call to addMouseMotionListener
}
// Make sure that the image is not 'null' and that
// it has the same size as this panel
private void validateImage()
{
if (image == null)
{
image = new BufferedImage(getWidth(), getHeight(),
BufferedImage.TYPE_INT_ARGB);
}
if (image.getWidth() != getWidth() || image.getHeight() != getHeight())
{
BufferedImage newImage = new BufferedImage(getWidth(), getHeight(),
BufferedImage.TYPE_INT_ARGB);
Graphics g = newImage.getGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
image = newImage;
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
validateImage();
g.drawImage(image, 0, 0, null);
}
}
change your MyPanel to this:
class MyPanel extends JPanel
{
private int x2 = 0, y2 = 0;
private int x1 = 0, y1 = 0;
public MyPanel()
{
addMouseMotionListener(new MouseMotionAdapter()
{
public void mouseDragged( MouseEvent event )
{
x2 = event.getX();
y2 = event.getY();
repaint();
}
}
); // end call to addMouseMotionListener
addMouseListener(new MouseListener() {
#Override
public void mousePressed(MouseEvent e) {
x1 = e.getX();
y1 = e.getY();
}
});
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.fillOval(x1, y1, x2, y2);
}
}
I have a 3x3 check board-like image rendered on a JPanel which is added onto a JFrame. Then I have 9 more JPanels (1 on top of each square) and on click something needs to be drawn on the corresponding square. My problem is that it only works for the top-left square. The rest of the drawings seem to be drawn below the checkboard image. So if I comment out the part that loads the checkboard image,and click as if they were there then the drawings appear correctly. I get the same result with a layered pane. Absolute positioning is used and the coordinates seem to be correct since if I remove the checkboard image then the drawings appear where they should and the drawings do not occupy more than a square.
My code is structured as follows:
'main' class creates the frame and adds an instance of another class which extends JPanel and which also draws the checkboard image using paintComponent(Graphics g).
'main' class has also 9 instances added of a class that extends JPanel and draws something on a mouse click using paintComponent(Graphics g). Each instance is placed on top of a square
Please note that because I was going to do it with just Rectangles I named the second class Rectangles but it is rectangualar JPanels not java Rectangle instances
Code:
public class Main3
{
private JFrame frame=new JFrame("");
private Rectangles rect00=new Rectangles(0,0,129,129);
private Rectangles rect01=new Rectangles(136,0,129,129);
private Rectangles rect02=new Rectangles(268,0,129,129);
private Rectangles rect10=new Rectangles(0,136,129,129);
private Rectangles rect11=new Rectangles(134,136,129,129);
private Rectangles rect12=new Rectangles(269,137,129,129);
private Rectangles rect20=new Rectangles(0,270,129,129);
private Rectangles rect21=new Rectangles(136,269,129,129);
private Rectangles rect22=new Rectangles(269,270,129,129);
public void Display()
{
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setLayout(null);
frame.setSize(600,400);
sub inter=new sub();
inter.setLayout(null);
inter.setBounds(0,0,600,400);
inter.setSize(600,400);
rect00.setBounds(rect00.getX(),rect00.getY(),rect00.getWidth(),rect00.getHeight());
rect01.setBounds(rect01.getX(),rect01.getY(),rect01.getWidth(),rect01.getHeight());
rect02.setBounds(rect02.getX(),rect02.getY(),rect02.getWidth(),rect02.getHeight());
rect10.setBounds(rect10.getX(),rect10.getY(),rect10.getWidth(),rect10.getHeight());
rect11.setBounds(rect11.getX(),rect11.getY(),rect11.getWidth(),rect11.getHeight());
rect12.setBounds(rect12.getX(),rect12.getY(),rect12.getWidth(),rect12.getHeight());
rect20.setBounds(rect20.getX(),rect20.getY(),rect20.getWidth(),rect20.getHeight());
rect21.setBounds(rect21.getX(),rect21.getY(),rect21.getWidth(),rect21.getHeight());
rect22.setBounds(rect22.getX(),rect22.getY(),rect22.getWidth(),rect22.getHeight());
rect00.setOpaque(false);
rect01.setOpaque(false);
rect02.setOpaque(false);
rect10.setOpaque(false);
rect11.setOpaque(false);
rect12.setOpaque(false);
rect20.setOpaque(false);
rect21.setOpaque(false);
rect22.setOpaque(false);
inter.add(rect00);
inter.add(rect01);
inter.add(rect02);
inter.add(rect10);
inter.add(rect11);
inter.add(rect12);
inter.add(rect20);
inter.add(rect21);
inter.add(rect22);
frame.add(inter);
frame.setResizable(false);
frame.setVisible(true);
}
public static void main(String args[])
{
new main().Display();
}
private class sub extends JPanel
{
private BufferedImage image;
public sub ()
{
try
{
image=ImageIO.read(new File("image.jpg"));
}
catch (IOException e)
{
e.printStackTrace();
}
}
#Override
public Dimension getPreferredSize()
{
return (new Dimension(600,400));
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(image, 0, 0, null);
}
}
}
This is the other class
public class Rectangles extends JPanel implements MouseListener
{
private int Posx;
private int Posy;
private int width;
private int height;
private boolean selected=false;
public Rectangles(int Posx,int Posy,int width,int height)
{
this.Posx=Posx;
this.Posy=Posy;
this.width=width;
this.height=height;
this.addMouseListener(this);
}
#Override
protected void paintComponent(Graphics g)
{
if(selected==true)
{
Graphics2D g2 = (Graphics2D) g;
super.paintComponent(g2);
g2.setColor(new Color(250, 235, 215));
g2.drawRect(Posx,Posy,width,height);
Graphics2D g3=(Graphics2D)g;
g2.setColor(new Color(0,0,0));
g3.setStroke(new BasicStroke(20));
g3.drawLine(Posx,Posy,Posx+width,Posy+height);
g3.drawLine(Posx+width,Posy,Posx,Posy+height);
}
}
public int getX()
{
return Posx;
}
public int getY()
{
return Posy;
}
public int getWidth()
{
return width;
}
public int getHeight()
{
return height;
}
public void setSelected()
{
selected=true;
}
#Override
public void mouseClicked(MouseEvent arg0)
{
}
#Override
public void mouseEntered(MouseEvent arg0)
{
}
public void mouseExited(MouseEvent arg0)
{
}
#Override
public void mousePressed(MouseEvent arg0)
{
}
#Override
public void mouseReleased(MouseEvent arg0)
{
selected=true;
repaint();
}
}
1) You dont honor the components paint chain.
As per java docs for paintComponent(Graphics g):
Further, if you do not invoker super's implementation you must honour
the opaque property, that is if this component is opaque, you must
completely fill in the background in a non-opaque color. If you do not
honor the opaque property you will likely see visual artifacts.
2) super.paintComponent would in most cases be the first call in the method.
3) But there is more, your cast to Graphics2D twice, that should not be done:
Graphics2D g2 = (Graphics2D) g;
...
Graphics2D g3=(Graphics2D)g;
omit the g3 its not needed you already have casted to a Graphics2D object
4) Another problem lies here in sub class. You do this in your main code:
inter.add(rect00);
inter.add(rect01);
...
but in inter which is your variable name for the instance of sub class you only have:
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(image, 0, 0, null);
}
Thus it will only draw a single image no matter how many rectangles you add!
Also dont do
g2.drawLine(Posx, Posy, Posx + width, Posy + height); rather
g2.drawLine(0, 0, Posx + width, Posy + height); as the JPanel has been added at co-ordinates x and y on its container, when you draw on the JPanel we want to start at the top left i.e 0,0, changing the value would move the image further down on its conatiner
See fixed code here:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test {
private JFrame frame = new JFrame("");
private Rectangles rect00 = new Rectangles(0, 0, 129, 129);
private Rectangles rect01 = new Rectangles(136, 0, 129, 129);
private Rectangles rect02 = new Rectangles(268, 0, 129, 129);
private Rectangles rect10 = new Rectangles(0, 136, 129, 129);
private Rectangles rect11 = new Rectangles(134, 136, 129, 129);
private Rectangles rect12 = new Rectangles(269, 137, 129, 129);
private Rectangles rect20 = new Rectangles(0, 270, 129, 129);
private Rectangles rect21 = new Rectangles(136, 269, 129, 129);
private Rectangles rect22 = new Rectangles(269, 270, 129, 129);
public void Display() {
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setLayout(null);
frame.setSize(600, 400);
sub inter = new sub();
inter.setLayout(null);
inter.setBounds(0, 0, 600, 400);
inter.setSize(600, 400);
rect00.setBounds(rect00.getX(), rect00.getY(), rect00.getWidth(), rect00.getHeight());
rect01.setBounds(rect01.getX(), rect01.getY(), rect01.getWidth(), rect01.getHeight());
rect02.setBounds(rect02.getX(), rect02.getY(), rect02.getWidth(), rect02.getHeight());
rect10.setBounds(rect10.getX(), rect10.getY(), rect10.getWidth(), rect10.getHeight());
rect11.setBounds(rect11.getX(), rect11.getY(), rect11.getWidth(), rect11.getHeight());
rect12.setBounds(rect12.getX(), rect12.getY(), rect12.getWidth(), rect12.getHeight());
rect20.setBounds(rect20.getX(), rect20.getY(), rect20.getWidth(), rect20.getHeight());
rect21.setBounds(rect21.getX(), rect21.getY(), rect21.getWidth(), rect21.getHeight());
rect22.setBounds(rect22.getX(), rect22.getY(), rect22.getWidth(), rect22.getHeight());
rect00.setOpaque(false);
rect01.setOpaque(false);
rect02.setOpaque(false);
rect10.setOpaque(false);
rect11.setOpaque(false);
rect12.setOpaque(false);
rect20.setOpaque(false);
rect21.setOpaque(false);
rect22.setOpaque(false);
inter.addPanel(rect00);
inter.addPanel(rect01);
inter.addPanel(rect02);
inter.addPanel(rect10);
inter.addPanel(rect11);
inter.addPanel(rect12);
inter.addPanel(rect20);
inter.addPanel(rect21);
inter.addPanel(rect22);
frame.add(inter);
frame.setResizable(false);
frame.setVisible(true);
}
public static void main(String args[]) {
new Test().Display();
}
private class sub extends JPanel {
private BufferedImage image;
private ArrayList<Rectangles> rects = new ArrayList<>();
public sub() {
try {
image = ImageIO.read(new File("c:/image.png"));
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return (new Dimension(600, 400));
}
void addPanel(Rectangles r) {
rects.add(r);
add(r);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Rectangles r : rects) {
g.drawImage(image, r.getX(), r.getY(), null);
}
}
}
}
class Rectangles extends JPanel implements MouseListener {
private int Posx;
private int Posy;
private int width;
private int height;
private boolean selected = false;
public Rectangles(int Posx, int Posy, int width, int height) {
this.Posx = Posx;
this.Posy = Posy;
this.width = width;
this.height = height;
this.addMouseListener(this);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (selected == true) {
Graphics2D g2 = (Graphics2D) g;
g2.setColor(new Color(250, 235, 215));
g2.drawRect(0,0, width, height);
g2.setColor(new Color(0, 0, 0));
g2.setStroke(new BasicStroke(20));
g2.drawLine(0,0, width,height);
g2.drawLine(getWidth(),0, 0, height);
}
}
public int getX() {
return Posx;
}
public int getY() {
return Posy;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public void setSelected() {
selected = true;
}
#Override
public void mouseClicked(MouseEvent arg0) {
}
#Override
public void mouseEntered(MouseEvent arg0) {
}
public void mouseExited(MouseEvent arg0) {
}
#Override
public void mousePressed(MouseEvent arg0) {
}
#Override
public void mouseReleased(MouseEvent arg0) {
selected = true;
repaint();
}
}
A few other pointers:
Dont use Absolute/Null layout. A GridLayout or GridBagLayout would suit your needs fine. (see here for more.)
Dont do JFrame#setSize(...); rather use Correct LayoutManager and call pack() on JFrame before setting it visible.
Dont call setSize on your Rectangles instances, simply override getPreferredSize like you did with sub panel??
No need for implementing MouseListener, just use MouseAdapter thus giving you the freedom to choose which methods to override and not just override all.
Have a read on Concurrency in Swing especailly Event-Dispatch-Thread
I am having a problem using the repaint method in the following code.Please suggest how to use repaint method so that my screen is updated for a small animation.
This is my code :
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class movingObjects extends JPanel {
Timer timer;
int x = 2, y = 2, width = 10, height = 10;
public void paintComponent(final Graphics g) { // <---- using repaint method
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent ae) {
g.setColor(Color.red);
g.drawOval(x, y, width, height);
g.fillOval(x, y, width, height);
x++;
y++;
width++;
height++;
}
};
new Timer(100, taskPerformer).start();
}
}
class mainClass {
mainClass() {
buildGUI();
}
public void buildGUI() {
JFrame fr = new JFrame("Moving Objects");
movingObjects obj = new movingObjects();
fr.add(obj);
fr.setVisible(true);
fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fr.setSize(1300, 700);
}
public static void main(String args[]) {
new mainClass();
}
}
Don't try to delay the actual painting. The component needs to be painted when it is asked to be painted.
Instead, use your timer to modify some state in MovingObjects. In your case the state you want to change is x, y, width and height. When your timer fires, increment those values and call repaint().
Then in your paintComponents method, you would just use those values to paint the component
public void paintComponent(Graphics g) {
g.setColor(Color.red);
g.drawOval(x,y,width,height);
g.fillOval(x,y,width,height);
}
Edit
Not sure what you're having trouble with, but calling repaint() is not difficult:
ActionListener taskPerformer=new ActionListener() {
public void actionPerformed(ActionEvent ae) {
x++;
y++;
width++;
height++;
repaint();
}
};
new Timer(100,taskPerformer).start();