0

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);

 }
});





}
Sujoy Ghosh
  • 13
  • 1
  • 3
  • *"Any suggestions?"* 1) Ask a *specific* question. 2) For better help sooner, post an [SSCCE](http://sscce.org/). 3) Don't put a 'game' in a `JOptionPane`. See [this answer](http://stackoverflow.com/a/9554657/418556) for tips on other strategies for putting the game **into** the frame. – Andrew Thompson Oct 14 '12 at 09:39

1 Answers1

4

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);
}
Community
  • 1
  • 1
code4j
  • 4,208
  • 5
  • 34
  • 51
  • @user1022209 ..that works,I can return to main menu,but all dialogs pop up at the same time,which don't allow the program to run as I want it to – Sujoy Ghosh Oct 14 '12 at 18:28
  • As the dialogs are non-modal, they will not block the thread for poping up the dialogs. You may let the pop up of the next dialog as an trigger event when the users pass the previous dialog. :) – code4j Oct 15 '12 at 01:30
  • @user1022209 ..how to go about doing that , maybe a hint :) – Sujoy Ghosh Oct 15 '12 at 07:44
  • @SujoyGhosh I have added a simple example :) – code4j Oct 15 '12 at 15:49
  • Thanks, I can use a JDialog instead of JOptionPane. But if I add a button to JOptionPane and set modal to false,then I see that button only when I take mouse pointer over it – Sujoy Ghosh Oct 16 '12 at 19:18
  • You should should `new JDialog` instead of `JOptionPane.createDialog()` which simply creates Dialog with the template of `JOptionPane` instance. For better customization, you can extends the `JDialog` and customize it just like `JFarme`, see the code I edited – code4j Oct 18 '12 at 13:04