Search code examples
javaswingdialogreturn

Struggle disposing of JDialog


I tried to create a little JDialog as a popup for requesting two values from the user: width and height. After a lot of tweaking, I thought I might retrieve those values upon the disposal of the dialog by using the windowClosed method of a window adapter to pass these values to a object together with the information, that the dialog had closed as a Boolean. The main method just intializes the dialog and waits for it to signal, that it has exit. I can verify, that the windowClosed method got executed, but it still doesn't seem to end my while loop waiting for the objects Boolean to change to false. Thank you for you help in advance.

The code was stripped of formatting stuff for the dialog as well as imports.

//dialogSubstitute.java 
 public class ResizeDialogSubstitute { 
     // I cant code plz help me, slopy solution for returning from a dialog ): 
     int Width, Height; 
     void SetWidth(int width){Width=width;} 
     void SetHeight(int height){Height=height;} 
     boolean stillrunning = true; 
     ResizeDialogSubstitute(){ 
         Width=0; 
         Height=0; 
     } 
 } 
  
 // test.java 
 public class test { 
     String NewWidth,NewHeight; //Terrible way of returning from a function 
     public static void main(String[] args) { 
         ResizeDialogSubstitute uwudaddy = new ResizeDialogSubstitute(); 
         ResizeDialog dialog = new ResizeDialog(100,100, uwudaddy); 
         dialog.setVisible(true); 
         while(uwudaddy.stillrunning); 
         System.out.println(uwudaddy.Height); 
         System.out.println(uwudaddy.Width); 
     } 
 } 
  
 // ResizeDialog.java 
 public class ResizeDialog extends JDialog 
 { 
  JTextArea x,y;   
   ResizeDialogSubstitute uwudaddy; 
     ResizeDialog(int widthNow, int heightNow, ResizeDialogSubstitute UwuDaddy) 
     { 
         uwudaddy=UwuDaddy; 
         this.setSize(300, 200); 
         this.setTitle("Resize"); 
         this.setDefaultCloseOperation(DISPOSE_ON_CLOSE); 
         JLabel label1= new JLabel("Define new Imagesize"); 
         this.add(label1,c); 
         JLabel label2= new JLabel("Width:"); 
         this.add(label2,c); 
         x = new JTextArea(Integer.toString(widthNow)); 
         this.add(x,c); 
         JLabel label3 = new JLabel("Height:"); 
         this.add(label3,c); 
         y = new JTextArea(Integer.toString(heightNow)); 
         this.add(y,c); 
         this.addWindowListener(new WindowAdapter()  
         { 
           public void windowClosed(WindowEvent e) 
           { 
             System.out.println("At least I gotr so far"); 
             //Tell Parent the result of the request, plz kill me 
             uwudaddy.SetHeight(Integer.parseInt(GetNewHeight())); 
             uwudaddy.SetWidth(Integer.parseInt(GetNewWidth())); 
             uwudaddy.stillrunning=false; 
           } 
  
           public void windowClosing(WindowEvent e) 
           { 
           } 
         }); 
  
     } 
     String GetNewWidth(){ 
         return x.getText(); 
     } 
     String GetNewHeight(){ 
         return y.getText(); 
     } 
 }

Solution

  • Your dialog handling has its flaws. But you can take a completely different approach:

    Subclass JPanel and add your labels, fields, buttons - whatever you need. You can use a UI builder if you like. Add getter/setter methods for the fields you are interested in.

    Instantiate this customized panel and use the setters to populate the fields. Then use JOptionPane.showOptionDialog to display the panel (pass it in as message). I prefer to have the OK_CANCEL_OPTION for usual dialogs.

    Once showOptionDialog returns, check the return code. If it is OK_OPTION, use the panel's getters to access the user input.

    Here is the above in code:

    import javax.swing.JLabel;
    import javax.swing.JOptionPane;
    import javax.swing.JPanel;
    import javax.swing.JTextField;
    
    public class MyPanel extends JPanel {
        
        private final JTextField txtUser;
    
        public MyPanel() {
            add(new JLabel("User"));
            txtUser = new JTextField();
            add(txtUser);
        }
        
        public String getUser() {
            return txtUser.getText();
        }
        
        public void setUser(String user) {
            txtUser.setText(user);
        }
        
        public static void main(String[] args) {
            MyPanel mp = new MyPanel();
            
            mp.setUser("DefaultUser");
            
            if (JOptionPane.showOptionDialog(
                    null, mp, "Input User", JOptionPane.OK_CANCEL_OPTION, 
                    JOptionPane.QUESTION_MESSAGE, null, null, null) == JOptionPane.OK_OPTION) {
                System.out.println("User entered: " + mp.getUser());
            }
        }
    }
    

    One of the advantages is that this pattern allows you to reuse the custom panel in create and in edit situations. It also works in other situations. Imagine the user exits the application but the data was not saved. Then you can do

    switch(JOptionPane.showConfirmDialog(null, "Do you want to save your data?") {
        case YES_OPTION:
            doSave();
            System.exit(0);
        case NO_OPTION:
            System.exit(0);
        case CANCEL_OPTION:
            // do nothing, assuming the main window will not exit
    }