JWindow Refuses To Show

  • (2 Pages)
  • +
  • 1
  • 2

15 Replies - 1239 Views - Last Post: 06 January 2013 - 09:59 PM Rate Topic: -----

#1 axnjxn  Icon User is offline

  • D.I.C Head

Reputation: 14
  • View blog
  • Posts: 144
  • Joined: 04-February 12

JWindow Refuses To Show

Posted 06 January 2013 - 10:24 AM

I'm really pulling my hair out on this one, guys.

I have finished developing my program. The one problem I am having is simply showing a "Connecting to Server" message while the program attempts to contact a listener on another computer. The computers connect fine when they are supposed to. However, I simply cannot get the JWindow to show "Connecting to Server". It won't show at all. I have tried everything I've found in google searches and nothing is working.

The part that is making me pull my hair out is the fact that the same code works perfectly when used in a self contained program but it simply refuses to work when called from within my program.

package clock;

import java.awt.*;

import javax.swing.*;

public class WaitScreen extends JWindow {
	
	private TimeClock timeClock;
	
	public WaitScreen(TimeClock tc) {
		super(tc);
		timeClock = tc;
		
		JPanel mainPanel = new JPanel();
		mainPanel.setLayout(new BorderLayout());
		
		JPanel messagePanel = new JPanel();
		messagePanel.setBackground(Color.white);
		messagePanel.setLayout(new FlowLayout(FlowLayout.CENTER));
		JLabel message = new JLabel("Connecting to server...");
		message.setFont(new Font("Arial", Font.BOLD, 14));
		message.setForeground(Color.black);
		messagePanel.add(message);
		
		mainPanel.add(new JLabel(""), BorderLayout.NORTH);
		mainPanel.add(messagePanel, BorderLayout.CENTER);
		mainPanel.add(new JLabel(""), BorderLayout.SOUTH);
		
		getContentPane().add(mainPanel);
		pack();
		setLocation((int)(Toolkit.getDefaultToolkit().getScreenSize().getWidth()/2 - this.getWidth()/2), 100);
		revalidate();
		getContentPane().setVisible(true);
		setVisible(true);
	}
	
}



If you try this code in its own self contained program, it will work fine. But it simply refuses to show when used in my program.

Even more baffling is the fact that if you cause an exception to be thrown by adding the following line to the end of the code, the JWindow will FINALLY show, but the exception causes the program to stop and the server is never contacted.
timeClock.getContentPane().add(this);


I tried adding the JWindow to timeClock (which extends JFrame) and, of course, you can't do that and an exception is thrown. But when this occurs, the JWindow WILL show. Remove that faulty code, and JWindow no longer shows.


Any ideas? This one is really baffling to me.

Is This A Good Question/Topic? 0
  • +

Replies To: JWindow Refuses To Show

#2 farrell2k  Icon User is online

  • D.I.C Lover
  • member icon

Reputation: 856
  • Posts: 2,620
  • Joined: 29-July 11

Re: JWindow Refuses To Show

Posted 06 January 2013 - 10:45 AM

Eh. Yeah, it worked fine for me. Something is wrong. How are you instantiating the JWindow within your application?

This post has been edited by farrell2k: 06 January 2013 - 10:46 AM

Was This Post Helpful? 0
  • +
  • -

#3 axnjxn  Icon User is offline

  • D.I.C Head

Reputation: 14
  • View blog
  • Posts: 144
  • Joined: 04-February 12

Re: JWindow Refuses To Show

Posted 06 January 2013 - 10:50 AM

This code is called before the connection is attempted:
WaitScreen waitScreen = new WaitScreen(timeClock);



I simply instantiate WaitScreen.

Why would the JWindow appear when an exception is thrown? I tried adding the WaitScreen to a JFrame's contentPane() and it threw an exception (of course), but the JWindow showed! Of course, the program couldn't progress because of the exception. Take out that faulty code and JWindow doesn't show.

This post has been edited by axnjxn: 06 January 2013 - 10:50 AM

Was This Post Helpful? 0
  • +
  • -

#4 g00se  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2812
  • View blog
  • Posts: 11,895
  • Joined: 20-September 08

Re: JWindow Refuses To Show

Posted 06 January 2013 - 10:54 AM

You need to place the networking code in a dedicated separate Thread or it will interfere with your gui. Look at the excellent api docs for SwingWorker
Was This Post Helpful? 0
  • +
  • -

#5 farrell2k  Icon User is online

  • D.I.C Lover
  • member icon

Reputation: 856
  • Posts: 2,620
  • Joined: 29-July 11

Re: JWindow Refuses To Show

Posted 06 January 2013 - 10:58 AM

Works fine for me.

public class WaitScreen extends JWindow {
	
	//private TimeClock timeClock;
	
