简体   繁体   中英

Why the repaint() method not working here?

public class Ova extends JPanel implements ActionListener{

int x=0;
Timer timer=new Timer(100,this);
int y=0,x1=5,y1=5;

public static void main(String[] ds)
{
    Ova ss=new Ova();
    ss.nn();    
}

private void nn() {     
    JFrame frame=new JFrame("fram");
    frame.setSize(1000,600);
    JPanel as=new JPanel();
    frame.add(as);  
    frame.add(new Ova());
    frame.setVisible(true);

    timer.start();
}

public void paintComponent(Graphics g)
{
    super.paintComponent(g);    
    g.drawOval(x, y, 50, 50);
}

public void actionPerformed(ActionEvent e) {
    if (x<0 || x>950){
        x1=-x1; 
    }
    if (y<0 || y>530)
    {
        y1=-y1;
    }

    x=x+x1;
    y=y+y1;

    repaint();
}
}

Whenever I put timer.start() inside paintComponent() the repaint() method works but if I start the timer outside the paint component method the repaint method does not work.Please explain the reasons. Thank you.

Problem

You have mis-matched reference issue

Start with this snippet...

public class Ova extends JPanel implements ActionListener {

    int x = 0;
    Timer timer = new Timer(100, this);
    int y = 0, x1 = 5, y1 = 5;

    public static void main(String[] ds) {
        Ova ss = new Ova();
        ss.nn();
    }

    private void nn() {
        JFrame frame = new JFrame("fram");
        frame.setSize(1000, 600);

        JPanel as = new JPanel();
        frame.add(as);
        frame.add(new Ova());
        frame.setVisible(true);
        timer.start();

    }

First, main creates an instance of Ova , then the method nn creates a new instance of Ova and then you start the timer ...

Now the question you need to ask is, which Ova s timer did you start...the one on the screen or the one main created...

I can tell, it was the one that main created, which is not visible on the screen

(A possible) Solution

Start by never creating a JFrame inside a JPanel (or other component). The only time I would do something like that is via a static support method...

Remove the nn method and replace it with a begin (or something like that) method that starts the timer .

In the main method, create an instance of Ova , add it to an instance of JFrame and call Ova 's begin method...

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Ova extends JPanel implements ActionListener {

    int x = 0;
    Timer timer = new Timer(100, this);
    int y = 0, x1 = 5, y1 = 5;

    public static void main(String[] ds) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                Ova ova = new Ova();

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(ova);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

                ova.begin();
            }
        });
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(600, 600);
    }

    private void begin() {
        timer.start();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

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

    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (x < 0 || x > 950) {
            x1 = -x1;
        }
        if (y < 0 || y > 530) {
            y1 = -y1;

        }

        x = x + x1;
        y = y + y1;

        repaint();

    }
}

Avoid calling setSize on anything, instead, override the getPreferredSize method of the component and return a preferred size and then use pack on the JFrame to wrap the frame around this. You will get far better and reliable results.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM