I am trying to create a JPanel with a CardLayout that switches between a menu and a forum when a button is pressed, but I am encountering a visual error where elements of the menu are still displaying when I switch to the forum.
(If relevant, my system specifications are: MacBook Air (13-inch, Early 2015), 2.2 GHz Dual-Core Intel Core i7, 8 GB 1600 MHz DDR3, Intel HD Graphics 6000 1536 MB, MacOS Monterey 12.6.7)
What follows is a simplified example of my basic implementation. Obviously certain features are not fully implemented in the example.
Main Class:
import javax.swing.*;
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setContentPane(new MainPanel());
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
MainPanel Class:
import javax.swing.*;
import java.awt.*;
public class MainPanel extends JPanel {
private final CardLayout layout = new CardLayout();
private final Menu menuScreen;
private final Forum forumScreen;
public static final String MENU = "1";
public static final String FORUM = "2";
public MainPanel() {
setLayout(layout);
menuScreen = new Menu(this);
add(menuScreen, MENU);
forumScreen = new Forum(this);
add(forumScreen, FORUM);
layout.show(this, MENU);
}
public void navigate (String destination) {
layout.show(this, destination);
switch (destination) {
case MENU -> menuScreen.updateUI();
case FORUM -> forumScreen.updateUI();
}
this.revalidate();
this.updateUI();
}
}
Menu Class:
import java.awt.*;
import java.awt.event.ActionEvent;
public class Menu extends Screen {
private final MainPanel panel;
public Menu(MainPanel panel) {
this.panel = panel;
Button deleteButton = new Button("Delete");
deleteButton.addActionListener(this::delete);
add(deleteButton);
Button loadButton = new Button("Load");
loadButton.addActionListener(this::load);
add(loadButton);
Button forumButton = new Button("Forum");
forumButton.addActionListener(this::toForum);
add(forumButton);
}
private void toForum(ActionEvent actionEvent) {
panel.navigate(MainPanel.FORUM);
}
private void load(ActionEvent actionEvent) {
}
private void delete(ActionEvent actionEvent) {
}
}
Forum Class:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
public class Forum extends Screen {
private final MainPanel panel;
private final JSpinner heightField = new JSpinner(new SpinnerNumberModel(1,1,Integer.MAX_VALUE,1));
private final JSpinner widthField = new JSpinner(new SpinnerNumberModel(1, 1, Integer.MAX_VALUE, 1));
public Forum(MainPanel panel) {
this.panel = panel;
add(new Label("Forum", Label.CENTER));
add(new Label("Height"));
add(heightField);
add(new Label("Width"));
add(widthField);
Button exitButton = new Button("Exit");
exitButton.addActionListener(this::exit);
add(exitButton);
}
private void exit(ActionEvent actionEvent) {
panel.navigate(MainPanel.MENU);
}
}
Screen Class:
import javax.swing.*;
public class Screen extends JPanel {
public Screen() {
setBorder(BorderFactory.createEmptyBorder(30,30,30,30));
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
}
}
Functionally, the code succeeds at switching between the panels, but I've consistently been getting a visual glitch where elements of the last panel display and cover up elements on the new panel. I can still select the elements of the new panel that are covered up, and after I do so, they seem to be switched to the foreground in front of the glitched elements.
Menu Forum with Glitched Display
Note: this is part of a larger project so the UI seen here may not exactly match the code above. I will note, however, that a similar glitch has been seen throughout the project when using the CardLayout.
I have tried a variety of fixes. I rolled back my java version to java 11, but I still encountered the same problem. I made a loading card to force the ui to update with two switches, but I found that an empty loading card did not solve the problem and a loading card with elements still caused the visual glitch. As seen in the code, I tried a variety of calls that might update the panels such as revalidate, updateUI, and repaint, but nothing I have tried has worked.
Let me know if you have any suggestions.
It appears the visual glitch is resolved by switching from awt components (Button and Label) to swing lightweight components (JButton and JLabel). For instance, the menu class is:
Credit and thanks to hovercraft-full-of-eels