-1

I am writing a turn-based game on the internet. I try to pop up a window that should be in front until the input stream is ready. I created smth like this, but it seems that it does not work.

class CustomBlockerDialog extends JDialog {
/**
 * 
 */
private static final long serialVersionUID = 1L;

public CustomBlockerDialog(Frame owner, String text) {
    super(owner, true);
    setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
    setSize(300, 100); // Adjust if needed
    setTitle("");
    add(new JLabel(text, SwingConstants.CENTER));
} 
}




final CustomBlockerDialog block = new CustomBlockerDialog(null, "Not your turn");

SwingUtilities.invokeLater(new Runnable() {//A

    @Override
    public void run() {
        System.out.println("show");
        block.setVisible(true);
    }
});


boolean one_write_only = true;
while(in.ready()){ /* C*/ 
    if(one_write_only){
        System.out.println("waiting server");
        one_write_only = false;
    }
};

System.out.println("suppose to hide");

SwingUtilities.invokeLater(new Runnable() {//B

    @Override
    public void run() {
    System.out.println("hide");
    block.setVisible(false);
    }
});

It looks like "A" and "B" are executed after "C" and I have no idea why.

mKorbel
  • 109,525
  • 20
  • 134
  • 319
slawic
  • 1
  • 1

2 Answers2

2

Your problem must be due to "C" being called on the Swing event thread and not in a background thread, since it sounds like "C" is blocking the event thread from running "A". Solution: be sure that "C" is not called on the Swing event thread. Also if this is the case, and this can be tested by running the SwingUtilities.isEventDispatchThread() method, then you don't need all those other runnables.

// note that this all must be called on the Swing event thread:
final CustomBlockerDialog block = new CustomBlockerDialog(null, "Not your turn");

System.out.println("show");
// block.setVisible(true);  // !! no this will freeze!

final SwingWorker<Void, Void> worker = new SwingWorker<>() {
   public void doInBackground() throws Exception {
      boolean one_write_only = true;
      while(in.ready()){ /* C*/ 
         if(one_write_only){
            System.out.println("waiting server");
            one_write_only = false;
         }
      }
   }
}

worker.addPropertyChangeListener(new PropertyChangeListener() {
   public void propertyChanged(PropertyChangeEvent pcEvt) {
      if (pcEvt.getNewValue() == SwingWorker.StateValue.DONE) {
         System.out.println("hide");
         block.setVisible(false);

         // call worker's get() method here and catch exceptions
      }
   }
});

worker.execute();

// moved to down here since the dialog is modal!!!
block.setVisible(true);

Caveat: code not compiled nor tested. There may be errors present as it was typed off the cuff.

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
0

Thanks to Hovercraft Full Of Eels, I created a little different solution which works in my case:

final SwingWorker<Object,Object> worker2 = new SwingWorker<Object, Object>() {
        public Object doInBackground() throws Exception {
          boolean one_write_only = true;
            while(!in.ready()){ /* C*/ 
              if(one_write_only){
                System.out.println("waiting server");
                one_write_only = false;
              }
            }
            return one_write_only;
        }

        protected void done() {
            try {
                block.setVisible(false);
            } catch (Exception ignore) {}
        }

};
worker2.execute();
block.setVisible(true);
slawic
  • 1
  • 1