简体   繁体   English

使用Thread.Sleep(1000)时,在Jframe中移动像素并使JFrame崩溃

[英]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. 我想在JFrame中移动像素,但是使用Thread.Sleep(1000)方法最终会导致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 . 不要使用Thread.sleep Even if you were to use it, you never want to use it in the paintComponent method. 即使您要使用它,也永远不要paintComponent方法中使用它。
  2. Instead use a javax.swing.Timer , that will update some variables and repaint every so many milliseconds 而是使用javax.swing.Timer ,它将更新一些变量并每隔毫秒重新绘制一次

     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 如何使用Swing计时器中查看更多信息

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 . 使用SwingUtilities.invokeLater从EDT运行Swing应用程序。
  • paintComponent should be protected not public paintComponent应该被protected而不是public
  • Don't set the background from with the paintComonent method. 不要使用paintComonent方法设置背景。 You can either do it from the constructor or instead you can paint the background in the paintComponent method by doing this 您可以从构造函数中执行此操作,也可以通过执行以下操作在paintComponent方法中绘制背景

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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