	public WaitScreen(JFrame f) {
		JPanel mainPanel = new JPanel();
		mainPanel.setLayout(new BorderLayout());
		
		JPanel messagePanel = new JPanel();
		messagePanel.setBackground(Color.white);
		messagePanel.setLayout(new FlowLayout(FlowLayout.CENTER));
		JLabel message = new JLabel("Connecting to server...");
		message.setFont(new Font("Arial", Font.BOLD, 14));
		message.setForeground(Color.black);
		messagePanel.add(message);
		
		mainPanel.add(new JLabel(""), BorderLayout.NORTH);
		mainPanel.add(messagePanel, BorderLayout.CENTER);
		mainPanel.add(new JLabel(""), BorderLayout.SOUTH);
		
		getContentPane().add(mainPanel);
		pack();
		setLocation((int)(Toolkit.getDefaultToolkit().getScreenSize().getWidth()/2 - this.getWidth()/2), 100);
		//revalidate();
		getContentPane().setVisible(true);
		setVisible(true);
	}
	
   
}



import javax.swing.JFrame;
import javax.swing.SwingUtilities;

/**
 *
 * @author tj
 */
public class TimeClock extends JFrame {
    
    public TimeClock() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(300,300);
       
        setVisible(true);
        
        WaitScreen w = new WaitScreen(this);
       
    }
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
           public void run() {
               new TimeClock();
           } 
        });
    }
}


Was This Post Helpful? 0
  • +
  • -

#6 axnjxn  Icon User is offline

  • D.I.C Head

Reputation: 14
  • View blog
  • Posts: 144
  • Joined: 04-February 12

Re: JWindow Refuses To Show

Posted 06 January 2013 - 11:06 AM

I tried putting the networking code in another thread. The JWindow still doesn't show and my connection rejected code runs followed by my successful connection code. I think I have to rework how the rejection screen appears.

However, the JWindow still does not show and this still doesn't explain why it will show when an exception is thrown.
Was This Post Helpful? 0
  • +
  • -

#7 farrell2k  Icon User is online

  • D.I.C Lover
  • member icon

Reputation: 856
  • Posts: 2,620
  • Joined: 29-July 11

Re: JWindow Refuses To Show

Posted 06 January 2013 - 11:09 AM

You can post all your UI code, and I am sure one of us will figure it out. It seems like all you're doing is instantiating a JWindow with your TimeClock JFrame subclass as its owner. Not a big deal.

Something non-obvious is happening.

It's highly unlikely that it would cause problems, but are you instantiating your JFrame and JWindow on the EDT with SwingUtilities or EventQueue,invokeLater(), or are you just calling new WaitScreen() from your main thread?
Was This Post Helpful? 2
  • +
  • -

#8 g00se  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2812
  • View blog
  • Posts: 11,895
  • Joined: 20-September 08

Re: JWindow Refuses To Show

Posted 06 January 2013 - 11:13 AM

Quote

However, the JWindow still does not show and this still doesn't explain why it will show when an exception is thrown.
It shows because the code that was blocking the event dispatch thread is unblocked by the throwing of the exception, allowing the code to proceed and show the gui.
Was This Post Helpful? 2
  • +
  • -

#9 farrell2k  Icon User is online

  • D.I.C Lover
  • member icon

Reputation: 856
  • Posts: 2,620
  • Joined: 29-July 11

Re: JWindow Refuses To Show

Posted 06 January 2013 - 11:20 AM

So, what, were you trying to execute your network connection on the edt before setVisible() on your JWindow as G00se is saying?
Was This Post Helpful? 1
  • +
  • -

#10 g00se  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2812
  • View blog
  • Posts: 11,895
  • Joined: 20-September 08

Re: JWindow Refuses To Show

Posted 06 January 2013 - 11:35 AM

(That's what i'm guessing was happening)
Was This Post Helpful? 1
  • +
  • -

#11 axnjxn  Icon User is offline

  • D.I.C Head

Reputation: 14
  • View blog
  • Posts: 144
  • Joined: 04-February 12

Re: JWindow Refuses To Show

Posted 06 January 2013 - 06:14 PM

Sorry it took so long, I had a lot to do today! I didn't code the networking to occur first, but it was occurring first because I am very new to concurrency and didn't have my threads set up properly.

g00se was absolutely right:

Quote

It shows because the code that was blocking the event dispatch thread is unblocked by the throwing of the exception, allowing the code to proceed and show the gui.


This is, ultimately, how I understood what was happening. I was executing the GUI code in a new thread, but I wasn't executing the networking code inside its own thread.

Also, when farrell2k said

Quote

It's highly unlikely that it would cause problems, but are you instantiating your JFrame and JWindow on the EDT with SwingUtilities or EventQueue,invokeLater(), or are you just calling new WaitScreen() from your main thread?


I realized that I was calling new WaitScreen() AND the networking code right from the main thread.

Finally, I realized that to get this to work, I would execute the gui code within its own thread, follow that with another thread strictly for the networking and had the networking code use join() so it would wait until the gui code was finished before executing. This did the trick.

If I have left out any technical details or have a concept mixed up with regards to why it is now working, please feel free to fill it in, gentlemen. Thank you very much for all your help.
Was This Post Helpful? 1
  • +
  • -

#12 axnjxn  Icon User is offline

  • D.I.C Head

Reputation: 14
  • View blog
  • Posts: 144
  • Joined: 04-February 12

Re: JWindow Refuses To Show

Posted 06 January 2013 - 07:02 PM

