gpt4 book ai didi

Java Swing : How do I wake up the main thread from the event-dispatch thread?

转载 作者:塔克拉玛干 更新时间:2023-11-02 07:53:58 25 4
gpt4 key购买 nike

我想让“主线程”(运行 main() 的线程启动)从按钮的 ActionListener 的 actionPerformed() 方法做一些工作, 但我不知道如何实现这一目标。

更多背景信息:

我目前正在使用 Swing(俄罗斯方 block 的一种风格)编写 2D 游戏。
当应用程序启动时,会打开一个显示游戏主菜单的窗口。向用户提供了几种可能性,其中一种是通过按下“开始”按钮开始游戏,这会导致显示游戏面板并触发游戏的主循环。

为了能够在两个面板(主菜单面板和游戏面板)之间切换,我使用了 CardLayout 管理器,然后我可以通过调用 show() 显示一个面板。 .
我的想法是,我希望我的开始按钮有一个如下所示的监听器:

public class StartListener implements ActionListener {
StartListener() {}
public void actionPerformed(ActionEvent e) {
displayGamePanel();
startGame();
}
}

但这不起作用,因为 actionPerformed() 是从事件派发线程调用的,因此调用 startGame()(触发主循环:游戏逻辑更新 + repaint() 在每一帧调用)阻塞整个线程。

我现在处理这个的方式是 actionPerformed() 只是改变一个 boolean 标志值:public void actionPerformed(ActionEvent e) {
开始推送=真;
}

然后最终由主线程检查:

while (true) {
while (!g.startPushed) {
try {
Thread.sleep(100);
} catch (Exception e) {}
}
g.startPushed = false;
g.startGame();
}

但我发现这个解决方案非常不优雅。

我已阅读Concurrency in Swing教训,但我仍然感到困惑(我应该实现一个工作线程——这不是有点矫枉过正吗?)。我还没有完成任何实际的多线程工作,所以我有点迷茫。

有没有办法告诉主线程(它会无限期地 hibernate ,等待用户操作)“好的,现在醒来并执行此操作(显示游戏面板并开始游戏)”?。

感谢您的帮助。

编辑:需要说明的是,这就是我的游戏循环的样子:

long lastLoopTime = System.currentTimeMillis();
long dTime;
int delay = 10;
while (running) {
// compute the time that has gone since the last frame
dTime = System.currentTimeMillis() - lastLoopTime;
lastLoopTime = System.currentTimeMillis();

// UPDATE STATE
updateState(dTime);
//...

// UPDATE GRAPHICS
// thread-safe: repaint() will run on the EDT
frame.repaint()

// Pause for a bit
try {
Thread.sleep(delay);
} catch (Exception e) {}
}

最佳答案

这没有意义:

but this does not work because actionPerformed() is called from the event-dispatch thread, so the call to startGame() (which triggers the main loop: game logic update + repaint() call at each frame) blocks the whole thread.

因为您的游戏循环不应该阻止 EDT。您在游戏循环中使用 Swing Timer 或后台线程吗?如果没有,请这样做。

关于:

while (true) {
while (!g.startPushed) {
try {
Thread.sleep(100);
} catch (Exception e) {}
}
g.startPushed = false;
g.startGame();
}

也不要这样做,而是为这类事情使用监听器。

例如,

import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;

public class GameState extends JPanel {
private CardLayout cardlayout = new CardLayout();
private GamePanel gamePanel = new GamePanel();
private StartPanel startpanel = new StartPanel(this, gamePanel);

public GameState() {
setLayout(cardlayout);
add(startpanel, StartPanel.DISPLAY_STRING);
add(gamePanel, GamePanel.DISPLAY_STRING);
}

public void showComponent(String displayString) {
cardlayout.show(this, displayString);
}

private static void createAndShowGui() {
GameState mainPanel = new GameState();

JFrame frame = new JFrame("GameState");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

class StartPanel extends JPanel {
public static final String DISPLAY_STRING = "Start Panel";

public StartPanel(final GameState gameState, final GamePanel gamePanel) {
add(new JButton(new AbstractAction("Start") {

@Override
public void actionPerformed(ActionEvent e) {
gameState.showComponent(GamePanel.DISPLAY_STRING);
gamePanel.startAnimation();
}
}));
}
}

class GamePanel extends JPanel {
public static final String DISPLAY_STRING = "Game Panel";
private static final int PREF_W = 500;
private static final int PREF_H = 400;
private static final int RECT_WIDTH = 10;
private int x;
private int y;

public void startAnimation() {
x = 0;
y = 0;
int timerDelay = 10;
new Timer(timerDelay , new ActionListener() {

@Override
public void actionPerformed(ActionEvent e) {
x++;
y++;
repaint();
}
}).start();
}

@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.fillRect(x, y, RECT_WIDTH, RECT_WIDTH);
}

@Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
}

关于Java Swing : How do I wake up the main thread from the event-dispatch thread?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10263430/

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