I'm trying to use CardLayout
to show two JPanels
, a main menu, and a controls screen. When I add two JPanels
to my cards JPanel
, it just shows two with flashing images. Here is my code:
package main;
public class MazeGame {
// Layout
public static JPanel cards = new JPanel();
// Window
public static JFrame window;
public static String windowLabel = "2D Maze Game - Before Alpha";
// Window Dimensions and Location
public static int WIDTH = 600;
public static int HEIGHT = 600;
public static Component center = null;
public static int exit = 3;
public static void main(String[] args) {
window = new JFrame(windowLabel);
window.setSize(new Dimension(WIDTH, HEIGHT));
window.setResizable(false);
window.setLocationRelativeTo(center);
window.setDefaultCloseOperation(exit);
cards.setLayout(new CardLayout());
cards.add(new MazeGamePanel(), "main");
cards.add(new MazeControlsPanel(), "controls");
window.add(cards);
CardLayout cl = (CardLayout) cards.getLayout();
cl.show(cards, "main");
window.setVisible(true);
}
}
MazeGamePanel:
public class MazeGamePanel extends JPanel implements Runnable {
private static final long serialVersionUID = 1L;
// Timer
public Timer timer;
// Font
public Font bitTrip;
public Thread thread;
public BufferedImage canvas;
public Graphics2D g;
public boolean running;
public int HEIGHT = MazeGame.HEIGHT;
public int WIDTH = MazeGame.WIDTH;
public int FPS = 30;
public int opacity = 255;
public int selectedOption = 0;
public String option1 = "Play";
public String option2 = "Controls";
public String option3 = "Quit";
public MazeGamePanel() {
this.setFocusable(true);
this.requestFocus();
addKeyListener(new MazeGameKeyListener());
try {
bitTrip = Font.createFont(Font.TRUETYPE_FONT, new File(
"res/font/BitTrip7.TTF"));
} catch (FontFormatException | IOException e) {
e.printStackTrace();
}
/**
ActionListener action = new ActionListener () {
public void actionPerformed (ActionEvent e) {
if(opacity != 0) {
opacity--;
} else {
timer.stop();
opacity = 0;
}
}
};
timer = new Timer(10, action);
timer.setInitialDelay(0);
timer.start();
*/
}
public void addNotify() {
super.addNotify();
if (thread == null) {
thread = new Thread(this);
thread.start();
}
}
public void run() {
running = true;
canvas = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
g = (Graphics2D) canvas.getGraphics();
long startTime = 0;
long millis = 0;
long waitTime = 0;
long targetTime = 1000 / FPS;
while (running) {
startTime = System.nanoTime();
update();
render();
draw();
millis = (System.nanoTime() - startTime) / 1000000;
waitTime = targetTime - millis;
try {
Thread.sleep(waitTime);
} catch (Exception e) {
}
}
}
// TODO
public void render() {
g.setColor(Color.WHITE);
g.fillRect(0, 0, WIDTH, HEIGHT);
bitTrip = bitTrip.deriveFont(40F);
g.setFont(bitTrip);
if (selectedOption == 0) {
//Play
g.setColor(Color.BLACK);
g.drawString(option1, WIDTH / 2 - 200, HEIGHT / 2);
//Controls
g.setColor(Color.GRAY);
g.drawString(option2, WIDTH / 2 - 200, HEIGHT / 2 + 50);
//Quit
g.setColor(Color.GRAY);
g.drawString(option3, WIDTH / 2 - 200, HEIGHT / 2 + 100);
} else if (selectedOption == 1) {
//Play
g.setColor(Color.GRAY);
g.drawString(option1, WIDTH / 2 - 200, HEIGHT / 2);
//Controls
g.setColor(Color.BLACK);
g.drawString(option2, WIDTH / 2 - 200, HEIGHT / 2 + 50);
//Quit
g.setColor(Color.GRAY);
g.drawString(option3, WIDTH / 2 - 200, HEIGHT / 2 + 100);
} else if (selectedOption == 2) {
//Play
g.setColor(Color.GRAY);
g.drawString(option1, WIDTH / 2 - 200, HEIGHT / 2);
//Controls
g.setColor(Color.GRAY);
g.drawString(option2, WIDTH / 2 - 200, HEIGHT / 2 + 50);
//Quit
g.setColor(Color.BLACK);
g.drawString(option3, WIDTH / 2 - 200, HEIGHT / 2 + 100);
}
//g.setColor(new Color(0, 0, 0, opacity));
//g.fillRect(0, 0, WIDTH, HEIGHT);
}
public void update() {
}
public void draw() {
Graphics g2 = this.getGraphics();
g2.drawImage(canvas, 0, 0, null);
g2.dispose();
}
private class MazeGameKeyListener extends KeyAdapter {
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_UP) {
if (selectedOption == 1) {
selectedOption = 0;
} else if (selectedOption == 2) {
selectedOption = 1;
}
}
if (e.getKeyCode() == KeyEvent.VK_DOWN) {
if (selectedOption == 0) {
selectedOption = 1;
} else if (selectedOption == 1) {
selectedOption = 2;
}
}
if(e.getKeyCode() == KeyEvent.VK_ENTER) {
if(selectedOption == 1) {
MazeGame.window.removeAll();
MazeGame.window.add(new MazeControlsPanel());
MazeGame.window.validate();
}
}
}
}
}
MazeControlsPanel:
package screens;
public class MazeControlsPanel extends JPanel implements Runnable {
private static final long serialVersionUID = 1L;
// Font
public Font bitTrip;
public Thread thread;
public BufferedImage canvas;
public Graphics2D g;
public boolean running;
public int HEIGHT = MazeGame.HEIGHT;
public int WIDTH = MazeGame.WIDTH;
public int FPS = 30;
public int opacity = 255;
public int selectedOption = 0;
public MazeControlsPanel() {
this.setFocusable(true);
this.requestFocus();
addKeyListener(new MazeControlsKeyListener());
try {
bitTrip = Font.createFont(Font.TRUETYPE_FONT, new File(
"res/font/BitTrip7.TTF"));
} catch (FontFormatException | IOException e) {
e.printStackTrace();
}
/**
final Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
if (opacity != 0) {
opacity--;
} else {
timer.cancel();
opacity = 0;
}
}
}, 0, 4);
*/ }
public void addNotify() {
super.addNotify();
if (thread == null) {
thread = new Thread(this);
thread.start();
}
}
public void run() {
running = true;
canvas = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
g = (Graphics2D) canvas.getGraphics();
long startTime = 0;
long millis = 0;
long waitTime = 0;
long targetTime = 1000 / FPS;
while (running) {
startTime = System.nanoTime();
update();
render();
draw();
millis = (System.nanoTime() - startTime) / 1000000;
waitTime = targetTime - millis;
try {
Thread.sleep(waitTime);
} catch (Exception e) {
}
}
}
// TODO
public void render() {
g.setColor(Color.WHITE);
g.fillRect(0, 0, WIDTH, HEIGHT);
bitTrip = bitTrip.deriveFont(40F);
g.setFont(bitTrip);
// Quit
g.setColor(Color.BLACK);
g.drawString("Main Menu", WIDTH / 2 - 200, HEIGHT / 2 + 100);
//g.setColor(new Color(0, 0, 0, opacity));
//g.fillRect(0, 0, WIDTH, HEIGHT);
}
public void update() {
}
public void draw() {
Graphics g2 = this.getGraphics();
g2.drawImage(canvas, 0, 0, null);
g2.dispose();
}
private class MazeControlsKeyListener extends KeyAdapter {
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
}
}
}
}
Here's a problem:
Don't use a java.util.Timer in a Swing program as you will have threading problems. Instead use a Swing Timer.
Also, you're making Swing calls in background threads and using Graphics object obtained by calling
getGraphics()
on a component, two no-nos for Swing programs.EDIT
Here is a program that I worked on that swaps components with a CardLayout, but fades one component out as it fades the other one in. What it does:
swap()
on the SwappingImgPanel instance.done()
method is called which sets the SwappingImgPanel's State to State.DONE.