I'm currently working on an implementation of the card game "Munchkin" (for me and my friends to play during the pandemic) and display the Munchkin logo on the launcher. The code actually works pretty well in setting the logo exactly where it should be.
However I encounter an issue on resizing events of the JFrame: Initially when e.g. resizing the frame to its minimum size, the image takes about 5 seconds to load and only after that the content contained within the frame is updated. Before the reloading of the image is done, the content is only partially visible inside the screen, e.g. the buttons are still outside of the frame.
After repeatedly resizing the loading times of the UI seem to increase exponentially (possibly because the loading and scaling of the image is performed for multiple frame sizes between the sizes before and after scaling). Also the image takes a perceivable amount of time to load (like 0.5 seconds) when the frame is newly generated.
To make clearer what I mean, here's what it looks like initially and shortly after resizing:
Before:
To give you some insight here's the code, doing all the UI stuff:
package de.munchkin.frontend;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class MunchkinLauncher extends JFrame{
private static final long serialVersionUID = 1598309638008663371L;
private Toolkit toolkit = Toolkit.getDefaultToolkit();
private Dimension screenDim = toolkit.getScreenSize();
private JPanel contentPane;
private JButton btnHostGame, btnJoinGame;
private JLabel imageLabel;
public static void main(String[] args) {
new MunchkinLauncher();
}
public MunchkinLauncher() {
setTitle("Munchkin Launcher");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocation(screenDim.width / 4, screenDim.height / 4);
setSize(screenDim.width / 2, screenDim.height / 2);
setMinimumSize(new Dimension(700, 387));
contentPane = new JPanel(null);
contentPane.setLayout(null);
setLayout(null);
setContentPane(contentPane);
contentPane.setBackground(new Color(253, 205, 136));
setVisible(true);
loadComponents();
loadBounds();
addActionListeners();
}
private void loadComponents() {
// Load header image
imageLabel = new JLabel("");
btnHostGame = new JButton("Host Game");
btnJoinGame = new JButton("Join Game");
}
private void loadBounds() {
int width = contentPane.getSize().width;
int height = contentPane.getSize().height;
btnHostGame.setBounds(width/2 - 300, height * 2 / 3, 250, 100);
contentPane.add(btnHostGame);
btnJoinGame.setBounds(width/2 + 50, height * 2 / 3, 250, 100);
contentPane.add(btnJoinGame);
imageLabel.setIcon(new ImageIcon(new ImageIcon(this.getClass().getResource("/Munchkin_logo.jpg"))
.getImage().getScaledInstance(width - 40, height * 2 / 3 - 40, Image.SCALE_DEFAULT)));
imageLabel.setBounds(20, 0, width - 40, height * 2 / 3);
contentPane.add(imageLabel);
revalidate();
repaint();
}
private void addActionListeners() {
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
super.componentResized(e);
loadBounds();
}
});
btnHostGame.addActionListener(e -> {
new MatchCreation();
dispose();
});
btnJoinGame.addActionListener(e -> {
new MatchJoin();
dispose();
});
}
}
I also tried to load the inner ImageIcon resource itself separately in loadComponents()
in order to reduce loading times, however it appears to me as if it takes even longer to update by doing so. I think it could have something to do with the image's original size as it has a resolution of 4961 x 1658 px
. I also tried different scaling algorithms and also using Image.SCALE_FAST
didn't perceivably accelerate the process.
What puzzles me the most is that this process is executed on high-end hardware (3900X + 2080Ti) which means that mid-range or low-end PCs probably would take even longer to load and update this which makes this even more absurd to me. If there was no other solution I assume just even basic 2D games would still lag as hell on nowadays hardware which they obviously don't.
Are there any best practices when loading images for resizing that I'm missing or how could I solve this issue in general?