Well, I THOUGHT everything was great, but now, when the network connection is successful, the GUI that is supposed to appear is not appearing.

I am so befuddled by concurrency in Java that my head is spinning in circles. Now that I've used multiple threads with join(), when a connection is successful, the GUI is no longer appearing. But when the connection fails, everything works properly (I get my fail message and the sign in screen loads).

I've read the Oracle trails on concurrency and still have no clue how to implement it in this type of situation. Am I supposed to run separate threads for GUI, networking, and event handling? In that case, I have a problem because elements in the GUI are populated by information received in the networking thread.

I'm so turned around by all this. I don't want to post all my code because it would be hundreds of lines from 3 or 4 different files. Without me posting a ton of code, is there any way one of you could clear up the basics of utilizing concurrency with GUI and network connection? Maybe a basic example?

This post has been edited by axnjxn: 06 January 2013 - 07:04 PM

Was This Post Helpful? 0
  • +
  • -

#13 farrell2k  Icon User is online

  • D.I.C Lover
  • member icon

Reputation: 856
  • Posts: 2,620
  • Joined: 29-July 11

Re: JWindow Refuses To Show

Posted 06 January 2013 - 08:51 PM

Well, Swing works on a Thread called the EDT, event dispatch thread. All GUI related code, updating the value of a text field, setting visible a JFrame, etc should be forced to happen there. This gives Swing the ability to work on its own and not interfere with anything else, so the GUI is always responsive. You can tell if something you do is executing on the edt by:

System.out.println(SwingUtilities.isEventDispatchThread());



You can do a simple if check before execution.

if(System.out.println(SwingUtilities.isEventDispatchThread()) {
    //execute GUI update
}
else {
    //post the update to the update to the edt
    SwingUtilities.involkeLater(new Runnable() {
        public void run() {
            //update the gui.
        }
    });



Under normal circumstances, all AWTEvents will execute on the edt - Mouse clicks through listeners, button presses.

As for your networking code, the best way to handle that is to obviously do it outside of the edt. g00se suggested a SwingWorker, and that is the cleanest way to do it. It's simplest use case is:

SwingWorker<String, Void> worker = new SwingWorker() {
   protected String doInBackground() {
        //this will execute in a seperate thread away from the edt.
        // Networking code here.
        return "operation completed".
   }

   //when doInBackground finiss, Swingworker will call this method on the edt, so you can update the gui.
    protected void done() {
        jLabel1.setText("Network connected");
    } 
};

worker.execute();



SwingWorker

This post has been edited by farrell2k: 06 January 2013 - 09:02 PM

Was This Post Helpful? 2
  • +
  • -

#14 axnjxn  Icon User is offline

  • D.I.C Head

Reputation: 14
  • View blog
  • Posts: 144
  • Joined: 04-February 12

Re: JWindow Refuses To Show

Posted 06 January 2013 - 09:13 PM

Thank you farrell2k. That was extremely informative. Can I give 2+?

I was ignorant of InvokeLater (and am surprised I have made it for so long with Threads without using it). I ended up structuring the code as such:

Thread t = new Thread(){  
	          public void run(){
	        	//
	            SwingUtilities.invokeLater(new Runnable(){//do networking here  
	                public void run(){  
	                	conn = new ClockConnection(thisScreen, timeClock, adminList);   
	              }  
	            });  
	            SwingUtilities.invokeLater(new Runnable(){//do swing work on EDT  
	              public void run(){  
	                waitScreen.dispose();
	                if(conn != null)
	                	completeUI();
	              }  
	            });  
	          }  
	        }; 
t.start();  
waitScreen.setVisible(true);


The SwingWorker looks great, but if I'm trying to show a "Currently Loading" type deal, would this still apply? Or is what I have done here a good solution?

This post has been edited by axnjxn: 06 January 2013 - 09:16 PM

Was This Post Helpful? 1
  • +
  • -

#15 farrell2k  Icon User is online

  • D.I.C Lover
  • member icon

Reputation: 856
  • Posts: 2,620
  • Joined: 29-July 11

Re: JWindow Refuses To Show

Posted 06 January 2013 - 09:27 PM

Well, remember that SwingUtilities invokeLater() will execute a runnable on the edt, so you do not want to do networking code there. Your example, Line 04. Also, nothing will execute in the space between lines 4 and 5. run() is called immediately. Line 19 also calls waitScreen.setVisible() OFF of the edt, so that is no good. Remember, you can always check with SwingUtilities.inEventDispatch(), or you can even do a Thread.currentThread.getName() in a println to see which thread you are in. I +1'd you for trying. :)/>

Your solution could work. I could do:

Thread th = new Thread() {
    public void run() {
        //do networking code.
        Connector.connect("blah blah bla");

        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                //update gui.
                jLabel1.setText("Connection made");
            }
        }
    }
};

th.start();



That is a little clunky as a solution with the nested run and runnable. Using SwingWorker is cleaner. Here is Oracles tutorial on it. It also includes an example as to how to report back progress as your code executes, in case you wanted to do something like a progress bar.

This post has been edited by farrell2k: 06 January 2013 - 09:28 PM

Was This Post Helpful? 2
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2