简体   繁体   English

无法理解Java Swing计时器。 如何延迟1次?

[英]Can't understand Java Swing Timers. How do I make a 1 time delay?

I need a one-time pause in this program for what I'm trying to do. 我需要在程序中暂停一次,以尝试执行此操作。 I display some text in a Java Swing JFrame , repaint shows it, I wait 1.5 sec, then I change the text. 我在Java Swing JFrame显示一些文本,重涂显示它,我等待1.5秒,然后更改文本。

Basically, I started with this: 基本上,我从这里开始:

statusLabel.setText(s);    
appFrame.repaint();
Thread.sleep(1500);
statusLabel.setText(y);
appFrame.repaint();

But this wasn't working. 但这是行不通的。 Thread.sleep() would invoke before repaint had finished, meaning s would never be shown. Thread.sleep()将在重新绘制完成之前调用,这意味着s将永远不会显示。 I read a lot of places that you're not supposed to use Thread.sleep() in swing applications because it pauses all threads, even the threads trying to repaint, and that to pause something triggered by actionPerformed() you need to use a Java Swing Timer. 我读过很多地方,您不应该在摆动应用程序中使用Thread.sleep() ,因为它会暂停所有线程,甚至是试图重绘的线程,并且要暂停由actionPerformed()触发的操作,您需要使用Java Swing计时器。

Which is all well and fine, except I can't find a single place that offers a decent explanation on how they work. 一切都很好,除了我找不到一个可以对它们如何工作提供不错解释的地方。 Since, as far as I can tell, timers are specifically used for repeating events on a timer. 据我所知,由于计时器专门用于重复计时器上的事件。 I just want a 1.5 second delay between 2 repaints. 我只希望两次重涂之间有1.5秒的延迟。

I tried doing this... 我尝试这样做...

statusLabel.setText(s);    
appFrame.repaint();

Timer timer = new Timer(1500, new ActionListener()
{
    public void actionPerformed(ActionEvent ae)
    {

    }
});

timer.setInitialDelay(1500);
timer.setRepeats(false);
timer.start();

statusLabel.setText(y);
appFrame.repaint();

...adding a timer with a 1.5 sec initial delay, no repeating, and no body to its actionPerformed event, so that it literally does nothing but wait that 1.5 sec, but it didn't work. ...在其actionPerformed事件中添加了一个具有1.5秒初始延迟,没有重复且没有内容的计时器,因此它实际上什么也没做,只是等待那1.5秒,但没有用。

As coded in your example, it looks like the timer would "work", it just doesn't do anything because the actionPerformed method is empty. 如您示例中的代码所示,计时器似乎可以“工作”,因为actionPerformed方法为空,所以它什么也不做。 You might be thinking that timer.start() blocks and waits for the timer to trigger, but it fact it returns immediately. 您可能会认为timer.start()阻塞并等待计时器触发,但实际上它会立即返回。 The way timers work is that the timer's actionPerformed method will be invoked from the UI thread when it is supposed to be. 计时器的工作方式是,应该在UI线程中调用计时器的actionPerformed方法。 Placing code inside the actionPerformed method of a timer is a good way to update the UI state periodically. 将代码放在计时器的actionPerformed方法内是一种定期更新UI状态的好方法。

Have you tried placing statusLabel.setText(y); 您是否尝试过放置statusLabel.setText(y); inside the actionPerformed method of your ActionListener ? 在您的ActionListeneractionPerformed方法内部?

statusLabel.setText(s);    

Timer timer = new Timer(1500, new ActionListener()
{
    public void actionPerformed(ActionEvent ae)
    {
        statusLabel.setText(y);
    }
});

timer.setRepeats(false);
timer.start();

If that's still not working, then consider providing a runnable example which demonstrates your problem. 如果仍然无法解决问题,请考虑提供一个可运行的示例来演示您的问题。 This will result in less confusion and better responses 这将减少混乱并改善响应

Updated 更新

