简体   繁体   English

Swing repaint() 在循环或线程中不起作用

[英]Swing repaint() doesn't work in loop or thread

I have the following code:我有以下代码:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.text.View;

public class ex10 extends JPanel  {
    private int x=1;
    int y=1;

    //Constructor 
    public ex10() {


        while(true) {

          System.out.println("x ->"+ x);
          System.out.println("y ->" + y);


          x = randomposition(x);
          y = randomposition(y);

          this.repaint();
        }
    }

  public int randomposition(int value) {
        Random random = new Random();

    if (random.nextBoolean() == true) {
      if (value+1 != 500) {
        value++;
      }
    }
    else {
      if (value-1 != 0) {
        value--;  
      }
    }
    return value;
  }
    @Override
    public void paintComponent(Graphics g) {
        //super.paintComponent(g);
        g.setColor(Color.green);
    g.fillRect(x, y, 20, 20);
    }


    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setSize(500, 500);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        frame.add(new ex10());
    }

}

Unfortunately, when this.repaint() is called, the point isn't being displayed, but I still got the System.out.println .不幸的是,当this.repaint()被调用时,点没有被显示,但我仍然得到了System.out.println I tried setting a new thread separatedly, but to no avail.我尝试单独设置一个新线程,但无济于事。 I tried out some other solution ( invokelater , and paintimmediately ), also to no avail.我尝试了其他一些解决方案( invokelaterpaintimmediately ),也无济于事。

My goal is to set a green point which wanders on the screen.我的目标是设置一个在屏幕上徘徊的绿点。 Do you have any solution?你有什么解决办法吗?

Your while (true) is blocking the Swing event thread putting the application to sleep.您的while (true)正在阻塞使应用程序进入睡眠状态的 Swing 事件线程。

For simple animation and game loop, use a Swing Timer.对于简单的动画和游戏循环,请使用 Swing Timer。 If you have long running code that needs to be in the background, then use a background thread such as a SwingWorker, but taking care to make sure that all calls that change the state of your Swing components should be done on the Swing event thread.如果您有长时间运行的代码需要在后台运行,则使用后台线程,例如 SwingWorker,但要注意确保所有更改 Swing 组件状态的调用都应在 Swing 事件线程上完成。

For example, you could change this:例如,您可以更改此设置:

    while(true) {

      System.out.println("x ->"+ x);
      System.out.println("y ->" + y);


      x = randomposition(x);
      y = randomposition(y);

      this.repaint();
    }

to this that uses a Swing Timer (javax.swing.Timer):对此使用 Swing Timer (javax.swing.Timer):

int timerDelay = 20;
new Timer(timerDelay, new ActionListener(){
  public void actionPerformed(ActionEvent e) {
    x = randomposition(x);
    y = randomposition(y);
    repaint();
  }
}).start();

Regarding DSquare's comments:关于DSquare的评论:

  • Indeed you are not running your GUI on the Swing event thread, something you should be doing, and yet your while true loop is still freezing your painting because your infinite loop prevents the component from completely creating itself.实际上,您没有在 Swing 事件线程上运行 GUI,这是您应该做的事情,但是您的 while true 循环仍然冻结了您的绘画,因为您的无限循环阻止了组件完全创建自己。
  • As noted above, you should in fact start all Swing GUI's on the Swing event thread which you could do by placing the Swing creation code into a Runnable and queuing the Runnable on the event thread via the SwingUtilities method, invokeLater.如上所述,您实际上应该在 Swing 事件线程上启动所有 Swing GUI,您可以通过将 Swing 创建代码放入 Runnable 并通过 SwingUtilities 方法 invokeLater 在事件线程上排队 Runnable 来实现。
  • You need to call the super's paintComponent method in your paintComponent override so that the JPanel can do its housekeeping graphics works including clearing "dirty" pixels.您需要在您的paintComponent 覆盖中调用super 的paintComponent 方法,以便JPanel 可以执行其内务图形工作,包括清除“脏”像素。

For example, change this:例如,改变这个:

public static void main(String[] args) {
    JFrame frame = new JFrame();
    frame.setSize(500, 500);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);
    frame.add(new ex10());
}

to this:对此:

public static void main(String[] args) {
  SwingUtilities.invokeLater(new Runnable() {
     public void run() {
        JFrame frame = new JFrame();
        frame.setSize(500, 500);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        frame.add(new Ex10());
     }
  });
}

And change this:并改变这一点:

@Override
public void paintComponent(Graphics g) {
  //super.paintComponent(g);
  g.setColor(Color.green);
  g.fillRect(x, y, 20, 20);
}

to this:对此:

@Override
public void paintComponent(Graphics g) {
  super.paintComponent(g);
  g.setColor(Color.green);
  g.fillRect(x, y, 20, 20);
}

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

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