I have two JFrames:
ApplicationsJFrame, which is my Main, and
InsertApplicationsForm.
I'm setting the InsertApplicationsForm visible by clicking a Button in my ApplicationsJFrame.
Every time I'm closing the InsertApplicationsForm the ApplicationsJFrame also closes, but the Program is still running, same when I minimize InsertApplicationsForm, ApplicationsJFrame minimizes, but wont maximize anymore...
ApplicationsJFrame:
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setTitle("T-AMS");
setFocusableWindowState(false);
InsertApplicationsForm:
public class InsertApplicationForm extends javax.swing.JFrame {
/**
* Creates new form InsertApplicationForm
*/
public InsertApplicationForm() {
initComponents();
}
[...]
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
setTitle("Insert Application")
addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosed(java.awt.event.WindowEvent evt) {
formWindowClosed(evt);
}
});
private void formWindowClosed(java.awt.event.WindowEvent evt) {
ApplicationsJFrame.insert = false;
}
Open InsertApplicationsForm:
new InsertApplicationForm().setVisible(true);
You should just add the EXIT_ON_CLOSE constant int to your main JFrame.
Instead, add a WindowListener to your temporal Frames:
//Suppose you have a custom Frame in your Form class
class InsertApplicationsForm extends JFrame{
//Some stuff
//...
public InsertApplicationsForm(){
//Implement
//DO NOT ADD setDefaultCloseOperation
setVisible(true);
}
addWindowListener(new WindowAdapter(){
#Override
public void windowClosing(WindowEvent e){
InsertApplicationsForm.this.dispose();
}
});
}
So in your main class, or method, event, whatever just call this:
new InsertApplicationsForm();
And will automatically open a new JFrame, which you can close and not affecting the main or other Frames. You can even instance multiple of this class Frames and closing won't affect other ones.
Related
I'm curious how can I use a dialog designer that is built into IntelliJ IDEA since I find it an option with big potential but I don't really know how to use it.
Let's consider a desktop program with two classes created using designer: MainWindow and MainDialog. Let's assume that MainWindow class already has all fields, components etc. required for a simple form to be displayed. Then in the MainWindow class we have:
JLabel label = new JLabel("This is default text");
JButton showDialog = new JButton("Show dialog");
showDialog.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
MainDialog dialog = new MainDialog ();
dialog.pack();
dialog.setVisible(true);
}
});
which makes the dialog visible. The MainDialog class designed by default by designer looks like this:
public class MainDialog extends JDialog {
private JPanel contentPane;
private JButton buttonOK;
private JButton buttonCancel;
public MainDialog() {
setContentPane(contentPane);
setModal(true);
getRootPane().setDefaultButton(buttonOK);
buttonOK.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
onOK();
}
});
buttonCancel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
onCancel();
}
});
// call onCancel() when cross is clicked
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
onCancel();
}
});
// call onCancel() on ESCAPE
contentPane.registerKeyboardAction(new ActionListener() {
public void actionPerformed(ActionEvent e) {
onCancel();
}
}, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
}
private void onOK() {
// add your code here
dispose();
}
private void onCancel() {
// add your code here if necessary
dispose();
}
}
Now let's also assume that in the dialog class I have a text field:
JTextField textField = new JTextField();
that I am getting a text to be displayed by label in the MainWindow class from.
Since I have an onOK() function created by default I'd like it to update a label in MainWindow class with text typed in text field in MainDialog class.
The problem is: how can I perform an action on another class's field using this pattern without writing in MainDialog a line MainWindow window = new MainWindow or making label static? Is it possible? I know that this can be done much simpler but this is also an easy example and I'd like to perform much more complex operations using this structure.
Yes, it's possible.
First option: since the dialog is modal, the code opening the modal in the main window will be blocked until the dialog is closed. So you could just do something like this in the modal:
public String getEnteredText() {
return textField.getText();
}
and in the main window:
dialog.setVisible(true);
myLabel.setText(dialog.getEnteredText());
Or (but I would use the first option), you can pass the main window, or any other callback, to the dialog. For example:
MainDialog dialog = new MainDialog(this);
And in the dialog:
private void onOK() {
mainWindow.setLabelText(textField.getText());
dispose();
}
My recommendation is to avoid UI designers. Especially if you're not able yet to write the code that they generate by yourself, and you don't have a deep understanding of how Swing works.
I'm working on a program which has multiple JFrame and JDialog windows.
I have a JFrame which contains a button, when I click on this button a JDialog window opens up. In this JDialog windows there is another button, which when is clicked it opens up a second JDialog window. In the second JDialog window I have a last button.
What I want to do is to close both JDialog windows and JFrame window when this last button is clicked.
This is how the opening order is:
JFrame Frame1;
JButton Button1;
JDialog Dialog1;
JButton Button2;
JDialog Dialog2;
JButton Button3;
Button1ActionPerformed(ActionEvent e){
new Dialog(Frame1Frame);
}
Button2ActionPerformed(ActionEvent e){
new Dialog2(Dialog1Frame)
}
Button3ActionPerformed(ActionEvent e){
//Here I wnat to add the code that closes JDialog2 JDialog1 and JFrame1 windows.
}
I have tried super.dispose(); but it doesn't work. Any ideas?
As shown here using Action, your actionPerformed() implementation can dispatch the WINDOW_CLOSING event to the desired Window instances.
#Override
public void actionPerformed(ActionEvent e) {
d1.dispatchEvent(new WindowEvent(d1, WindowEvent.WINDOW_CLOSING));
d2.dispatchEvent(new WindowEvent(d2, WindowEvent.WINDOW_CLOSING));
f1.dispatchEvent(new WindowEvent(f1, WindowEvent.WINDOW_CLOSING));
}
There may be better ways of doing this, but here is one general approach that might help.
In your code you create the windows but you do not store the reference to the windows you created into a variable. For example, you have:
JDialog Dialog1;
Then later, when you create the instance of Dialog1, you have this code:
Button1ActionPerformed(ActionEvent e){
new Dialog(Frame1Frame);
}
This means you have created the Dialog, but you have not retained a reference to the Dialog for later manipulation by your code. If you assign this value here, you should be able to manipulate it later.
If you change your implementation to:
Button1ActionPerformed(ActionEvent e){
Dialog1 = new Dialog(Frame1Frame);
}
Then later in your code you will have a reference to the Dialog in order to manipulate it,
Button3ActionPerformed(ActionEvent e){
Dialog1.dispose();
// you can manipulate the variables of the class from here and close other windows etc.
}
If you have the objects reference, you can do:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
public class Main
{
private static JFrame frame;
private static JButton buttonFrame;
private static JDialog dialog1;
private static JButton buttonDialog1;
private static JDialog dialog2;
private static JButton buttonDialog2;
public static void main(String[] args) {
/* frame */
frame = new JFrame("Main Frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.setLocationRelativeTo(null);
buttonFrame = new JButton("open dialog 1");
buttonFrame.addActionListener(new ActionListener() {
#Override public void actionPerformed(ActionEvent e) {
dialog1.setVisible(true);
}
});
frame.add(buttonFrame);
/* dialog 1 */
dialog1 = new JDialog(frame, "Dialog 1");
dialog1.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog1.setSize(300, 300);
dialog1.setLocationRelativeTo(null);
buttonDialog1 = new JButton("open dialog 2");
buttonDialog1.addActionListener(new ActionListener() {
#Override public void actionPerformed(ActionEvent e) {
dialog2.setVisible(true);
}
});
dialog1.add(buttonDialog1);
/* dialog 2 */
dialog2 = new JDialog(dialog1, "Dialog 2");
dialog2.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog2.setSize(200, 200);
dialog2.setLocationRelativeTo(null);
buttonDialog2 = new JButton("close all");
buttonDialog2.addActionListener(new ActionListener() {
#Override public void actionPerformed(ActionEvent e) {
dialog2.dispose();
dialog1.dispose();
frame.dispose();
}
});
dialog2.add(buttonDialog2);
/* show frame */
frame.setVisible(true);
}
}
Otherwise you can use System.exit(0);:
buttonDialog2.addActionListener(new ActionListener() {
#Override public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
Closing multiple JFrame by another JFrame-
It is possible to close multiple windows, even non-static Java swing windows. Type below small code, step by step.
The below code is mainly for closing the First frame through the second open frame which has been opened by the same First frame.
*Make a **second class global variable** in the first-class & a **button global variable in first-class*
Class2 NiceApp1 = new Class2();
JToggleButton Nice=new JToggleButton("Nice One");
// *After the Class1 above code, you will need a close method. I use a jar of NiceApplication1 with class New Close you can use the same jar or very below close method and can call the close method. You will need to type the method in Class1, just type your **close method in the method**.*
public void method (){
NewClose NiceO = new NewClose();
NiceO.Close(this);
//or
Close();
}
*// Now make a **Button Global variable in Class2**.*
javax.swing.JToggleButton Zero = new javax.swing.JToggleButton();
*// Type in Class2 the below **method**.*
public void methodclass2(JToggleButton Nice){
Zero = Nice;
}
*//Now you will need to type the below code, type the below code in the **Class1 button action** by which you will open the Class2.*
Nice.addActionListener((ActionEvent e) -> {
method();
});
NiceApp1.methodclass2(Nice);
NiceApp1.setVisible(true);
*//Now just type a **single line code** in the second class, type anywhere from which you want to close Class1.*
Zero.doClick();
*//Now the **close method** if you don't have a close method.*
public void Close() {
WindowEvent winclosing = new WindowEvent(this, WindowEvent.WINDOW_CLOSING);
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(winclosing);
}
**You have done now if you did the above process.
If you only want to close which opens secondly so by the only close method change the this into your frame variables.
You can also visit NiceApplication1.BlogSpot.Com.
You can use the above code. From Class2 after the button's click, you will see your previous Class1 window will close.**
I'm having the following bug/problem and I havent been able to found solution yet on web or example of someone with similar issue.Basicaly I have a main frame that contains a panel of the same size(acting as the main panel) and When you press "Enter" an internal frame pop up(on top of where the playersprite is) acting as the inventory and then the control is passed to it and if you press "Enter" again the inventory is destroyed and control is passed back to the main panel.
the repaint function is called and the character and the map is then redrawn and this work about 90% of the time.The other 10% or less of time whenever the inventory is destroyed it seems the repaint is called(and work) except nothing is drawn its as if it draw on the destroyed panel because if I add a debug keypress that call repaint on the mainpanel(thescreen) everything is back to normal.
of course I could just repaint the character every loop in the run() method but thats terrible since I will only repaint if something changed(ie I moved)
I removed all the move and other code since they arent useful and still get the problem with the below code.You can think of the Character class as a plain drawn square.Anyone as any insight on why this is happening?
public class main extends JFrame implements Runnable{
private boolean gameRunning=true;
private Character Link;
private MainScreen theScreen;
public final int ScreenHeight=500;
public final int ScreenWidth=500;
public boolean inMenu=false;
Block ablock=new Block(200,200);
public class Inventory extends JInternalFrame{
public Inventory(){
setBounds(25,25,300,300);
setDefaultCloseOperation(HIDE_ON_CLOSE);
setVisible(true);
addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e){
int key=e.getKeyCode();
if(key==KeyEvent.VK_ENTER){
try{
setClosed(true);
theScreen.requestFocusInWindow();
theScreen.repaint();
inMenu=false;
}
catch(Exception ex){}
}
}});
}
}
class MainScreen extends JPanel{
MainScreen(){
super();
setIgnoreRepaint(true);
setFocusable(true);
setBounds(0,0,ScreenWidth,ScreenHeight);
setVisible(true);
setBackground(Color.white);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Link.draw(g);
g.drawImage(ablock.getImg(),ablock.getX(), ablock.getY(),null);
}
}
main(){
super();
final JDesktopPane desk = new JDesktopPane();
theScreen=new MainScreen();
add(theScreen);
theScreen.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e){
int key=e.getKeyCode();
if(key==KeyEvent.VK_ENTER){
inMenu=true;
Inventory myInventory=new Inventory();
desk.add(myInventory);
myInventory.requestFocusInWindow();
}
}
});
add(desk);
try {
UIManager.setLookAndFeel(
UIManager.getSystemLookAndFeelClassName());
}
catch (Exception e) {}
setTitle("Project X");
setResizable(false);
Link=new Character();
setSize(500,500);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static void main(String[] args) {
main Game=new main();
new Thread(Game).start();
}
public void run(){
//omitted/irrelevant only contains a FPS count
}
}
}
Don't use KeyListeners. Use Key Bindings.
Don't use a Thread. Use a Swing Timer for animation so updates will be done on the EDT.
Don't use an Internal Frame for a popup window. Use a JDialog.
Do custom painting on a JPanel, not a JDesktopPane.
Don't use setIgnoreRepaints(). That is used for active rendering.
Don't use empty catch clauses.
Use standard Java naming conventions. Classes start with upper cases characters, variable names do not.
Don't use setBounds(). Use a Layout Manager.
I have a button in my GUI that is supposed to close its window. However, its event handler is located in an AbstractAction subclass that is located in a seperate method from the JFrame. Because of this I cannot see a way to tell the JFrame to close from my AbstractAction.
Heres the basic layout of my code:
public PointWindow()
{
initialize();
}
public void initialize()
{
JFrame frame = new JFrame();
// JFrame stuff
frame.setContentPane(createGUI());
frame.setVisible(true);
}
public JPanel createGUI()
{
JPanel gui = new JPanel();
// Code....
class MakeGraphACT extends AbstractAction
{
public void actionPerformed(ActionEvent e)
{
frame.setVisible(false); // <--- How to get this to work?
frame.dispose(); // <---
new GraphWindow(pointList);
}
}
//Code...
return gui;
}
Have I done a bad job planning my code or am I just missing something obvious?
You need to pass the frame as a final parameter to the createGUI() method.
You will then be able to access it from within the inner class.
I have a class FilePathDialog which extends JDialog and that class is being called from some class X. Here is a method in class X
projectDialog = new FilePathDialog();
projectDialog.setVisible(true);
projectDialog.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.out.println("Window closing");
try {
doWork();
} catch (Throwable t) {
t.printStackTrace();
}
}
public void windowClosed(WindowEvent e) {
System.out.println("Window closed");
try {
doWork();
} catch (Throwable t) {
t.printStackTrace();
}
}
});
doWork never gets called when the JDialog window closes. All I'm trying to do is wait for the JDialog to close before it proceeds in the method. I also tried using SwingWorker and Runnable but that did not help.
Again, the key is is the dialog modal or not?
If it's modal, then there's no need for a WindowListener as you will know that the dialog has been dealt with since code will resume immediately below your call to setVisible(true) on the dialog. i.e., this should work:
projectDialog = new FilePathDialog();
projectDialog.setVisible(true);
doWork(); // will not be called until the dialog is no longer visible
If on the other hand it's mode-less, then a WindowListener should work, and you've likely got another problem in code not shown here, and you'll want to post an sscce for us to analyze, run, and modify.
Edit for gpeche
Please check out this SSCCE that shows that the 3 types of default closing parameters will trigger the window listener:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class DialogClosing {
private static void createAndShowGui() {
JFrame frame = new JFrame("DialogClosing");
JPanel mainPanel = new JPanel();
mainPanel.add(new JButton(new MyAction(frame, JDialog.DISPOSE_ON_CLOSE, "DISPOSE_ON_CLOSE")));
mainPanel.add(new JButton(new MyAction(frame, JDialog.HIDE_ON_CLOSE, "HIDE_ON_CLOSE")));
mainPanel.add(new JButton(new MyAction(frame, JDialog.DO_NOTHING_ON_CLOSE, "DO_NOTHING_ON_CLOSE")));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class MyAction extends AbstractAction {
private JDialog dialog;
private String title;
public MyAction(JFrame frame, int defaultCloseOp, final String title) {
super(title);
dialog = new JDialog(frame, title, false);
dialog.setDefaultCloseOperation(defaultCloseOp);
dialog.setPreferredSize(new Dimension(300, 200));
dialog.pack();
dialog.addWindowListener(new WindowAdapter() {
#Override
public void windowClosed(WindowEvent e) {
System.out.println(title + " window closed");
}
#Override
public void windowClosing(WindowEvent e) {
System.out.println(title + " window closing");
}
});
this.title = title;
}
#Override
public void actionPerformed(ActionEvent arg0) {
dialog.setVisible(true);
}
}
Javadoc for WindowListener.windowClosed():
Invoked when a window has been closed as the result of calling dispose on the window.
And for JDialog.setDefaultCloseOperation():
Sets the operation which will happen by default when the user initiates a "close" on this dialog. The possible choices are:
DO_NOTHING_ON_CLOSE - do not do anything - require the program to handle the operation in the windowClosing method of a registered WindowListener object.
HIDE_ON_CLOSE - automatically hide the dialog after invoking any registered WindowListener objects
DISPOSE_ON_CLOSE - automatically hide and dispose the dialog after invoking any registered WindowListener objects
The value is set to HIDE_ON_CLOSE by default.
That suggests that you should call projectDialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); after instantiating FilePathDialog.
answer to your question
add WindowListener to your JDialog (JDialog.DO_NOTHING_ON_CLOSE) , on windowClosing event to try to run your code, if ends with success then call dispose(), or setVisible(false)
I don't agreed with your idea, another workaround
create only one JDialog (JDialog.DO_NOTHING_ON_CLOSE) with WindowListener, and re-use that for another Action, final action will be always setVisible(false), if your code ends with success, then remove the child(s) from JDialog, your JDialog is prepared for another job