简体   繁体   中英

Java Swing Program- Input from GUI to Main getting stuck

I have a Java program where I plan to take input from GUI, and use that input later for processing in main() . I am using Eclipse .
I am sending an HW object(called HWObj ) to the GUI JFrame , and checking for a boolean field in the object to continue processing in main() .

InputWindow is custom object which extends JPanel implements ActionListener It contains a reference to the current JFrame (parentFrame). On clicking a JButton in InputWindow, I have written a custom ActionListener which sets the value of HWObj .check to true and disposes the parentFrame. This should cause execution to resume in main() .
Code for HW class is as below :

import java.awt.*;
import javax.swing.*;
public class HW {

    //globals
    boolean check;
    public HW() {
        //initialisations
        check = false;
    }

    public static void main(String args[]) { 
        final HW problem = new HW();
        try {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    //Create and set up the window.
                    JFrame frame = new JFrame("Select folders");
                    frame.setPreferredSize(new Dimension(640, 480));
                    frame.setResizable(false);
                    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                    InputWindow Directories = new InputWindow(problem, frame);
                    Directories.setOpaque(true);
                    frame.add(Directories);
                    //Display the window.
                    frame.pack();
                    frame.setVisible(true);
                }
            });
        } catch(Exception e) {
            System.out.println("Exception:"+e.getLocalizedMessage());
        }
        while(!problem.finish);
        //Do processing on problem
        System.out.println("Done");
    } 
}

The Actionlistener in the gui is as follows:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class InputWindow extends JPanel
                implements ActionListener {

    private static final long serialVersionUID = 4228345704162790878L;

    HW problem;
    JFrame parentFrame;
    //more globals

    public InputWindow(HW problem, JFrame parentFrame) {
        super();
        this.setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();

        this.parentFrame = parentFrame;
        this.problem = problem;

        JButton finishButton = new JButton("Finish");
        finishButton.setActionCommand("fin");
        finishButton.addActionListener(this);
        gbc.gridx = 0;
        gbc.gridy = 0;
        this.add(finishButton, gbc);

        //Initialize buttons and text areas and labels
        //Code removed for ease of reading

    }

    public void actionPerformed(ActionEvent e) {
        String command = e.getActionCommand();
        if(command.equals("fin")) {
            //Do a lot of stuff, then   
            this.removeAll();
            parentFrame.dispose();
            problem.check = true;
        }
    }
}

I have checked, and the control to this function comes normally on button click.

Now, I would expect it to return to main , and exit the while loop, and continue processing. This does not happen. The debugger in eclipse shows only the main thread running, and when I try to pause it, I see that the thread is stuck in the while loop. But if I try to step through, it exits the while loop as expected, and continues. However, it gets remains stuck in the while loop until I manually try to debug it.
What is the problem? Why is it not resuming the main thread as expected? How do I resolve this issue?

Your problem is to do with how the Java memory model works. The loop in your main thread will be checking a stale value of check .

When you enter the debugger, the memory is forced to be updated, so that's why it starts working at that point.

If you mark your variable as volatile , that will force the JVM to ensure that all threads are using the up-to-date value:

volatile boolean check;

You can read more about volatile and the Java memory model in the documentation .

It looks like you're using a JFrame where you should be using a modal JDialog. If you use the modal JDialog for an input window, you will know exactly when it is "finished" since code flow will resume from the calling code from right after when the dialog was set visible.

Either that or if you are trying to swapviews, then use a CardLayout to swap your view, and use an observer type pattern to listen for change of state.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM