Simple Swing Delay

2020-02-07 07:05发布

问题:

In a swing application, I have a popup jDialog which pops up with a jlabel that says "Hang on 5 seconds."

After 5 Seconds, the label should change to "Okay, now I'm done." And a button should appear allowing the user to click continue.

In the example action below (linked to a button which causes the popup), the popup appears as it should but it is blank instead of saying "Hang on 5 seconds." Then after 5 seconds everything updates and the labels are there and the button too. So what's going on? Is the thread sleeping before a repaint or something?

@Action
    public void popUp() {
        popUpDialog.setSize(300,200);
        popUpDialog.setLocationRelativeTo(null);
        popUpDialog.setVisible(true);

        popUpLabel.setVisible(true);
        popUpLabel.setText("Working, hang on a sec....");

        try {
            Thread.sleep(5000);
        } catch (InterruptedException ex) {
            Thread.currentThread().interrupt();
        }

        popUpLabel.setText("Okay Now I'm Done.");
        popUpBut.setVisible(true);
    }

EDIT: So I tried this, in an effort to use a swing timer in place of thread sleeping:

@Action
        public void popUp() {
            popUpDialog.setSize(300,200);
            popUpDialog.setLocationRelativeTo(null);
            popUpDialog.setVisible(true);

            popUpLabel.setVisible(true);
            popUpLabel.setText("Working, hang on a sec....");

            Timer timer = new Timer(speed, this);
            timer.setInitialDelay(pause);
            timer.start(); 

            popUpLabel.setText("Okay Now I'm Done.");
            popUpBut.setVisible(true);
        }

Obviously I'll need more code to finish the timer, but right off the bat I get a symbol not found, variable: timer error. What's that all about? Am I doing it wrong?

Edit 2: I changed the timer declaration and solved one problem but created another. Now I am getting the symbol not found error in regards to speed. I have never used a swing timer before and don't know how to use them. The java tutorial on the topic is convoluted and difficult to understand. Can any of you point me to a simple, clear example of a timer so I can learn from that and figure out what I need to do?

回答1:

If your code modifying your Swing component's state is on the EDT here (it should be), then no repainting of the label with the first text will take place even if you do call repaint(), because all other EDT requests queued before the last repaint need to complete before you reach that repaint, and your code here is one of those queued EDT events.

If you call repaint, it adds a repaint to the queue, it doesn't repaint right away. Your actions here will result in a 5 second wait, with the label before the next repaint having only the text you last set it to (as code queued on the EDT is executed fully before going to what next is queued).

Try using a Swing Timer, events fired from the Swing Timer are already executing on the EDT, so it's pretty much what you need, one event here where you set the text initially, and another event fired by the Swing Timer to change the text after 5 seconds.

Edit, example of Swing Timer firing once, after 5 seconds as requested by author:

    // set first jlabel text here

    ActionListener task = new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            System.out.println("This is on the EDT after 5 seconds, " +
                "well depending on if I'm used with a Timer, and if " +
                "the right options are set to that Timer");
            // set second jlabel text here
        }
        };
    Timer timer = new Timer(5000 , task);
    timer.setRepeats(false);
    timer.start();


回答2:

I have a popup jDialog which pops up with a jlabel that says "Hang on 5 seconds."

You have a dialog that is visible BEFORE:

  1. you set the text on the label
  2. the Thread.sleep()

The code following popupDialog.setVisible(true) is not executed until the dialog is closed. Reorder your code.

Also, you need to use a Swing Timer to schedule the changing of the text.



回答3:

       popUpLabel.setVisible(true);
       popUpLabel.setText("Working, hang on a sec....");

should be

       popUpLabel.setText("Working, hang on a sec....");
       popUpLabel.setVisible(true);

and AFTER this you should set the dialog to visible.

You could also keep the order of your code as you have it now - and force the label / panel to update. Though this seems like less of a logical choice in this scenario