Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/350.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 内部喷漆摆动计时器不工作_Java_Swing_Timer_Paint - Fatal编程技术网

Java 内部喷漆摆动计时器不工作

Java 内部喷漆摆动计时器不工作,java,swing,timer,paint,Java,Swing,Timer,Paint,我以前从未使用过定时器,所以我的问题可能真的很愚蠢。我的程序画了一个红色的圆圈,在随机的几秒钟后,圆圈应该变成绿色。我刚刚制作了一个swing计时器,正如您在下面的代码中看到的那样。它进入actionPerformed()方法,但不改变颜色。你能帮我解决一下换颜色的问题吗 我的代码: package igrica; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Graphics; import java.

我以前从未使用过定时器,所以我的问题可能真的很愚蠢。我的程序画了一个红色的圆圈,在随机的几秒钟后,圆圈应该变成绿色。我刚刚制作了一个swing计时器,正如您在下面的代码中看到的那样。它进入
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();
    }
}
}

不要从paintComponent方法中启动计时器。此方法仅适用于绘画和绘画。相反,在构造函数和计时器的actionPerromed中启动计时器并调用
repaint()
,更改类字段的状态,并在paintComponent中使用该信息使用该字段绘制任何新信息

e、 g

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


如果需要更改颜色,请为JPanel提供一个颜色字段,例如调用
Color
,并在计时器内更改其值,然后调用
repaint()
。同样在paintComponent中,使用该字段的值绘制椭圆。同样在这种情况下,计时器应该重复,所以在这种情况下要去掉
Timer.setRepeats(false)

计时器异步工作,并且
paintComponent
在完成计时器的工作之前完成。

你的代码中有很多乱七八糟的东西。试试这个:

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);
        }
    }
}
其思想是计时器只更改要绘制的形状的属性,然后调用
repaint()
以反映更改。只要需要,就会调用
paintComponent
,即使是快速连续调用,也应该很快返回

具体说明:

  • paintComponent
    外部创建并启动计时器,因为它被多次调用,这将创建并启动许多计时器
  • 您可能应该将计时器设置为不重复
  • 调用
    super.paintComponent(g)作为内部的第一件事
    paintComponent
  • 您似乎有一个什么都不做的
    ActionListener
一般提示:

  • 如果适用,请使用
    @覆盖
    注释
  • 在框架上调用
    pack()
    ,而不是手动设置其大小,并
    @覆盖您在其上绘制的组件的
    getPreferredSize
    方法。根据绘制的内容返回有意义的大小
  • 使用
    添加(组件、位置)
    而不是相反的方法(不推荐使用)
  • 当局部变量可用时,不要使用字段(例如,
    Random r
  • 使用大写常量名称(
    Color.RED
    而不是
    Color.RED

英语提示:不要每个句子都以“So”开头,你不是在讲故事。我知道我不应该这样做,但我不知道句子的开头是哪个词。只要去掉“So”,句子就可以了。好的,谢谢你的建议。我会尝试遵循它。但是我的System.out.println会工作,并且每次计时器完成时都会打印出来。在这个示例中,你有一个JFrame和一个Jpanel,如果你添加了很多组件,这个实现会抛出异常,因为当你的计时器尝试更改g时,同时,另一个组件将使用相同的g实例重新绘制,但不知道这是如何回答问题的<代码>喷漆组件应该/可以在计时器启动或执行其操作之前完成。异步的问题无关紧要。但是如果你需要不断地将颜色从红色变为绿色,然后再从绿色变为红色,该怎么办,这也行吗?@DomagojSabolic:然后在计时器中更改颜色字段的状态,并在paintComponent方法中使用。我认为您在主类中有一个剩余的
操作执行
。谢谢您如此详细地描述它!
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);
        }
    }
}