What you "seem" to be wanting to do, is set up a series of events which get trigger at different times...Rather then using separate Timer s, you should be using a single Timer like a loop, each time it ticks, you check it's state and make some decisions about what should be done, for example... 您“想”要做的是设置一系列事件,这些事件在不同的时间触发……而不是使用单独的Timer ,您应该像循环一样使用单个Timer ,每次滴答时,您检查它的状态并做出一些决定应该做什么的决定,例如...

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Flashy {

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

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

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

    public static class TestPane extends JPanel {

        private JLabel flash;
        private JButton makeFlash;

        protected static final Color[] FLASH_COLORS = new Color[]{Color.BLUE, Color.RED, Color.GREEN, Color.YELLOW};
        protected static final int[] FLASH_DELAY = new int[]{1000, 2000, 3000, 4000};
        private int flashPoint;

        public TestPane() {
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;

            flash = new JLabel("Flash");
            flash.setOpaque(true);
            makeFlash = new JButton("Make Flash");

            add(flash, gbc);
            add(makeFlash, gbc);

            makeFlash.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    flashPoint = -1;
                    Timer timer = new Timer(0, new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                            Timer timer = ((Timer)e.getSource());
                            flashPoint++;
                            if (flashPoint < FLASH_COLORS.length) {
                                flash.setBackground(FLASH_COLORS[flashPoint]);
                                System.out.println(FLASH_DELAY[flashPoint]);
                                timer.setDelay(FLASH_DELAY[flashPoint]);
                            } else {
                                flash.setBackground(null);
                                timer.stop();
                                makeFlash.setEnabled(true);
                            }
                        }
                    });
                    timer.setInitialDelay(0);
                    timer.start();                  
                    makeFlash.setEnabled(false);
                }
            });

        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

    }

}

Now, if you wanted to do something really fancy, you could devise a series of key frames over a given period of time. 现在,如果您想做一些真正想做的事情,则可以在给定的时间内设计一系列关键帧。

This means that you could change the duration of the animation, without needing to change any other piece of code, for example... 这意味着您可以更改动画的持续时间,而无需更改任何其他代码,例如...

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.NumberFormat;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Flashy {

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

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

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

    public static class TestPane extends JPanel {

        private JLabel flash;
        private JButton makeFlash;

        protected static final Color[] FLASH_COLORS = new Color[]{Color.BLUE, Color.RED, Color.GREEN, Color.YELLOW};
        protected static final double[] FLASH_DELAY = new double[]{0, 0.2, 0.4, 0.6};

        public TestPane() {
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;

            flash = new JLabel("Flash");
            flash.setOpaque(true);
            makeFlash = new JButton("Make Flash");

            add(flash, gbc);
            add(makeFlash, gbc);

            makeFlash.addActionListener(new ActionListener() {
                private int playTime = 10000;
                private long startTime;
                private int currentFrame = -1;

                @Override
                public void actionPerformed(ActionEvent e) {
                    startTime = System.currentTimeMillis();

                    Timer timer = new Timer(50, new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                            Timer timer = ((Timer) e.getSource());
                            long now = System.currentTimeMillis();
                            long duration = now - startTime;

                            double progress = (double) duration / (double) playTime;
                            int keyFrame = 0;
                            for (keyFrame = 0; keyFrame < FLASH_DELAY.length; keyFrame++) {

                                double current = FLASH_DELAY[keyFrame];
                                double next = 1d;
                                if (keyFrame + 1 < FLASH_DELAY.length) {
                                    next = FLASH_DELAY[keyFrame + 1];
                                }

                                if (progress >= current && progress < next) {
                                    break;
                                }

                            }

                            if (keyFrame < FLASH_COLORS.length) {

                                flash.setBackground(FLASH_COLORS[keyFrame]);

                            }

                            if (duration >= playTime) {
                                timer.stop();
                                makeFlash.setEnabled(true);
                                flash.setBackground(null);
                            }

                        }
                    });
                    timer.setInitialDelay(0);
                    timer.start();
                    makeFlash.setEnabled(false);
                }
            });

        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

    }

}

A much more advanced concept, which is demonstrated in this answer 一个更高级的概念,在此答案中得到了证明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM