我正在尝试制作一个游戏。游戏中有几个不同的屏幕,例如主菜单和实际的游戏屏幕。这些中的每一个都是一个单独的 jpanel 扩展。我已经将它们中的每一个都添加到我的JFrame中,这是一个叫做Game的类。在我的游戏课上,我有以下方法
public void addPanel( JPanel p ) {
panels.add( p ); // An array of all the different panels I need
this.getContentPane().add( p );
}
public void switchToPanel( JPanel p ) {
for ( JPanel somePanel : panels ) {
somePanel.setVisible( false );
}
p.setVisible( true );
repaint();
}
这样做的重点是我有许多不同的面板,当我需要显示特定的面板时,例如菜单屏幕,我调用 switchToPanel( myPanel )。基本上只是隐藏每个面板,然后取消隐藏我需要看到的面板。唯一的问题是当我切换到它们时,这些面板没有显示。唯一会出现的是我上次添加的面板。在Objective C中,我一直使用这种技术在视图之间切换,我从来没有遇到过任何问题。这种事情在java中是不允许的吗?
编辑:现在我在切换后调用 repaint(),但它仍然不起作用
您可以执行许多不同的操作来达到相同的效果。
我提出的第一个建议是使用CardLayout(如何使用CardLayout),因为这是它的设计目的。
另一种是使用JTabbedPane(如何使用Tabbed Panes)
如果您正在制作游戏,则可以在与EDT
不同的单独线程中制作它。大多数游戏通过不更改面板来显示不同的屏幕,但它们使用单个面板,并根据GameState
在其上渲染。
下面是一个示例。
public class MyGame extends JPanel implements Runnable {
public static enum GameState {
MENU, INTRO, LEVELS, END, TITLES
}
GameState state = GameState.MENU;
public MyGame(){
setDoubleBuffered(true);
// Initialize the resources
new Thread(this).start();
}
public void update(long elapsedTime){
switch (state){
case MENU:
// Show the menu
break;
....
}
}
private void GameLoop(){
// Game Loop goes here
}
public void run(){
GameLoop();
}
public void paint(Graphics g){
// switch and draw your game
}
public static void main(String[] args){
JFrame f = new JFrame("MyGame");
f.setSize(640, 480);
f.add(new MyGame());
f.setVisible(true);
}
}
如果一个状态,即菜单已完成,则更改state
变量。在自己制作之前,先学习使用GameEngine
。
如果要在两个面板之间切换,请将这些面板添加到另一个 JPanel 并使用 cardLayout。然后,在添加JPanel
之前删除当前。喜欢这个:
parentPanel.removeAll();
parentPanel.repaint();
parentPanel.revalidate();
parentPanel.add(childPanel1);
parentPanel.repaint();
parentPanel.revalidate();
同样,对其他子面板执行相同的操作。
public static void main(String[] args) {
JFrame jFrame = new JFrame("Test");
jFrame.setSize(500, 500);
jFrame.setLocationRelativeTo(jFrame.getOwner());
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jFrame.setLayout(new BorderLayout());
var jPanel = new JPanel(new BorderLayout());
jFrame.add(jPanel, BorderLayout.CENTER);
AtomicBoolean b = new AtomicBoolean(false);
jFrame.add(new JButton("Switch") {
{
addActionListener(e -> {
b.set(!b.get());
jPanel.removeAll();
jPanel.repaint();
jPanel.revalidate();
jPanel.add(b.get() ? new JPanel() {
@Override
protected void paintComponent(Graphics g) {
setBackground(Color.RED);
super.paintComponent(g);
}
} : new JPanel() {
@Override
protected void paintComponent(Graphics g) {
setBackground(Color.GREEN);
super.paintComponent(g);
}
});
jPanel.repaint();
jPanel.revalidate();
});
}
}, BorderLayout.SOUTH);
jFrame.setVisible(true);
}