Swing Timer里面的绘画不起作用

Dom*_*lic 5 java swing timer paint

Timer之前从未使用过s,所以我的问题可能真的很愚蠢.我的程序绘制一个红色的圆圈,随机秒后圆圈应将其颜色更改为绿色.我刚刚制作了一个摆动计时器,你可以在下面的代码中看到.它进入actionPerformed()方法,但它不会改变颜色.你能帮我改变一下颜色吗?

我的代码:

package igrica;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;


public class ChangingCircle implements ActionListener{

JFrame frame;

Timer timer;
Random r;

public static void main(String[] args) {
    ChangingCircle gui = new ChangingCircle();
    gui.go();
}

public void go() {
    frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    MyPanel panel = new MyPanel();

    frame.getContentPane().add(BorderLayout.CENTER, panel);
    frame.setSize(300, 300);
    frame.setVisible(true);
}   

public void actionPerformed(ActionEvent event) {
    frame.repaint();
}

class MyPanel extends JPanel {
    public void paintComponent(Graphics g) {


        g.setColor(Color.red);
        g.fillOval(100, 100, 100, 100);

        Random r = new Random();

        Timer timer = new Timer(r.nextInt(5000) + 1000, new ActionListener() {
            public void actionPerformed(ActionEvent ev) {
                System.out.println("Timer out");
                g.setColor(Color.green);
                g.fillOval(100, 100, 100, 100);
            } 
        });
        timer.start();
    }
}
}
Run Code Online (Sandbox Code Playgroud)

use*_*551 8

你的代码中有很多混乱.试试这个:

public class ChangingCircle {

    Color color = Color.RED;
    MyPanel panel = new MyPanel();

    public static void main(String[] args) {

        SwingUtilities.invokeLater(() -> {
            ChangingCircle gui = new ChangingCircle();
            gui.go();
        });
    }

    public void go() {

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.getContentPane().add(panel, BorderLayout.CENTER);
        frame.pack();
        frame.setVisible(true);

        Random r = new Random();
        Timer timer = new Timer(r.nextInt(5000) + 1000, new ActionListener() {

            public void actionPerformed(ActionEvent ev) {

                System.out.println("Timer");
                color = Color.GREEN;
                panel.repaint();
            }
        });
        timer.setRepeats(false);
        timer.start();
    }

    class MyPanel extends JPanel {

        private int size = 100, loc = 100;

        @Override
        public void paintComponent(Graphics g) {

            super.paintComponent(g);
            g.setColor(color);
            g.fillOval(loc, loc, size, size);
        }

        @Override
        public Dimension getPreferredSize() {

            return new Dimension(size + loc, size + loc);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这个想法是计时器只改变要绘制的形状的属性,然后调用repaint()以反映更改.该paintComponent每当它是必要的,即使是在连续快速和应该很快返回被调用.

具体说明:

  • 从EDT开始挥杆.
  • 从外部创建并启动计时器,paintComponent因为它被多次调用,这将创建并启动许多计时器.
  • 您应该将计时器设置为不重复.
  • 打电话super.paintComponent(g);是里面的第一件事paintComponent.
  • 你好像ActionListener什么也没做.

一般提示:

  • @Override适用时使用注释.
  • 调用pack()框架而不是手动设置其大小和您绘制的组件@OverridegetPreferredSize方法.根据您绘制的内容返回有意义的大小.
  • 使用add(component, location)而不是相反(弃用).
  • 当局部变量可以使用时(Random r例如)不要使用字段.
  • 使用大写常量名称(Color.RED而不是Color.red).


Hov*_*els 6

不要在paintComponent方法中启动Timer.此方法仅适用于绘画和绘画.而是在构造函数中启动Timer并在Timer的actionPerromed中调用repaint(),更改类的字段状态,并在paintComponent中使用该信息使用该字段来绘制任何新信息.

例如

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class ChangingCircle {
    JFrame frame;

    public static void main(String[] args) {
        ChangingCircle gui = new ChangingCircle();
        gui.go();
    }

    public void go() {
        frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        MyPanel panel = new MyPanel();

        frame.getContentPane().add(BorderLayout.CENTER, panel);
        frame.setSize(300, 300);
        frame.setVisible(true);
    }   

    public void actionPerformed(ActionEvent event) {
        frame.repaint();
    }

    class MyPanel extends JPanel {
        private Random r = new Random();
        private boolean draw = false;

        public MyPanel() {
            Timer timer = new Timer(r.nextInt(5000) + 1000, new ActionListener() {
                public void actionPerformed(ActionEvent ev) {
                    draw = true;
                    repaint();
                } 
            });
            timer.setRepeats(false);
            timer.start();
        }
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (draw) {
                g.setColor(Color.red);
                g.fillOval(100, 100, 100, 100);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

另外,不要忘记在覆盖中调用super的paintComponent方法.

如果你需要改变颜色,给JPanel一个Color字段,比如调用color并从Timer中改变它的值,然后调用repaint().同样在paintComponent中,使用该字段的值来绘制椭圆.同样在这种情况下,Timer 应该重复,所以摆脱timer.setRepeats(false)那种情况.