您好我正在构建一个游戏,其中包括JFrame,Startscreen,DrawingPanel和GameOver屏幕上的3个JPanel。如果我只是创建DrawingPanel并告诉GameController类开始更新它工作正常,但如果我创建一个带按钮的StartScreen来启动游戏,那么当我按下开始游戏按钮时,游戏窗口不会显示,尽管游戏代码运行。
编辑:
我创建了一个模仿JPanels创建的新程序,但排除了所有游戏代码,使其更容易理解。下面我列出了所有相关课程:
此类创建一个JFrame和两个JPanel。它还运行代码来更新游戏状态并告诉DrawingPanel重新绘制。
public class TestController{
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
private final int FRAME_WIDTH = (int)screenSize.getWidth();
private final int FRAME_HEIGHT = (int)screenSize.getHeight();
public boolean gameStarted = false;
private JFrame gameWindow;
private TestDrawingPanel myDrawingPanel;
private TestStartGame startGame;
int counter;
Set<Rectangle> rects;
//creates a JFrame and all the JPanels
public TestController(String title)
{
gameWindow = new JFrame(title);
gameWindow.setSize(FRAME_WIDTH, FRAME_HEIGHT);
gameWindow.setVisible(true);
gameWindow.setResizable(false);
gameWindow.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
startGame = new TestStartGame(getAvailableWidth(), getAvailableHeight());
startGame.addAL(new StartButton());
myDrawingPanel = new TestDrawingPanel(getAvailableWidth(), getAvailableHeight());
gameWindow.add(startGame);
gameWindow.add(myDrawingPanel);
myDrawingPanel.setVisible(false);
myDrawingPanel.setEnabled(false);
rects = new HashSet();
}
private int getAvailableWidth()
{
return gameWindow.getWidth() - gameWindow.getInsets().left - gameWindow.getInsets().right;
}
private int getAvailableHeight()
{
return gameWindow.getHeight() - gameWindow.getInsets().top - gameWindow.getInsets().bottom;
}
//starts the game running
public void startTheGame()
{
myDrawingPanel.setEnabled(true);
startGame.setVisible(false);
startGame.setEnabled(false);
myDrawingPanel.setVisible(true);
gameStarted = true;
update();
}
public boolean getGameStarted()
{
return gameStarted;
}
//loop that runs the game code
public void update()
{
counter = 0;
while(gameStarted)
{
updatePictureState();
myDrawingPanel.draw(rects);
myDrawingPanel.repaint();
}
}
//updates the game state
public void updatePictureState()
{
rects.clear();
for (int i = counter + 10; i < counter + 100; i = i + 10)
{
rects.add(new Rectangle(i,i,10,10));
}
}
//an action listener to be added to the start screen
private class StartButton implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
Object buttonPressed = e.getSource();
if(buttonPressed.equals(TestStartGame.start))
{
startTheGame();
}
}
}
}
这个类是一个扩展的JPanel,只有一个按钮来启动游戏:
public class TestStartGame extends JPanel{
private final JPanel buttons;
public static JButton start;
//creates a JPanel with a single button to start the game
public TestStartGame(int width, int height)
{
setSize(width, height);
setLayout(new GridLayout(2,1));
setBackground(Color.GREEN);
buttons = new JPanel();
buttons.setSize(width, height / 2);
buttons.setBackground(Color.red);
start = new JButton("Start");
buttons.add(start);
add(buttons, BorderLayout.SOUTH);
}
//adds an action listener to the button
public void addAL(ActionListener al)
{
start.addActionListener(al);
}
}
这个类是一个扩展的JPanel,作为游戏的主屏幕,在每个游戏周期更新到显示它的当前状态:
public class TestDrawingPanel extends JPanel{
Set<Rectangle> drawSet;
//creates the drawing panel and sets the size and background
public TestDrawingPanel(int width, int height)
{
setSize(width, height);
this.setBackground(Color.CYAN);
drawSet = new HashSet();
}
public void draw(Set<Rectangle> platforms)
{
drawSet.clear();
drawSet = platforms;
}
//draws the game window
@Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
System.out.println("works here");
g.setColor(Color.red);
for (Rectangle r : drawSet)
{
g.fillRect((int)r.getX(), (int)r.getY(), (int)r.getWidth(), (int)r.getHeight());
}
}
}
如果我只是添加TestDrawingPanel,它显示正常,但如果我从TestStartScreen开始,那么当我单击开始游戏按钮时,TestStartScreen不会消失,并且TestDrawingPanel永远不会显示。有趣的是,如果我有两个屏幕,但没有调用更新方法是TestController,那么开始游戏按钮正常工作并显示TestDrawingPanel,但显然没有任何反应,因为更新方法是游戏状态改变的地方。
我发现问题是如果TestDrawingPanel不是唯一创建的JPanel,那么重绘它的调用将失败。
答案 0 :(得分:0)
下面:
Thread.sleep(20);
你最有可能睡在Event Dispatcher Thread上。这会冻结整个申请。您必须退后一步并查看invokeLater以确保您的UI中的“正确”线程。
答案 1 :(得分:0)
问题解决了@ Andrew-Thompson的礼遇:
&#34; while(gameStarted)..不,没有一千次没有。无限循环可能会冻结GUI。使用基于Swing的Timer在ActionListener的actionPerformed方法中调用循环中的代码语句&#34;