gpt4 book ai didi

Java JFrame - 在另一个线程完成之前不重绘()

转载 作者:行者123 更新时间:2023-12-03 18:20:48 25 4
gpt4 key购买 nike

我正在尝试创建一个游戏,我从加载屏幕开始,它将加载所有需要的文件。我想显示完成的百分比,但它不起作用。 JPanel Loading 仅在 Loading_files 完成后才 repaints() 。我不知道怎么了。

主.java

package Main;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Main extends JFrame{

//-------------- Final Variables --------------
//Screen Related
public final static int JFRAME_WIDTH = 800;
public final static int JFRAME_HEIGHT = 600;
public final static Dimension SCREEN_SIZE = Toolkit.getDefaultToolkit().getScreenSize();
public final static int SCREEN_WIDTH = SCREEN_SIZE.width;
public final static int SCREEN_HEIGHT = SCREEN_SIZE.height;
//Game Related
public final static String NAME = "Xubris";
public final static String IMAGE_DIRECTORY = System.getProperty("user.dir") + "\\images\\";
public static final int FPS = 1000 / 36;

//-------------- Dynamic Variables --------------
//Global
public static JFrame main;

public static void main(String[] args) {
//Start the Loading screen
Loading load = new Loading();

main = new JFrame(NAME);

main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

main.setSize(JFRAME_WIDTH, JFRAME_HEIGHT);
main.setLocation((SCREEN_WIDTH-JFRAME_WIDTH)/2, (SCREEN_HEIGHT-JFRAME_HEIGHT)/2);

//Add Content
main.getContentPane().add(load);

main.setResizable(false);
main.setUndecorated(false);
main.setVisible(true);
}

}

Loading.java

package Main;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JPanel;

public class Loading extends JPanel implements Runnable{

//Pictures
BufferedImage background;

//-------------- Final Variables --------------
private final int num_of_files = 32;

//-------------- Dynamic Variables --------------
//Global Variables
private double loading_percentage = 0;
private int num_of_loaded_files = 0;

public Loading(){
try {
background = ImageIO.read(new File(Main.IMAGE_DIRECTORY + "Background_Loading.jpg"));
} catch (IOException e) {
e.printStackTrace();
}
//Start the thread
new Thread(new LoadingFiles()).start();
new Thread(this).start();
}

public void paint(Graphics g){
g.drawImage(background, 0, 0, this);
for(int i = 0; i < loading_percentage; i=i+15){
g.setColor(new Color(20,241,47));
g.drawRect(180 + (i/15)*(50+10), 375, 50, 50);
}
}

@Override
public void run(){
while(true){
repaint();
}
}

class LoadingFiles implements Runnable{
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
num_of_loaded_files++;
loading_percentage = (num_of_loaded_files/num_of_files)*100;

if(num_of_loaded_files!=32)
run();
}

}
}

最佳答案

阻止 EDT 并重新绘制合并也是我的第一个想法(这就是我赞成评论的原因)。但很好奇 - 真正的问题也不是 :-)

  • 从任何线程调用重绘都是完全有效的(尽管在紧密的 while 循环中这样做肯定会减慢 ui react )
  • 即使在一些清理之后也没有按预期重绘(见下文)。罪魁祸首纯粹是算术

下面一行:

loading_percentage = (num_of_loaded_files/num_of_files)*100;

这是 0 直到

num_of_loaded_files == num_of_files

直到一切都加载完毕。我们都对仓促下结论感到内疚 :-)

一些清理:

  • 遵循 java 命名约定使代码更易于阅读
  • 不要覆盖 paint,而是覆盖 paintComponent
  • 始终在 paintComponent 中调用 super(默认情况下 JPanel 报告为不透明,也就是说,它必须填充其区域)
  • 无需交织线程,只需让加载线程在加载下一张图像后调用重绘
  • 算术正确:-)

代码:

public class Loading extends JPanel { 

// Pictures
private BufferedImage background;

// -------------- Final Variables --------------
private final int numOfFiles = 32;

// -------------- Dynamic Variables --------------
// Global Variables
private double loadingPercentage = 0;

private int numOfLoadedFiles = 0;

public Loading() {
background = XTestUtils.loadDefaultImage("moon.jpg");
// Start the thread
new Thread(new LoadingFiles()).start();
}

@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(background, 0, 0, this);
for (int i = 0; i < loadingPercentage; i = i + 15) {
g.setColor(new Color(20, 241, 47));
g.drawRect(180 + (i / 15) * (50 + 10), 375, 50, 50);
}
}

class LoadingFiles implements Runnable {
@Override
public void run() {

while (numOfLoadedFiles < 32) {
numOfLoadedFiles++;
loadingPercentage = (double) numOfLoadedFiles / numOfFiles
* 100;
repaint();
try {
// simulate the loading
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

}

public static void main(String[] args) {
JFrame frame = new JXFrame("", true);
frame.add(new Loading());
frame.setSize(600, 600);
frame.setVisible(true);
}
}

关于Java JFrame - 在另一个线程完成之前不重绘(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11918605/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com