0

I'm fairly sure I understand how a swing timer works, I just cannot figure out how to apply it in my code. The way I apply it in my code doesn't allow it to draw because Graphics g is outside of its scope.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class JayFrame extends JFrame
{
  public JayFrame()
  {
    super("My Frame");
    setContentPane(new DrawPane());
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setSize(1200, 675);
    setResizable(false);
    setVisible(true);
  }

  class DrawPane extends JPanel
  {
    Timer timer = new Timer(1000, new MyTimer());

    public void paintComponent(Graphics g)
    {
      //Paint stuff
      super.paintComponent(g);

      timer.start();

      for(int i = 0; i < 1000; i += 110)
      {
        g.fillRect(i, 10, 100, 100);

        try{Thread.sleep(100);}
        catch(InterruptedException ie){}
      }

      timer.stop();
    }
  }

  class MyTimer implements ActionListener
  {
    public void actionPerformed(ActionEvent e)
    {
      //Loop stuff
      repaint();
    }
  }

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

EDIT: I have updated the code to show what I think should work, but does not. So I probably do have a flawed understanding of swing timers.

Liam Dooley
  • 1
  • 1
  • 2
  • What does the "Loop stuff" do? What does the "draw stuff" do? When do you start the `Timer`? This `Timer timer = new Timer(1000, new MyTimer());` looks strange, given the fact that you've started it from within your `MyTimer` class – MadProgrammer Sep 24 '15 at 04:10
  • Consider providing a [runnable example](https://stackoverflow.com/help/mcve) which demonstrates your problem. This is not a code dump, but an example of what you are doing which highlights the problem you are having. This will result in less confusion and better responses – MadProgrammer Sep 24 '15 at 04:10
  • `doesn't allow it to draw because Graphics g is outside of its scope.` in the ActionListener of your Timer you would invoke `repaint()` on the panel where you do your custom painting. In the constructor of your DrawPanel class you can create and start the Timer. There is no need for a separate MyTimer class. – camickr Sep 24 '15 at 04:16
  • I have updated the original post and added the suggestions from your comments. I do not completely understand the third however, if I do not need the MyTimer class, of which I am completely fine with removing, where would I declare the ActionListener? – Liam Dooley Sep 24 '15 at 04:31
  • Don't call `timer.start();` and/or `timer.stop()` in the `paintComponent` method, this makes no sense what so ever, painting may occur for any number of reasons, my of which you have no control over. – MadProgrammer Sep 24 '15 at 04:32
  • Where would I go about putting them then? – Liam Dooley Sep 24 '15 at 04:34
  • Think about this way. Each time `paintComponent` is called, you're going to iterate through you loop (roughly) 9 times, on each iteration, you're going to wait 1 second, so the loop is going to take 9 seconds to complete. In that time, nothing will be rendered to the screen, nor will your app respond to any events from the user. Instead, the `Timer` should be acting as the loop. Each time the timer is triggered, you update the state (add `110` to some variable) and call `repaint`, you allow the `Timer` to continue running until the variable is `>= 1000` at which time you stop the timer. – MadProgrammer Sep 24 '15 at 04:42

1 Answers1

3
  • Don't call timer.start(); and/or timer.stop() in the paintComponent method, this makes no sense what so ever, painting may occur for any number of reasons, my of which you have no control over.
  • Don't call Thread.sleep in your paintComponent, that's the point of have the Timer. You're just preventing Swing from updating the screen or process any new events

Timer acts as a psudo loop, on each iteration of the Timer, you update some state, check some exit condition and make your decisions about what should happen.

paintComponent simply paints the current state.

For example:

import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class JayFrame extends JFrame {

    public JayFrame() {
        super("My Frame");
        setContentPane(new DrawPane());
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(1200, 675);
        setResizable(false);
        setVisible(true);
    }

    class DrawPane extends JPanel {

        private int x = 0;

        public DrawPane() {
            Timer timer = new Timer(1000, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    x += 110;
                    if (x >= 1000) {
                        x = 1000;
                        ((Timer)e.getSource()).stop();
                    }
                    repaint();
                }
            });
            timer.start();
        }

        public void paintComponent(Graphics g) {
            //Paint stuff
            super.paintComponent(g);

            g.fillRect(x, 10, 100, 100);
        }
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                new JayFrame();
            }
        });
    }
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Thank you, so far, the best way I have found for myself to learn code is by example. I have been looking for an example for this for almost a year now. There are some parts I don't understand, but I'll read the docs and mess around with this until I do. – Liam Dooley Sep 24 '15 at 04:55
  • It can take a while for it to click (did for me), but the simplest way to think about it, is to see it as a kind of loop – MadProgrammer Sep 24 '15 at 04:57