简体   繁体   中英

How to return from JOptionPane to main menu(JFrame)

I have made a small number guessing game in Java. My main JFrame(main menu) has three JButtons, Play, Sound and Exit.

Pressing the play button starts my game, a series of JOptionPanes come up asking the user to enter numbers. It works fine and the game runs properly. But when I press play button to play the game, I can't press exit or sound button or any other button in the game. I can't even press the X(Close) button of the main JFrame window, until I play the game fully, or close the JOptionPane thus closing the current game.

I can press exit button, when I have already pressed sound button to start the background sound. I can press play button, when I have already pressed sound button.

Any suggestions?

My question is, suppose I am making a small game using JOptionPanes how to press JButtons that are present on my main JFrame(main menu) when a JOptionPane is already open

Here is my SSCCE

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

class Test2 {
    static JFrame frame;
    static JPanel jp;

    static JButton b1;
    static JButton b2;
    static JButton b3;

    public static void main(String[] args)  {
        final long startTime = System.currentTimeMillis();
        frame=new JFrame("Game ");
        jp=new JPanel();
        b1=new JButton("Play");
        b1.addActionListener (new Action());
        b2=new JButton("Exit");
        b2.addActionListener (new Action1());
        b3=new JButton("Sound");
        b3.addActionListener (new Action2());

        jp.add(b1);
        jp.add(b2);
        jp.add(b3);

        frame.add(jp);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(300,400);
        frame.setVisible(true);
    }

    static class Action implements ActionListener { // For (game) Play button
        public void actionPerformed (ActionEvent e) {
            Thread  bb=new Thread(new Runnable(){
                public void run(){
                    new Test2().start();
                }});
            bb.setPriority(1);
            bb.start();
        }
    }

    static class Action1 implements ActionListener { // For Exit button
        public void actionPerformed (ActionEvent e) {

            Thread  tt=new Thread( new Runnable(){
                public void run(){
                    int response = JOptionPane.showConfirmDialog(
                            null,
                            "Exit application?",
                            "Confirm",
                            JOptionPane.YES_NO_OPTION,
                            JOptionPane.QUESTION_MESSAGE);
                    if (response == JOptionPane.NO_OPTION) {

                    }
                    else if (response == JOptionPane.YES_OPTION) {
                        System.exit(0);
                    }
                }
            });
            tt.setPriority(10);
            tt.start();
        }
    }

    static class Action2 implements ActionListener { //For Sound Button
        public void actionPerformed (ActionEvent e)  {

            try {
                /* Code to play sound */
            }
            catch(Exception ex) {
                ex.printStackTrace();
            }
        }
    }

    void start() { //   sample  game
        JOptionPane.showMessageDialog(null,"Step 1  ..click OK  to continue");
        JOptionPane.showMessageDialog(null,"Step 2  ..click OK  to continue");
        JOptionPane.showMessageDialog(null,"Step 3  ..click OK  to continue");
        JOptionPane.showMessageDialog(null,"Step 4  ..click OK  to continue");
        JOptionPane.showMessageDialog(null,"Step 5  ..click OK  to continue");
        JOptionPane.showMessageDialog(null,"Step 6  ..click OK  to continue");
        JOptionPane.showMessageDialog(null,"Step 7  ..click OK  to continue");
        JOptionPane.showMessageDialog(null,"Step 8  ..click OK  to continue");
    }
}

In my new code only the start() method has changed

void start()                          //   sample  game
{

JOptionPane pane = new JOptionPane();
 // Configure via set methods
dialog = pane.createDialog(null,"exp 1");
 // the line below is added to the example from the docs

dialog.setSize(300, 200);

 dialog.setModal(false); // this says not to block background components

JButton nextButton = new JButton("Go to Dialog2");


dialog.add(nextButton);
nextButton.setBounds(25,25,20,20);


 dialog.show();

JOptionPane pane2 = new JOptionPane();
 // Configure via set methods
 dialog2 = pane2.createDialog(null,"exp 2");
 // the line below is added to the example from the docs
 dialog2.setModal(false); // this says not to block background components
// dialog2.show();






nextButton.addActionListener(new ActionListener() {
 public void actionPerformed(ActionEvent arg0) {

dialog2.setVisible(true);
dialog.setVisible(false);

 }
});





}

Unfortunately,the JOptionPane is an modal object, you cannot leave them until you pass all the dialogs. From the doucmentation, All dialogs are modal. Each showXxxDialog method blocks the current thread until the user's interaction is complete.

You may fix your problems by creating an non-modal dialog. Example to create non-modal dialog

Instead, JDialog is similar to JFrame , you can add Button, event listener inside it. A Simple Example

You may create a customized JDialog Class for yourself :)

There is an example of customized JDialog

And I edited your code just like:

void start() { // sample game
    MyDialog dialog7 = new MyDialog(null);
    MyDialog dialog6 = new MyDialog(dialog7);
    MyDialog dialog5 = new MyDialog(dialog6);
    MyDialog dialog4 = new MyDialog(dialog5);
    MyDialog dialog3 = new MyDialog(dialog4);
    MyDialog dialog2 = new MyDialog(dialog3);
    MyDialog dialog1 = new MyDialog(dialog2);

    dialog1.setVisible(true);
}

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