Search code examples
javaswingtimerjmenubar

Variable Controlled Java Timer through JMenuBar


I'm relatively new to java coding and am in the process of trying to make my first game. The issue I am stuck on currently is trying to get the game to run at different speeds. I'm trying to accomplish this by having the user select the speed settings they want through the JMenuBar and then have that control the Timer speed, however, I'm not able to find a way to have the user control they delay variable.

I've tried several different methods on how to change the delay, but the delay only works when there is an actual int variable between the parentheses.

Below is where my code is at now trying to change the timer delay:

private int speed, delay;
private JRadioButtonMenuItem fast, normal, slow;
private boolean speedSlow = false;
private boolean speedNorm = false;
private boolean speedFast = false;

public game()
    {
        frame = new JFrame("Simon");
        renderer = new Renderer();

        JMenuBar menuBar = setMenuBar();
        frame.setSize(WIDTH + 8, HEIGHT + 30);
        frame.setVisible(true);
        frame.addMouseListener(this);
        frame.setResizable(false);
        frame.add(renderer);
        frame.setJMenuBar(menuBar);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        Timer timer = new Timer(setDelay(delay), this);

        start();

        timer.start();
    }
public JMenuBar setMenuBar()
{   
    JMenuBar menuBar = new JMenuBar();

    JMenu settings = new JMenu("Settings");     
    JMenu speedSet = new JMenu("Set Speed");
    slow = new JRadioButtonMenuItem("Slow");
    normal = new JRadioButtonMenuItem("Normal");
    fast = new JRadioButtonMenuItem("Fast");
    slow.addActionListener(new java.awt.event.ActionListener()
    {
        public void actionPerformed(java.awt.event.ActionEvent evt)
        {
            speedSlow = true;
        }
    });
    normal.addActionListener(new java.awt.event.ActionListener()
    {
        public void actionPerformed(java.awt.event.ActionEvent evt)
        {
            speedNorm = true;
        }
    });
    fast.addActionListener(new java.awt.event.ActionListener()
    {
        public void actionPerformed(java.awt.event.ActionEvent evt)
        {
            speedFast = true;
        }
    });

    speedSet.add(slow);
    speedSet.add(normal);
    speedSet.add(fast);
    settings.add(speedSet);

    menuBar.add(settings);

    return menuBar;
}
public int setDelay(int delay)
{   

    if (speedSlow)
    {
        delay = 30;
    }
    if (speedNorm)
    {
        delay = 20;
    }
    if (speedFast)
    {
        delay = 10;
    }

    return delay;

}
public void start()
{
    random = new Random();
    indexShown = 0;
    ticks = 0;
    score = 0;
    speed = delay;
}

Solution

  • Below is where my code is at now trying to change the timer delay:

    Well, if you want to change the "delay" of the Timer, then you need to invoke the setDelay(..) method of the TImer.

    private boolean speedSlow = false;
    private boolean speedNorm = false;
    private boolean speedFast = false;
    

    There is no need for those variables. Instead you just want to set the delay of the Timer when the menu item is clicked. So this means you need to make the Timer variable an instance variable so it can be referenced in your ActionListeners:

    private Timer timer;
    

    Now in your constructor you create the Timer with a default delay:

    timer = new Timer(30, this);
    

    Then in your ActionListeners you reset the delay. For example:

    slow.addActionListener(new java.awt.event.ActionListener()
    {
        public void actionPerformed(java.awt.event.ActionEvent evt)
        {
            //speedSlow = true;
            timer.setDelay( 30 );
        }
    });
    

    Your existing setDelay(...) method is not required. Also, a "setter" method should NOT return a value. The point of a "setter" method is to set a property of the class. You would then also create a "getter" method is you need to access that value. Although in this case neither method is need because you can set/get/ the delay directly from the Timer object.