I have a project that I'm working on a project that requires 2 JFrames in a single program. The problem is that when I close one the other will also close so I made a test class to see what the issue was and I still couldn't figure it out so here is the test case that I have:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class frameTest {
public static void main(String[] args) {
JFrame f1 = new JFrame();
JButton open = new JButton("open");
open.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
JFrame f2 = new JFrame();
f2.setVisible(true);
f2.setDefaultCloseOperation(f2.EXIT_ON_CLOSE);
f2.setSize(200, 200);
}
});
f1.setDefaultCloseOperation(f1.EXIT_ON_CLOSE);
f1.setVisible(true);
f1.setSize(500, 500);
f1.add(open);
}
}
When I click the open button the popup (f2) will appear but when I close it the other window will also close, why does this happen?
f2.setDefaultCloseOperation(f2.EXIT_ON_CLOSE);
EXIT_ON_CLOSE means close the Java VM.
If you just want to close the current frame then use:
f2.setDefaultCloseOperation(f2.DISPOSE_ON_CLOSE);
Take a look on this line:
f2.setDefaultCloseOperation(f2.EXIT_ON_CLOSE);
It means that your application is terminated when you close the frame. So, not second frame is closed. Whole application is terminated.
If you do not want this behavior remove this line.
Related
I am working on a GUI project with Swing in Java and the program is generally working fine. However, under each screen, I have a back button that calls the method of the screen before it and goes through the ArrayList containing all of the elements on the current screen and calls setVisible(false) on them. Upon running the program, the back button works correctly if you click it once but if you go back on the screen, and click it again, it takes two clicks for it to correctly work and then four clicks and then eight clicks and so on. I have no idea what is going on or why it is behaving this way as nothing in my code seems to do it. Also, sometimes, the button correctly returns to the previous screen but then keeps the components on the current screen active as if setVisible(false) was never called. The following code represents the general structure of my project. Is there anything that it is doing that is generating this problem?
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class MAIN {
static JFrame frame;
static JPanel panel;
public static void main(String [] args) {
mainScreen();
}
public static void mainScreen() {
JButton newScreen = new JButton("Next Screen");
frame = new JFrame();
panel = new JPanel();
panel.setBounds(0,0,1920,1080);
panel.setBackground(Color.cyan);
newScreen.setBounds(50, 500, 100, 500);
newScreen.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
newScreen.setVisible(false);
JButton returnButton = new JButton("return");
returnButton.setBounds(50, 50, 100, 100);
panel.add(returnButton);
returnButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
returnButton.setVisible(false);
mainScreen();
}
});
}
});
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel.add(newScreen);
frame.add(panel);
frame.setSize(1920,1080);
frame.setLayout(null);
frame.setVisible(true);
}
}
I am making a GUI for a game, and I have a splash screen which I created using JFrame. I have a button which says play and what I want after that to happen is when I press play, I want to switch to another JFrame, which is going to have different stuff in it. However, I do not want the window to close and open another one, I want it to just switch from one frame to another frame.
I have no experience on GUI, if you have any information that would help it would be greatly appreciated.
Here is an example:
import javax.swing.JFrame;
import javax.swing.JButton;
public class Test {
public static void main(String[] args) {
JFrame f = new JFrame();
f.setBounds(10, 10, 500, 200);
JButton b1 = new JButton("b1");
b1.addActionListener((c) -> {
buttonPressed(f);
});
f.setContentPane(b1);
f.setVisible(true);
}
private static void buttonPressed(JFrame f) {
JButton b2 = new JButton("b2");
f.setContentPane(b2);
f.revalidate();
}
When b1 is pressed, the content pane for the frame is replaced with a new button. the revalidate() call is needed in order for the UI to refresh after the change.
So far all i have managed to get is the JButton to close the first JFrame (frame) but the other will not open.
Frame class code
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Frame {
public static void main(String[] args) {
// Frame - Labelled BrickFall
final JFrame frame = new JFrame();
frame.setSize(1290, 730);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("BrickFall");
frame.setLayout(null);
frame.setLocationRelativeTo(null);
// Start Button
JButton Start = new JButton("Start");
Start.setBounds(100, 300, 1080, 50);
frame.add(Start);
// Exit Button
JButton Exit = new JButton("Exit");
Exit.setBounds(369, 375, 540, 50);
frame.add(Exit);
// Closes when Exit Clicked
Exit.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
//New Frame opens when Start Clicked
Start.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
frame.setVisible(false);
}
});
// Background Image
JLabel background = new JLabel("");
background.setBounds(0, 0, 1280, 720);
background.setIcon(new ImageIcon(Frame.class.getResource("/resources/images/Title.png")));
frame.getContentPane().setLayout(null);
frame.getContentPane().add(background);
frame.setVisible(true);
}
protected static void dispose() {
// TODO Auto-generated method stub
}
}
On the (frame) action listener i have left out the second line to open the other JFrame as my attempts wont work
Game class code
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class game {
public static void main(String[] args) {
// Frame - Labelled BrickFall
JFrame game = new JFrame();
game.setSize(1290, 730);
game.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
game.setTitle("BrickFall");
game.setLayout(null);
game.setLocationRelativeTo(null);
// Background Image
JLabel GameBackground = new JLabel("");
GameBackground.setBounds(0, 0, 1280, 720);
GameBackground.setIcon(new ImageIcon(Frame.class.getResource("/resources/images/Fill In.png"))); //Change Picture When Required
game.getContentPane().setLayout(null);
game.getContentPane().add(GameBackground);
game.setVisible(true);
}
}
If anyone has any suggestions on how I can sort this I will be very thankful.
You're disposing the JFrame and setting its default close operation to JFrame.EXIT_ON_CLOSE which closes the JVM, shutting down your entire program.
Solution 1: Make your JFrame invisible via setVisible(false)
or if you do use dispose(), make sure that you set its default close operation to anything but what you're currently doing: frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); as this also closes the JVM.
Solution 2: better yet, make the closing window a JDialog.
Solution 3: Even better, don't spit different windows at the user, but rather swap views by swapping JPanels with a CardLayout. For details, please check out the CardLayout Tutorial.
Suggestion: don't use null layouts like you're doing, but rather learn to use the different layout managers.
Suggestion: get out of the main method. Don't make your classes nothing but large static main methods, basically 1970's procedural programming. Learn to use and then create OOP-compliant classes with constructors, non-static fields, non-static methods, with states and behaviors, and have these classes interact in a pleasing and useful fashion.
I am trying to develop a JFrame which has two buttons that would let me to call the main method of other classes. The first try was to put it directly into the actionPerformed of each button, this will cause the JFrame of the other class to open but showing only the title of it and not showing any contents of the JPanel additionally freezing the program (can't even press close button, have to go into task manager or eclipse to kill it). The second try was adding a method call in actionPerformed, and adding the method will this time call the main method of other class however the same result (freeze of program).
For testing purposes I have placed the call to main method of other class, straight in this class main method which has proven to me that the frame of other class has successfully appeared, including all its JPanel contents, functionality etc.
I know I could make some kind of infinite loop in my main method to wait until a boolean is set to true, but then I though there must be some less-expensive way to get it working. So here I am asking this question to you guys.
Here is the code of the 2nd try;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Chat {
public static void main (String[] args) {
JFrame window = new JFrame("Chat Selection");
//Set the default operation when user closes the window (frame)
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Set the size of the window
window.setSize(600, 400);
//Do not allow resizing of the window
window.setResizable(false);
//Set the position of the window to be in middle of the screen when program is started
window.setLocationRelativeTo(null);
//Call the setUpWindow method for setting up all the components needed in the window
window = setUpWindow(window);
//Set the window to be visible
window.setVisible(true);
}
private static JFrame setUpWindow(JFrame window) {
//Create an instance of the JPanel object
JPanel panel = new JPanel();
//Set the panel's layout manager to null
panel.setLayout(null);
//Set the bounds of the window
panel.setBounds(0, 0, 600, 400);
JButton client = new JButton("Run Client");
JButton server = new JButton("Run Server");
JLabel author = new JLabel("By xxx");
client.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//run client main
runClient();
}
});
server.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//run server main
}
});
panel.add(client);
client.setBounds(10,20,250,200);
panel.add(server);
server.setBounds(270,20,250,200);
panel.add(author);
author.setBounds(230, 350, 200, 25);
window.add(panel);
return window;
}
private static void runClient() {
String[] args1={"10"};
ClientMain.main(args1);
}
}
Only one main method is allowed per application. Honestly I am not sure what you are trying to do or think is supposed to happen when you call main on other classes. When you call main on other classes all you are doing is calling a method that happens to be called main and passing args to it. Your freezing is probably because you are not using Swing correctly:
http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
The problem you're having is that Java Swing is single threaded. When you're running the main function of the other class, however you do it, the GUI won't be able to keep running until it returns. Try spawning off a new thread that calls the second main method.
private static void runClient() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
String[] args1={"10"};
ClientMain.main(args1);
}
});
}
EDIT: Updated, as per #Radiodef's suggestion. Missed at the top when you said this second class had to display things on the GUI. Definitely want to go with the invokeLater then.
I have a weird problem with modal dialogs and undecorated JFrame.
If I create a main undecorated JFrame then I display a modal dialog thanks to the JOptionPane, everything goes well. The modal dialog stays always on top and I can't click on the main fame.
But, if create another JFrame (or another JDialog), the modal dialog still prevent me to interact with the main frame, but now the modal dialog is not always on top and go underneath the main frame when I click on it.
This problem doesn't happen:
if the main frame is decorated
or if the second frame is not visible
EDIT
I use jdk1.7.0.0_09 on Linux Suse.But I have the same result with jre 1.6.0_32
The code I used to test:
public static void main(String[] args) {
// creates main frame and set visible to true
final JFrame mainFrame = new JFrame();
mainFrame.setUndecorated(true); // if I comment this line, everything goes well
mainFrame.add((new JPanel()).add(new JButton("OK")));
mainFrame.setSize(new Dimension(500, 500));
mainFrame.setVisible(true);
// creates a dialog and set visible to true
JFrame anotherFrame = new JFrame();
anotherFrame.setVisible(true); // or if I comment this line, everything goes well too
// display a modal dialog
JOptionPane.showMessageDialog(mainFrame, "A message");
}
But, if create another JFrame (or another JDialog), the modal dialog
still prevent me to interact with the main frame, but now the modal
dialog is not always on top and go underneath the main frame when I
click on it.
not true at all, both are not accesible untill JOptioPane is visible
JOptionPane or JDialod.setModal(true) block mouse or key events to the alll windows invoked from currnet JVM
there must be something else that isn't clear from your question, rest of code, minor could be Java version and Native OS
code for Java6 (winxp), works for me on Win7 / Java7(x.x_011)
import java.awt.Dimension;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class Main {
private JFrame mainFrame = new JFrame();
private JFrame anotherFrame = new JFrame();
public Main() {
mainFrame.setUndecorated(true);
mainFrame.add((new JPanel()).add(new JButton("OK")));
mainFrame.setSize(new Dimension(100, 60));
mainFrame.setVisible(true);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
anotherFrame.setVisible(true);
anotherFrame.setLocation(110, 0);
anotherFrame.setSize(new Dimension(100, 60));
anotherFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JOptionPane.showMessageDialog(mainFrame, "A message");
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
Main main = new Main();
}
});
}
}