【问题标题】:Java - swing timer in WHILE, with enable / disable buttonJava - WHILE 中的摆动计时器,带有启用/禁用按钮
【发布时间】:2017-10-14 13:08:54
【问题描述】:

在这里搜索了三天,找到了一些答案,但不明白如何实施解决方案。所以,我将代码恢复到第一个版本并决定询问。

我的代码有两个问题,阅读有关线程和并发性的文章并没有解释如何多次使用摇摆定时器,如何在循环内启动和停止定时器,以及如何在定时器启动时禁用按钮并在停止时重新启用.

当你点击按钮时它会掷骰子,计时器必须按其顺序执行该次数并停止,但如果骰子数为 6,则它必须再次启动它,在

"do{ 定时器循环 }while(die==6);"

在我的代码中,按钮没有被禁用。如果滚动到 6,计时器会立即响起,而无需等待完成上一次移动,并且您可以在一切完成之前单击按钮,使 JLabel 移动更加混乱。

有人可以告诉我如何进行这项工作吗?我还有更多这些要写,需要查看示例并从中学习。

请。

提前感谢您的理解。

代码如下:

    import java.awt.EventQueue;
    import java.awt.Toolkit;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import static java.lang.Math.random;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JButton;
    import javax.swing.Timer;

    public class RunPhysics extends JFrame {
        private final int waits = 200;
        private JLabel blackBoard = new JLabel();
        private JLabel label = new JLabel("a=F/m -> O");
        private JButton roll = new JButton("Roll");
        private int labelX = 10;
        private int labelY = 60;
        private int die;
        private Timer timer;

        public static void main(String[] args) {
            EventQueue.invokeLater(new Runnable () {
                @Override
                public void run() {
                    new RunPhysics();
                }
            });
        }

        public RunPhysics() {
            setSize(1000, 200);
            setTitle("Running Physics");
            setLayout(null);
            setDefaultCloseOperation(DISPOSE_ON_CLOSE);
            setVisible(true);
            getContentPane().add(blackBoard);
            blackBoard.setBounds(10, 10, 980, 280);
            blackBoard.add(label);
            blackBoard.add(roll);
            label.setBounds(30, 50, 100, 20);
            roll.setBounds(10, 10, 60, 30);


            roll.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent roller) {
                    do {labelX = 10;
                        die = (int)(random()*6+1);
                        roll.setEnabled(false);
        System.out.println(die + " was rolled.");
                        timer = new Timer( waits, new ActionListener() {
                            @Override
                            public void actionPerformed(ActionEvent mover) {
                                Toolkit.getDefaultToolkit().beep();
                                label.setLocation(labelX, labelY);    
                                if (labelX >= 900) {((Timer)mover.getSource()).stop();}
                                else { labelX+=36; }
                            }
                        });
                        timer.start();
                    } while (die == 6); // “Dice” is the plural form of the singular noun “Die”.
                    roll.setEnabled(true);
        System.out.println("~~~~~~~~~~~~~~~~~~~~");
                }
            });
        }
    }

【问题讨论】:

  • and reading about threads and concurency does not explain how to multi-use swing timer, how to startd and stop timer INSIDE A LOOP - 这是因为 Timer REPLACES 循环。摆脱循环。计时器将在您指定的时间段内生成一个事件。
  • 是的,定时器是循环来逐步移动JLabel的。它是原始 FOR 循环的替代品。现在,如何将它放在另一个将替换 WHILE 的计时器中?
  • 你不需要while循环!当某些事件发生时,您停止计时器。也许用户点击一个按钮或输入一个特定的键。
  • 我正在尝试摆脱 DO。事件是如果单击按钮滚动 6,则计时器循环必须再次进行,如果不是 6,则计时器循环不会进行。查看代码。
  • 所以创建一个带有两个按钮的框架,开始和停止。开始按钮将启动计时器。当计时器触发时,您只需显示当前时间。然后停止按钮将停止计时器。一旦您了解了基于用户事件启动/停止计时器的基础知识,您就可以将这些知识应用到您的实际应用程序中。这个过程是您简化问题的方式。然后,如果您仍然无法让代码工作,您可以在论坛中发布简单的代码。

标签: java swing timer do-while


【解决方案1】:

按钮的 ActionListener 负责启动动画。因此,您所做的就是设置组件的属性,然后启动动画。所以它可能看起来像:

roll.addActionListener(new ActionListener()
{
    @Override
    public void actionPerformed(ActionEvent roller)
    {
        // disable the roll button
        // set the labelX to its start value
        // set the label location
        // start the timer
    }
});

Timer ActionListener 负责:

  1. 原动画
  2. 确定何时停止动画
  3. 根据掷骰子重新开始动画

所以代码应该在你的类的构造函数中定义(而不是在按钮的 ActionListener 中),并且可能看起来像:

timer = new Timer( waits, new ActionListener()
{
    @Override
    public void actionPerformed(ActionEvent mover)
    {
        // do the basic animation

        // 1. increment the labelX value
        // 2. set the location of the label

        // determine when to stop the animation 

        if (your stop condition is satisfied)
        {
            // stop the timeer
            // enable the roll button

            int die = (int)(random()*6+1);
            System.out.println(die + " was rolled.");

            //  auto restart the animation

            if (die > 4) // make it easier to test auto repeat
            {
                // Reset the component properties and restart the timer.
                // The code here is the same as the code for the roll button
                // that is why I suggested you create a method
            }
        }
    }
});

再次点这个答案理解分离

  1. 用户开始某种处理
  2. 让计时器负责其动画并知道何时停止/重新启动动画。

它可能不是您想要的,但应该为您提供更好的结构以实现您的确切要求的基础知识。

【讨论】:

  • 谢谢。我正在对此进行试验,并花时间更好地理解它。需要从根本上改变思维方式,20年的按部就班的结构化只是一个负担。计时器会自行循环我们告诉它的内容,在我们指示它时动态分支,并在我们放置下一个任务时循环它们。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多