The Use of Multiple JFrames: Good or Bad Practice?
I'm just wondering whether it is good practice to use multiple JFrames?
Bad (bad, bad) practice.
- User unfriendly: The user sees multiple icons in their task bar when expecting to see only one. Plus the side effects of the coding problems..
- A nightmare to code and maintain:
- A modal dialog offers the easy opportunity to focus attention on the content of that dialog - choose/fix/cancel this, then proceed. Multiple frames do not.
- A dialog (or floating tool-bar) with a parent will come to front when the parent is clicked on - you'd have to implement that in frames if that was the desired behavior.
There are any number of ways of displaying many elements in one GUI, e.g.:
CardLayout
(short demo.). Good for:- Showing wizard like dialogs.
- Displaying list, tree etc. selections for items that have an associated component.
- Flipping between no component and visible component.
JInternalFrame
/JDesktopPane
typically used for an MDI.JTabbedPane
for groups of components.JSplitPane
A way to display two components of which the importance between one or the other (the size) varies according to what the user is doing.JLayeredPane
far many well ..layered components.JToolBar
typically contains groups of actions or controls. Can be dragged around the GUI, or off it entirely according to user need. As mentioned above, will minimize/restore according to the parent doing so.- As items in a
JList
(simple example below). - As nodes in a
JTree
. - Nested layouts.
But if those strategies do not work for a particular use-case, try the following. Establish a single main JFrame
, then have JDialog
or JOptionPane
instances appear for the rest of the free-floating elements, using the frame as the parent for the dialogs.
Many images
In this case where the multiple elements are images, it would be better to use either of the following instead:
- A single
JLabel
(centered in a scroll pane) to display whichever image the user is interested in at that moment. As seen inImageViewer
. - A single row
JList
. As seen in this answer. The 'single row' part of that only works if they are all the same dimensions. Alternately, if you are prepared to scale the images on the fly, and they are all the same aspect ratio (e.g. 4:3 or 16:9).
Dealing with multiple JFrames
Use
JFrame.dispose()
on the second JFrame.
Also when using setDefaultCloseOperation() //this is what happens when you press x on window.
avoid EXIT_ON_CLOSE and use DISPOSE_ON_CLOSE.
PS:Where is the code? :P
Multiple JFrames
You should not be using multiple JFrames
See this link for more info.
Instead, I suggest you use a CardLayout as demonstrated here:
import javax.swing.*;
import java.awt.*;
public class MainFrame
{
static JPanel homeContainer;
static CardLayout cl;
JPanel homePanel;
JPanel otherPanel;
public MainFrame()
{
JFrame mFrame = new JFrame("CardLayout Example");
JButton showOtherPanelBtn = new JButton("Show Other Panel");
JButton backToHomeBtn = new JButton("Show Home Panel");
cl = new CardLayout(5, 5);
homeContainer = new JPanel(cl);
homeContainer.setBackground(Color.black);
homePanel = new JPanel();
homePanel.setBackground(Color.blue);
homePanel.add(showOtherPanelBtn);
homeContainer.add(homePanel, "Home");
otherPanel = new JPanel();
otherPanel.setBackground(Color.green);
otherPanel.add(backToHomeBtn);
homeContainer.add(otherPanel, "Other Panel");
showOtherPanelBtn.addActionListener(e -> cl.show(homeContainer, "Other Panel"));
backToHomeBtn.addActionListener(e -> cl.show(homeContainer, "Home"));
mFrame.add(homeContainer);
cl.show(homeContainer, "Home");
mFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
mFrame.setLocationRelativeTo(null);
mFrame.setExtendedState(JFrame.MAXIMIZED_BOTH);
mFrame.pack();
mFrame.setVisible(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(MainFrame::new);
}
}
With a Cardlayout, you switch between JPanel's instead. This way, you don't have to create a new JFrame, just to display new content. Basically, you have some sort of container, (Could be the JFrame
or could be a JPanel
) and then, when you add the other panels that you create, you give them a name. You can then switch between the panels using cardLayout.show(container, "Name");
Multiple JFrames in One Application
Here:
// suspend program until button is pushed
// i know, **this is not a very good way of doing it...** (emphasis mine)
while(!askPush){}
as you already know, this "is not a very good way of doing it..."
. It's not only not a very good way, it's a terrible way and will freeze up your Swing event thread and is not how event driven programming should be done. Simply don't do this.
What you want to use instead is a modal dialog such as a JOptionPane or a modal JDialog. This will freeze your calling code at the time of the request while not freezing the Swing event thread. The calling code will resume once the dialog is no longer visible.
Other issues:
- Your program is little more than one big bunch of static fields and methods with no true classes that have state and behavior. It's as if you're trying to shove a console program into an event-driven program. Don't do this. Instead first extract out the non-GUI objects that will be needed and make classes for them. Then create a GUI with true non-static methods and fields and that uses the non-GUI objects as its "model".
- Examples of modal dialogs:
- JFrame questions
- Passing values between JFrames
Making multiple frames in a single program
you are looking for a JFrame
with a CardLayout
. Some background:
A JFrame is the physical window. It comes with a title bar and three buttons: minimize, maximize, and close. Think of this as a picture frame.
A JPanel is a "content holder" of sorts. Typically, you put your other components (buttons, animations, whatever) on a JPanel, and then slap that JPanel into a JFrame. Using our picture frame example, a JPanel would be the photo paper you put in the picture frame. The other components would then be the actual contents of the picture itself, and what you have at the end is a nice picture...or in your case, an application.
Setting the JFrame to utilize a CardLayout
essentially lets you have multiple JPanels inside the same JFrame at once, while still only showing one at a time. So for your application, you would have (at least) two JPanels: one for the menu, and one for the game. When the app starts, you show the MenuPanel. When the user clicks "start", you switch to the GamePanel. The MenuPanel will be put in the background and will be inaccessible until you call it to the foreground again.
If, on the other hand, you create multiple JFrames, you will have two or more physically separate windows that can be dealt with individually. This can actually be kind of cool for game development. Although it takes more time to build and link the GUI for the second window, you can then have that window affect game settings in realtime (rate of fire, bullet strength, player speed, etc.)
How to avoid multiple frames?
Make the frame an instance variable. Whenever you have to display a new frame, check if it is already displayed and if it is, first close the existing one and then display the new one.
Related Topics
Calculating the Difference Between Two Java Date Instances
Validating Input Using Java.Util.Scanner
How to Solve "Java.Lang.Noclassdeffounderror"
Java - Sending Http Parameters Via Post Method Easily
How Do Getters and Setters Work
Creating a Custom Button in Java With Jbutton
How to Allow All Network Connection Types Http and Https in Android (9) Pie
Floating Point Arithmetic Not Producing Exact Results
String Concatenation: Concat() VS "+" Operator
Parsing Query Strings on Android
How to Import the Javax.Servlet/Jakarta.Servlet API in My Eclipse Project
How to Retrieve and Display Images from a Database in a Jsp Page
Is There an Eval() Function in Java
Round a Double to 2 Decimal Places
When Is the Finalize() Method Called in Java
Why Doesn't Recyclerview Have Onitemclicklistener()
Servlet Returns "Http Status 404 the Requested Resource (/Servlet) Is Not Available"