为什么我的Java应用程序在启动后随机冻结?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么我的Java应用程序在启动后随机冻结?相关的知识,希望对你有一定的参考价值。
所以出于某种原因,我的应用程序在启动时随机冻结。在GamePanel类的run()方法中添加sleep函数确实消除了问题,但我不明白为什么。
我查找了类似问题的其他帖子,但它们似乎有不同的起源。
应用类
import javax.swing.*;
import java.awt.*;
public class Application {
private Application() {
//create a JFrame window
JFrame frame = new JFrame("Moving Squares");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//add a JPanel
GamePanel gamePanel = new GamePanel();
frame.add(gamePanel);
//pack the window around the content
frame.pack();
//center
frame.setLocationRelativeTo(null);
//set minimum size
frame.setMinimumSize(new Dimension(40, 80));
frame.setVisible(true);
}
public static void main(String args[]){
new Application();
}
}
的GamePanel
import java.awt.*;
import java.util.ArrayList;
import javax.swing.*;
public class GamePanel extends JPanel implements Runnable{
//set JPanel size
private static final Dimension DESIRED_SIZE = new Dimension(600,600);
@Override
public Dimension getPreferredSize(){
return DESIRED_SIZE;
}
//constructor
GamePanel(){
Thread t = new Thread(this);
t.start();
}
private ArrayList <Rect> rect=new ArrayList<>();
public void run(){
for(int i=0; i<15; i++){
rect.add(new Rect());
}
//load time
//to avoid freezing on start
try{Thread.sleep(250);}
catch(InterruptedException e){}
while(true){
for(Rect rect:rect){
rect.move(this);
}
repaint();
try{Thread.sleep(30);}
catch(InterruptedException e){/**/};
}
}
public void paint(Graphics g){
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.white);
g2d.fillRect(0,0,getWidth(),getHeight());
for(Rect rect:rect) {
g2d.setColor(Color.black);
g2d.fillRect(rect.getXcord()-1, rect.getYcord()-1, rect.getWidth()+2, rect.getHeight()+2);
g2d.setColor(rect.getRGB());
g2d.fillRect(rect.getXcord(), rect.getYcord(), rect.getWidth(), rect.getHeight());
}
}
}
矩形
import javax.swing.*;
import java.awt.*;
import java.util.Random;
public class Rect{
//properties
private int width=30, height=30;
private int R, G, B;
private Color rgb;
//movement
private int xCord, yCord;
private int xVector, yVector;
private int xSlope, ySlope;
public Rect(){
Random rand = new Random();
//random color
int R, G, B;
R=rand.nextInt(256);
G=rand.nextInt(256);
B=rand.nextInt(256);
rgb= new Color(R, G, B);
//random spawn position
xCord=rand.nextInt(600-width);
yCord=rand.nextInt(600-height);
//direction
do{
xVector=rand.nextInt(3) - 1;
yVector=rand.nextInt(3) - 1;
}while(xVector==0 || yVector==0);
//slope
do{
xSlope=rand.nextInt(3);
ySlope=rand.nextInt(3);
}while(xSlope==0 || ySlope==0);
xVector*=xSlope;
yVector*=ySlope;
}
public void move(JPanel parent){
int jpWidth=parent.getWidth();
int jpHeight=parent.getHeight();
//if stuck outside because of resize
if ( (xCord>=(jpWidth-width+2)) || (yCord>+(jpHeight-height+2)) ){
Random rand = new Random();
xCord=rand.nextInt(jpWidth-width-2)+1;
yCord=rand.nextInt(jpHeight-height-2)+1;
return;
}
//bounce
if((xCord>=jpWidth-width) || (xCord<=0)){
bounceX();
}
if((yCord>=jpHeight-height) || (yCord<=0)) {
bounceY();
}
//move
xCord+=xVector;
yCord+=yVector;
}
public void bounceX(){
xVector*=-1;
}
public void bounceY(){
yVector*=-1;
}
public Color getRGB() {
return rgb;
}
public int getXcord() {
return xCord;
}
public int getYcord() {
return yCord;
}
public int getWidth(){
return width;
}
public int getHeight(){
return height;
}
}
答案
在框架可见之前,您不应尝试绘制/重新绘制内容。
您可以做的是删除GamePanel
的构造函数的内容并将其放在一个单独的方法中,例如:
public void startThread() {
Thread t = new Thread(this);
t.start();
}
然后在框架可见后启动线程:
frame.setVisible(true);
gamePanel.startThread();
更好的是,摆脱面板内的线程,并在您的主要创建它:
frame.setVisible(true);
new Thread(gamePanel).start();
以上是关于为什么我的Java应用程序在启动后随机冻结?的主要内容,如果未能解决你的问题,请参考以下文章