-1

I'm writing a simple game application and i'm stuck on this problem.

  • pwait and pmain are 2 panels
  • frame is the main frame

"create" is a button, inside the pmain Panel, and this is the action performed when it gets clicked:

Here is the code:

// ACTION: Create new game
    create.addActionListener(new ActionListener() {

        public void actionPerformed(ActionEvent e) {
            if(UA.alreadyOpen()) {
                JOptionPane.showMessageDialog(null,"already open game!");
                return;
            }

            int n = 0;
            String nome = null;

            try {
                n = Integer.parseInt(JOptionPane.showInputDialog(null, "Give the max number of guessers"));
                nome = JOptionPane.showInputDialog(null, "give the name of the game");
                if ( n < 1 || nome == null) System.out.println("mainInterface: input problems"); // TODO ...

                frame.setContentPane(pwait);
                pwait.setVisible(true);
                pmain.setVisible(false);
                frame.pack();
            } catch (NumberFormatException e1) {
                // ???
                e1.printStackTrace();
            } catch (HeadlessException e1) {
                // ???
                e1.printStackTrace();
            } 
                // AND HERE IS THE PROBLEM:
                if(!UA.apriPartita(n, nome)) 
                    System.out.println("ERR creazione partita"); // TODO
                refreshPartite(); 
        }
    });

UA is the logic-class behind the this interface class. The called method "UA.apripartita(..)" works fine and it does a lot of things. The problem is: i want the interface to repaint and show the pwait panel when the "create" button is clicked, but it doesn't UNTIL the method UA.apripartita(..) is returned (and, i guess, the ActionPerformed function is also returned?).

Effectively, i also tried removing that UA.apripartita(..) method call and it just works fine. Why it doesn't work when the method is inside it?

Thanks in advance!

ps. already tried putting in some frame.repaint() or frame.invalidate() but they seem to do nothing..

pps. any other good advide about this code is welcome!

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
OxPenguin
  • 93
  • 8
  • 1
    `frame.setContentPane(pwait);` Use a [`CardLayout`](http://download.oracle.com/javase/8/docs/api/java/awt/CardLayout.html) instead as shown in [this answer](http://stackoverflow.com/a/5786005/418556). – Andrew Thompson Jul 05 '15 at 16:35
  • 1
    I second @AndrewThompson's recommendation that you use CardLayout. Also, if your problem doesn't get resolved quickly, consider creating and posting a [minimal example program or mcve](http://stackoverflow.com/help/mcve) so we can see exactly where the problem is. I can almost guarantee you that `repaint()` call is not the problem here. – Hovercraft Full Of Eels Jul 05 '15 at 16:42

2 Answers2

0

Yep, that's by design. You can clearly see it in the documentation of 'repaint'. Basically, it sticks an "event" into swing event queue - the same one that handles clicks etc - so Swing will sequentially handle "action performed", then "repaint", then more pieces of code (e.g. mouseClicked or whatever gets in the queue). This approach saves the headache of synchronization, especially given that swing components are not thread-safe.

You can lookup 'paintImmediately' but I really recommend sticking with 'repaint' when possible.

Pelit Mamani
  • 2,321
  • 2
  • 13
  • 11
  • What is by design? It is impossible for me to guess why his code is not working based on the code and information presented so far, and I certainly cannot blame the structure of the Swing event queue for his current malfunction. – Hovercraft Full Of Eels Jul 05 '15 at 16:55
  • Sorry if it wasn't clear - I was referring to his original question, quote: "but it doesn't UNTIL ... the ActionPerformed function is also returned". That's the exact design of 'repaint', as originally designed & documented by Sun. – Pelit Mamani Jul 05 '15 at 17:10
  • His problem is all about his typing up the event queue with long-running code. He needs to show us that code since the solution is of course to use a background thread, not to consider use of paintImmediately. – Hovercraft Full Of Eels Jul 05 '15 at 17:12
0

This is because the actionPerformed(...) method runs under the control of the UI main event thread. So, your UI can't be refreshed while UA.apripartita() is running. If this method is designed to run for a long time (say more than half a second, users don't like long delays between actions and their effects), you should think about using multithreading (if this method must interact with UI, think about SwingWorker).

Jean-Baptiste Yunès
  • 34,548
  • 4
  • 48
  • 69