加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

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

发布时间:2020-12-15 07:36:37 所属栏目:Java 来源:网络整理
导读:我有以下代码: 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.R
我有以下代码:

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.我尝试分开设置一个新线程,但无济于事.
我尝试了一些其他解决方案(invokelater,并且立即痛苦),也无济于事.

我的目标是设置一个在屏幕上徘徊的绿点.
你有什么解决方案吗?

解决方法

你的while(true)阻止了让应用程序进入休眠状态的Swing事件线程.

对于简单的动画和游戏循环,请使用Swing Timer.如果你有长时间运行的代码需要在后台,那么使用后台线程,如SwingWorker,但要注意确保所有调用Swing组件状态的调用应该在Swing事件线程上完成.

例如,你可以改变这个:

while(true) {

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


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

      this.repaint();
    }

使用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();

关于DSquare的评论:

>实际上,你没有在Swing事件线程上运行你的GUI,你应该做的事情,然而你的while循环仍然会冻结你的绘画,因为你的无限循环阻止了组件完全自己创建.
>如上所述,实际上你应该在Swing事件线程上启动所有Swing GUI,你可以通过将Swing创建代码放入Runnable并通过SwingUtilities方法invokeLater在事件线程上排队Runnable来完成.
>您需要在paintComponent覆盖中调用super的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,20);
}

对此:

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读