How to use a swing Timer with JPanel

北慕城南 提交于 2019-12-12 05:42:22

问题


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.


回答1:


  • 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();
            }
        });
    }
}


来源:https://stackoverflow.com/questions/32753169/how-to-use-a-swing-timer-with-jpanel

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!