This is code for, a smiley have to move on the screen from one place to another. But in this code Smiley create but it is moving. Please tell my? Is there any wrong in my code.

import javax.swing.*;

import java.awt.*;

class CreateSmiley extends JPanel

{

    int x = 0,y = 0;



    public void paintComponen(Graphics g)

    {

        //System.out.println("x = :"+x);

        g.setColor(Color.RED);

        g.drawOval(x,y,200,200);

        g.setColor(Color.YELLOW);

        g.fillOval(x+50,y+70,20,20);

        g.fillOval(x+130,y+70,20,20);

        g.setColor(Color.GREEN);

        g.fillArc(x+30,y+80,140,70,190,165);

        //System.out.println("XXX ="+x);

    }

    void smileFlow() throws Exception

    {

        CreateSmiley s1 = new CreateSmiley();

        while(x != 600)

        {

            Thread.sleep(100);

            x = x + 5;

            y = y + 5;

            System.out.println("x123 = :"+x);

            s1.repaint();

            System.out.println("x321 = :"+x);





        }

    }



}

public class Smiley

{

    public static void main(String a[]) throws Exception

    {



        JFrame f = new JFrame("Smiley");

        CreateSmiley s = new CreateSmiley();

        s.smileFlow();

//      SmileyFlow sf = new SmileyFlow();

        f.add(s);

        f.setSize(600,600);

        f.setVisible(true);

        f.setDefaultCloseOperation(3);



    }

}

Dani AI

Generated

Three quick root causes in the original code that prevented visible animation: a misspelled painting method so Swing never called your painter, calling repaint() on a newly created panel (s1) instead of the panel added to the frame, and running a long loop with Thread.sleep(...) on the thread that builds/shows the UI (which blocks painting). and were right to push painting into the right callback and to start the animation after the frame is visible, but the more robust fixes are small and structural.

Practical checklist to fix the program (in order):

  • Change the method to paintComponent(Graphics g) and add @Override so typos are caught by the compiler. Call super.paintComponent(g) first to clear the background.
  • Update the panel’s own x,y fields and call repaint() on that same instance — do not new another CreateSmiley.
  • Do not run a long while loop with Thread.sleep on the Event Dispatch Thread. Use a javax.swing.Timer (runs on the EDT) or a background thread that posts updates to the EDT.
  • Create and show the GUI on the EDT via SwingUtilities.invokeLater(...). Start the timer after the frame is visible.
  • Use JFrame.EXIT_ON_CLOSE for readability and prefer setPreferredSize/pack() where appropriate.

Example pattern (structure only — replace the comment with your drawing code):

import javax.swing.*;
import java.awt.*;

class SmileyPanel extends JPanel {
  int x = 0, y = 0;
  @Override protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    // draw smiley relative to x, y
  }
  void step() { x += 5; y += 5; }
}

public class Smiley {
  public static void main(String[] args) {
    SwingUtilities.invokeLater(() -> {
      JFrame f = new JFrame("Smiley");
      SmileyPanel p = new SmileyPanel();
      f.add(p);
      f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      f.setSize(600,600);
      f.setVisible(true);
      new Timer(100, e -> { p.step(); p.repaint(); }).start();
    });
  }
}

Caution: keep painting fast (no I/O or heavy work in paintComponent) and use @Override to trap method-name mistakes like the original paintComponen. This addresses the issues raised by , and ties together the suggestions from and into a safe, Swing-friendly approach.

Recommended Answers

All 6 Replies

You may try the following changes.
Because we want the smileFlow() runs for a certain time (befor x reaches 600), you have to
(1) delete the line code s.smileFlow();
(2) insert the above code s.smileFlow(); after the f.setDefaultCloseOperation(3);
so that it runs after setting up the frame properly.
P.S. the code:f.setDefaultCloseOperation(3);
should be written as:
f.setDefaultCloseOperation(EXIT_ON_CLOSE); // so that one may clearly understand


(3) replace the name of the method: public void paintComponen(Graphics g)
by public void paint(Graphics g)
(4) inser the code line:
super.paint(g); // as the first line code of the method.
into the paint method.
so that the canvas is cleaned before the next operation of repaint().

I have modified your code a little bit so that the Smiley moves "forever".
Attached please find the modification
Please use the code tag to post your code so that one may mention about the code line number.

replace the name of the method: public void paintComponen(Graphics g)
by public void paint(Graphics g)

Unless you have some special reason, this is not a good idea. Sun's doc makes it clear that you should always override paintComponent rather than paint unless there's a specific reason not to
http://java.sun.com/products/jfc/tsc/articles/painting/#callbacks

Thank you, James, for the comment.

In the following code: line 17 the paintComponent() is replaced by paint(). If the paintComponent() is used the line 18 will produce a run error:

at javax.swing.JComponent.paint(JComponent.java:1027)
at CreateSmiley.paintComponent(Smiley.java:18)
(Why? I don't know. Please offer some annotation for this point.)

If the paintComponent() has to be used one has to write two lines of code as the first two lines of the method to do the job of cleaning canvas.

g.setColor(Color.white);
g.fillRect(0,0,600,600);

In order to clean the canvas by calling super.paint(g); one has to replace paintComponent() by paint().

import javax.swing.*;
import java.awt.*;

class CreateSmiley extends JPanel implements Runnable {

int x=0,y=0;
Thread timer=null;   // a Thread instance associated with repaint()
boolean flag =true;  // signal toggle controls the increment/decrement in x and y

public void start(){
	if (timer==null){
	timer = new Thread(this);
	timer.start();
	}
}

public void paint(Graphics g) {  //  paintComponent replaced otherwise the line 18 produces an error message
super.paint(g); // clean the canvas before drawing the next picture
g.setColor(Color.RED);
g.drawOval(x,y,200,200);
g.setColor(Color.YELLOW);
g.fillOval(x+50,y+70,20,20);
g.fillOval(x+130,y+70,20,20);
g.setColor(Color.GREEN);
g.fillArc(x+30,y+80,140,70,190,165);
}

public void run(){
   while(timer != null){
   try {Thread.sleep(300);
   if(flag) {
	x+=5;
	y+=5;
   } else {
	x-=5;
	y-=5;
	}
   if ((x == 400) || (x==0))
	flag = !flag;
   repaint();
	}catch(Exception e){}
   }
  }
}

public class Smiley extends JFrame {	
	public Smiley(){
	super("Smiley");	
   	CreateSmiley s = new CreateSmiley();
   	add(s);
   	s.start();
	setSize(600,600);
	setVisible(true);
	setDefaultCloseOperation(EXIT_ON_CLOSE);	
	}

public static void main(String a[]) throws Exception{
	Smiley sm= new Smiley();
	}
}

If you use paintComponent (as recommended) then the first line of the method should also be super.paintComponent(g); not super.paint(g);

Thank you James. It works.

Thank you guys, it's working fine..............

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.