Firing delay between JFrame components

2019-01-29 02:29发布

问题:

I want to show how merge sort perform visually using JFrame. What I want to do is to make visible subsequent JLabel with some time delay. I tried many way but all of them appears at same moment with no intermediate delay.

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
        // TODO add your handling code here:
       // jLabel1.setVisible(false);
        jLabel2.setVisible(false);
        jLabel3.setVisible(false);
        jLabel4.setVisible(false);
        jLabel5.setVisible(false);
        jLabel6.setVisible(false);
        jLabel7.setVisible(false);
        final Timer t=new Timer((4000), null);
         final int delay=2000;
        final ActionListener taskPerformer = new ActionListener() {
      public void actionPerformed(ActionEvent evt) {

          jLabel1.setVisible(true);
          t.getDelay();

          jLabel2.setVisible(true);
          t.setDelay(3000);

          jLabel3.setVisible(true);
          t.setDelay(2000);

          jLabel4.setVisible(true);
          t.setDelay(2000);

          jLabel5.setVisible(true);
          t.setDelay(2000);

          jLabel6.setVisible(true);
          t.setDelay(2000);
                }
  };

  new Timer(delay, taskPerformer).start();

But when I click button all the lables appear at same momenet though I have kept delay.

回答1:

There are a number of reasons why this won't work. Firstly, javax.swing.Timer doesn't work this way. It waits in the background until the given delay has past and then calls the registered ActionListeners actionPerformed method.

Secondly, if it did work this way, it would block the Event Dispatching Thread, preventing it from processing repaint requests.

I think you will find How to use Swing Timers of use.

public class BlinkOut {

    public static void main(String[] args) {
        new BlinkOut();
    }

    public BlinkOut() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }

        });
    }

    public class TestPane extends JPanel {

        private JLabel[] labels;
        private int[] delays;
        private Timer timer;
        private int index;

        public TestPane() {
            setLayout(new GridLayout(0, 1));
            labels = new JLabel[7];
            for (int index = 0; index < 7; index++) {
                labels[index] = new JLabel("Label " + (index + 1));
                add(labels[index]);
            }
            delays = new int[] {2000, 3000, 2000, 2000, 2000, 2000, 2000};
            JButton hide = new JButton("Hide");
            add(hide);
            hide.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    System.out.println("Click");
                    index = 0;
                    labels[index].setVisible(false);
                    timer.setDelay(delays[index]);
                    timer.start();
                }
            });
            timer = new Timer(delays[0], new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    System.out.println("Tick");
                    timer.stop();
                    index++;
                    if (index < 7) {
                        labels[index].setVisible(false);
                        timer.setDelay(delays[index]);
                        timer.start();
                    }
                }
            });
            timer.setRepeats(false);
            timer.setCoalesce(true);
        }
    }

}


回答2:

You need to update the icons in the timer's action listener, as shown here. You can implement the Icon interface to render icons having a size proportional to an element's comparative value, as shown here.

Addendum: Can you please be little bit specific?

You want to animate the intermediate steps of sorting a List<Number> of size N in some initially random order. Number subclasses implement Comparable<T>, so compareTo() is already done. A GridLayout(1, 0) of JLabel each having an Icon can be used to display the values. DecRenderer shows how to create icons with a proportional size; you'll want to vary the height over the interval [0, N). GrayIcons & Mad's example show how to animate the display of the icons in some order.