JDialog

Hi,

I think my problem is caused by my lack of knowledge of extending JDialog, heres my situation:

I have a JDialog that is crated and setVisible(true) when you click a button. The dialog only has a JTextArea as its only component. I have created a public method called log(String text) which appends whatever text I enter to the text area within the dialog.

My problem is that when I use this method nothing happens, no text added to the area, no exceptions, I checked the strings and there fine. Is this due to the event dispatching thread or have I forgot something?

Thanks,

Ken

modal dialogs spawn their own event queue.

Oh really, well yes its modal so that mean it has its own event thread?
So technically I’ve got some multithreading going on here then. The main thread is using the public method log so does that mean I need to implement some form of protection and could this have something to do with my problem?

It’s actually slightly different: the two queues are on the same thread, like a stack of queues.

Using SwingUtilities.invokeLater(Runnable) should put your ‘event’ in the right queue.

Just make sure you don’t call code after dialog.setVisible(true) that the dialog depends on. setVisible is blocking (as that’s where the new event queue is spawned, on that very same thread… if the current thread actually is the event thread. if not, it will still block, but hand over the work to the event thread, still making a new event queue)

Thanks, I do find it hard to get my head around these threading concepts etc. but I roughly understand.

Well nothing it depends on happens after setVisible() eg create the text area, setup the gui etc. The only thing that happens is calls to the one method I have mentioned before.

From what you are saying does it mean that I should use the log method and append text to text area after I create the dialog but before I setVisible?

Share some code.

No problem!

Ill not give you the full classes, just the relavent bits.

The dialog:

public class CalcsDialog extends javax.swing.JDialog {

    /** Creates new form CalcsDialog */
    public CalcsDialog(java.awt.Frame parent, boolean modal) {
        super(parent, modal);
        initComponents();
    }

    public void log(String text){
        calcsArea.append(text);
    }
}

The class accessing the dialog (my main frame on the main thread):
When the button is pressed.

if(currentBeam != null && bendingDiagram != null){
            CalcsDialog calcs = new CalcsDialog(this, true);
            calcs.setVisible(true);
            calcs.log(currentBeam.getCalcs());
            calcs.log(bendingDiagram.getCalcs());
}

Hopefully that gives you a clue how it works, it must be something fundimentally wrong as theres not much to it…

Stupid question (as I cant test it right now) but what would happen if I did the following then?

if(currentBeam != null && bendingDiagram != null){
            CalcsDialog calcs = new CalcsDialog(this, true);
            calcs.log(currentBeam.getCalcs());
            calcs.log(bendingDiagram.getCalcs());
            calcs.setVisible(true);
}

This is little incorrect. It actually creates a new thread for new queue but the old thread is paused in the meanwhile. So it behaves like there would be just one and there is no synchronization problems.

I vagely recall stacktraces with 2 (or 3) event ‘pumps’

What you say jezek2 makes perfect sense to me, it creates a new thread and pauses the main thread hence why my methods do nothing and why you cant do anything with any other GUI outside the dialog.

I changed my code to what I suggest and it worked anyway so Im happy :slight_smile:

Learn something new everyday…

I don’t really care what makes sense to you. What I say is a fact.

Run the code below, and you’ll see how there is only 1 thread involved in handling GUI.


 final JFrame[] frame = new JFrame[1];
         final JButton button1 = new JButton("click to open a dialog");
         final JButton button2 = new JButton("click to terminate");
         
         button1.addActionListener(new ActionListener()
         {
            @Override
            public void actionPerformed(ActionEvent e)
            {
               System.out.println("frame.thread.hashcode=" + System.identityHashCode(Thread.currentThread()));

               //Thread.dumpStack();

               JDialog dialog = new JDialog(frame[0], true);
               dialog.getContentPane().add(button2);
               dialog.pack();
               dialog.setLocationRelativeTo(null);
               dialog.setVisible(true);
            }
         });
         button2.addActionListener(new ActionListener()
         {
            @Override
            public void actionPerformed(ActionEvent e)
            {
               System.out.println("dialog.thread.hashcode=" + System.identityHashCode(Thread.currentThread()));

              // Thread.dumpStack();

               System.exit(0);
            }
         });
         frame[0] = new JFrame();
         frame[0].setTitle("test");
         frame[0].getContentPane().setLayout(new BorderLayout());
         frame[0].getContentPane().add(button1, BorderLayout.CENTER);
         frame[0].setResizable(false);
         frame[0].pack();
         frame[0].setLocationRelativeTo(null);
         frame[0].setVisible(true);
         frame[0].setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Output:


frame.thread.hashcode=17984263
dialog.thread.hashcode=17984263

You can uncomment the ‘Thread.dumpStack()’ lines to see the stacked event queues.

Thread stack dump after clicking 2nd button

java.lang.Exception: Stack trace at java.lang.Thread.dumpStack(Unknown Source) at automailer.AutoMailerMain$2.actionPerformed(AutoMailerMain.java:67) // my code ... at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) // event pump of dialog ... at java.security.AccessController.doPrivileged(Native Method) // creates new event pump ... at java.awt.Dialog.setVisible(Unknown Source) // call to setVisible at automailer.AutoMailerMain$1.actionPerformed(AutoMailerMain.java:57) // my code ... at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) // event pump of frame ... at java.awt.EventDispatchThread.run(Unknown Source) // creates the EDT

The only time the EDT thread changes is when an uncaught Exception occurs on the EDT.

Calm down :-
I didnt say what he said was correct, I dont know or I wouldnt be here!
All I said was what he says makes sense…

I will take alook at your code but I dont think it will mean much to me, I dont even understand what you mean by event pump.
EDIT: Ah yes I roughly see what you’ve done, ok I believe you its the same thread.

Sorry my mistake, I always thought it’s the case, thanks for the example code. It’s funny how you always learn something new about stuff you think you know well :slight_smile:

an ‘event pump’ is the code that pops events off the ‘event queue’, so every queue has a pump. every modal dialog has it’s own stacked queue+pump on top of the current queue+pump. all this is running on the ‘event thread’.

Ah I see I think I get the rough theory behind it. Its hard for a new programmer to learn these things when they happen behind the scenes, its not something you implement yourself.

So you have a list of events to occur and the pump goes down the stack one by one performing them…

to be precise: it goes down a queue (first-in-first-out), not a stack (first-in-last-out)