摇摆重绘()不循环或线程工作摇摆重绘()不循环或线程工作(Swing repaint() doesn

2019-05-12 12:08发布

我有以下代码:

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());
    }

}

不幸的是,当this.repaint()被调用时,没有显示这一点,但我还是得到了System.out.println 。 我试着separatedly设置一个新的线程,但无济于事。 我尝试了一些其他的解决方案( invokelater ,和paintimmediately ),也无济于事。

我的目标是建立一个绿色的点,其飘荡在屏幕上。 你有什么解决办法吗?

Answer 1:

while (true)挡住了Swing事件线程将睡眠中的应用。

对于简单的动画和游戏循环,使用Swing的计时器。 如果你长时间运行,需要在后台代码,然后使用一个后台线程,如SwingWorker的,但照顾,以确保该改变你的Swing组件的状态的所有调用应该Swing事件线程来完成。

例如,你可以改变这一点:

    while(true) {

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


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

      this.repaint();
    }

这是使用了摇摆定时器(javax.swing.Timer中):

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

关于DSquare的评论:

  • 事实上,你没有运行您的Swing事件线程上的GUI,是你应该做的,可是你的,但是实际循环仍在冻结你的画,因为你的无限循环防止组件完成创建本身。
  • 如上所述,你其实应该开始Swing事件线程,你可以通过将摇摆创建代码到一个Runnable和排队了Runnable通过SwingUtilities类的方法,invokeLater的事件线程上做所有的Swing GUI的。
  • 您需要调用父类的方法的paintComponent在你的paintComponent覆盖,使JPanel中可以做它的看家作品的图形包括清除“脏”的像素。

例如,更改此:

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());
}

为此:

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());
     }
  });
}

而改变这种:

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

为此:

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


文章来源: Swing repaint() doesn't work in loop or thread