我正在尝试在 Swing 中构建游戏,我知道我可以使用其他工具,但这仅用于学习目的。我面临的问题与线程有关。
基本上,在对 JPanel(GamePanel 类)进行任何绘制之前,主线程会运行 JFrame(Window 类)的 setVisible 属性。在我做了一些研究之后,我发现我可以使用 SwingUtilities.invokeLater()
方法解决这个问题,该方法应该给游戏线程一些时间来准备在 JPanel 上制作的绘图。
我还尝试将 setVisible (true)
属性放置在不同的线程中,并使该线程 hibernate 2、3 秒。这两种方法有时有效,有时无效。
我不知道这是否有什么不同,但我的操作系统是:macOS Catalina。
导致此线程问题的简单示例。
游戏启动器
public class GameLauncher {
public GameLauncher(){
new Window("MyGame");
}
public static void main(String[] args) {
new GameLauncher();
}
}
窗口
public class Window extends JFrame {
public Window(String title){
setTitle(title);
setContentPane(new GamePanel(1280, 1280));
setLocationRelativeTo(null);
setIgnoreRepaint(true);
pack();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// setVisible(true);
SwingUtilities.invokeLater(()->setVisible(true));
}
}
游戏面板
package com.progresso.games;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
public class GamePanel extends JPanel implements Runnable {
public int width;
public int height;
private BufferedImage bufferedImage;
private Thread gameThread;
private boolean isRunning = false;
Graphics2D graphics2D = null;
public GamePanel(int width, int height){
this.width = width;
this.height = height;
setPreferredSize(new Dimension(width, height));
setFocusable(true);
requestFocus();
}
@Override
public void addNotify() {
super.addNotify();
if(gameThread == null){
gameThread = new Thread(this, "GameThread");
gameThread.start();
}
}
private void init(){
isRunning = true;
bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
graphics2D = (Graphics2D) bufferedImage.getGraphics();
}
@Override
public void run() {
init();
while (isRunning) {
update();
render(graphics2D);
draw();
}
}
private void update(){ }
private void render(Graphics2D g){
if(g != null){
g.setColor(Color.BLACK);
g.fillRect(0,0, width, height);
}
}
private void draw(){ }
}
最佳答案
对 JFrame 进行子类化并不是一个好主意。相反,扩展 JPanel,并在其 PaintCpomponent() 方法中绘制您的内容。尝试这样的事情(不完整的代码):
public class GamePanel extends JPanel {
public GamePanel() {
// Create panel content here
}
@Override
public void paintComponent( Graphics g ) {
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(0,0, width, height);
}
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
// create the component to display in the frame
JPanel panel = new GamePanel();
;
frame.add(panel, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent arg0) {
System.exit(0);
}
});
}
});
}
}
关于java - 在进行任何绘图之前调用 setVisible 属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60020128/