简体   繁体   中英

move a pixel in Jframe and crash JFrame when use Thread.Sleep(1000)

I want to move a pixel in a JFrame but use of Thread.Sleep(1000) method eventuate to crash my JFrame. why this problem happen? and how solve it? Thank You

public class Main {
public static void main(String[] args) throws InterruptedException {
    JFrame mainFrame = new JFrame("Sadra Graphics");
    mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    SadraGraphics sadraGraphics = new  SadraGraphics();
    sadraGraphics.setPreferredSize((new Dimension(640,480)));
    mainFrame.getContentPane().add( sadraGraphics );
    mainFrame.pack();
    mainFrame.setVisible(true);    }}


public class SadraGraphics extends JPanel {


public void paintComponent (Graphics g){

    super.paintComponent(g);
    this.setBackground(Color.white);

    for (int i = 0; i <=639; i++) {
        g.setColor(Color.red);
        g.drawLine(i, i * 3 / 4, i, i * 3 / 4);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        g.setColor(Color.white);
        g.drawLine(i,i*3/4,i,i*3/4);

        }


    }
}
  1. Don't use Thread.sleep . Even if you were to use it, you never want to use it in the paintComponent method.
  2. Instead use a javax.swing.Timer , that will update some variables and repaint every so many milliseconds

     public SadraGraphics() { Timer timer = new Timer(1000, new ActionListener(){ public void actionPerformed(ActionEvent e) { // do something here that will refresh some variables that you // are using to paint, then call repaint() repaint(); } }); timer.start(); } 

See more at How to use Swing Timers

Here a simple runnable example

import java.awt.Dimension;
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.SwingUtilities;
import javax.swing.Timer;

public class Main {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JFrame mainFrame = new JFrame("Sadra Graphics");
                mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                SadraGraphics sadraGraphics = new SadraGraphics();
                sadraGraphics.setPreferredSize((new Dimension(640, 480)));
                mainFrame.getContentPane().add(sadraGraphics);
                mainFrame.pack();
                mainFrame.setVisible(true);
            }
        });
    }
}

class SadraGraphics extends JPanel {

    int x1 = 0;
    int y1 = 50;
    int x2 = 0;
    int y2 = 200;

    public SadraGraphics() {
        Timer timer = new Timer(30, new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                x1 += 2;
                x2 += 2;
                repaint();
            }
        });
        timer.start();
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawLine(x1, y1, x2, y2);

    }
}

Side Note

  • Run Swing apps from the EDT using SwingUtilities.invokeLater .
  • paintComponent should be protected not public
  • Don't set the background from with the paintComonent method. You can either do it from the constructor or instead you can paint the background in the paintComponent method by doing this

     g.setColor(Color.WHITE); g.fillRect(0, 0, getWidth(), getHeight()); 

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