带定时器的Java变色图形

带定时器的Java变色图形,java,swing,graphics,timer,Java,Swing,Graphics,Timer,我想画一张每秒改变两次颜色的光盘。磁盘在DrawPanel上绘制,DrawPanel扩展了JPanel,在主方法中,DrawPanel被添加到一个框架中。 对于颜色更改,我使用了一个计时器,当我试图在main方法中更改DrawPanel的背景时,它会起作用(我注释掉了它) 有人能告诉我为什么它不适用于图形g对象或任何其他建议吗 我只是从main方法复制了代码并将其添加到paintComponent()方法中,但在这里它不起作用 import java.awt.*; import java.awt

我想画一张每秒改变两次颜色的光盘。磁盘在DrawPanel上绘制,DrawPanel扩展了JPanel,在主方法中,DrawPanel被添加到一个框架中。 对于颜色更改,我使用了一个计时器,当我试图在main方法中更改DrawPanel的背景时,它会起作用(我注释掉了它)

有人能告诉我为什么它不适用于图形g对象或任何其他建议吗

我只是从main方法复制了代码并将其添加到paintComponent()方法中,但在这里它不起作用

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

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

public class DrawPanel extends JPanel{

    public GridBagLayout gbl;

    //position and dimension
    int x = 0, y = 0, width = 200, height = 200;

    public DrawPanel(){
        repaint();
    }

    public DrawPanel(GridBagLayout gridBagLayout) {
        this.gbl = gridBagLayout;
    }

    public void paintComponent(Graphics g){
        //Overwriting of old picture
        super.paintComponent(g);

        ActionListener action = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                Random gen = new Random();

                Color color = new Color(gen.nextInt(256), gen.nextInt(256), gen.nextInt(256));

                //Draw color disk
                g.setColor(color);
                g.fillArc(x, y, width, height, 0, 360);
            }
        };

        Timer t = new Timer(500, action);
        t.setRepeats(true);
        t.setInitialDelay(0);
        t.start();



        //Draw boundary of circle
        g.setColor(Color.BLACK);
        g.drawArc(x, y, width, height, 0, 360);
    }


    public static void main(String[] args) {
        final JFrame frame = new JFrame();
        frame.setSize(300, 300);
        final DrawPanel panel = new DrawPanel();
            panel.setOpaque(true);
            frame.getContentPane().add(panel);

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);

//      ActionListener action = new ActionListener() {
//          @Override
//          public void actionPerformed(ActionEvent e) {
//              Random gen = new Random();
//                  Color color = new Color(gen.nextInt(256), gen.nextInt(256), gen.nextInt(256));
//                  panel.setBackground(color);         
//          }
//      };
//
//      Timer t = new Timer(500, action);
//      t.setRepeats(true);
//      t.setInitialDelay(0);
//      t.start();

    }

}

图形对象仅对该绘图有效

最好是告诉JPanel更改它的当前颜色(使用一个变量),然后告诉它重新绘制

  • 将变量
    discColor
    添加到JPanel

  • 将绘图代码更改为不使用计时器,使其更简单,只需根据
    discColor

  • 使用计时器更新
    discColor
    变量,然后调用面板的
    repaint()
    方法


  • Graphics
    对象是暂时的,因此即使编译器允许,也不应该缓存它。而是在类的构造函数中建立计时器,设置面板的BG,然后调用重新绘制。例如

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import java.util.Random;
    
    public class DrawPanel extends JPanel {
    
        Random gen = new Random();
        //position and dimension
        int x = 0, y = 0, width = 200, height = 200;
        Color drawColor = Color.BLACK;
    
        public DrawPanel() {
            repaint();
            ActionListener action = new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    Color color = new Color(gen.nextInt(256), gen.nextInt(256), gen.nextInt(256));
    
                    //Draw color disk
                    drawColor = color;
                    DrawPanel.this.repaint();
                }
            };
    
            Timer t = new Timer(500, action);
            t.setRepeats(true);
            t.setInitialDelay(0);
            t.start();
        }
    
        @Override
        public void paintComponent(Graphics g) {
            //Overwriting of old picture
            super.paintComponent(g);
    
            //Draw boundary of circle
            g.setColor(drawColor);
            g.drawArc(x, y, width, height, 0, 360);
        }
    
        public static void main(String[] args) {
            final JFrame frame = new JFrame();
            frame.setSize(300, 300);
            final DrawPanel panel = new DrawPanel();
            panel.setOpaque(true);
            frame.getContentPane().add(panel);
    
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setVisible(true);
        }
    }
    

    paint方法不在我们的直接控制范围内,当JVM感觉需要重新绘制UI时,可能会调用它,这可能是由于许多不同的条件造成的。这不是建立新计时器的时候!我认为你误解了其中的一部分,背景没有改变,光盘的颜色也没有改变。另外,我认为
    setBackground
    可能会自动重新绘制面板以进行更新,我在电脑前必须检查一下。为了让事情清楚,我只想更改光盘的颜色,而不想更改背景的颜色。背景颜色应保持其默认颜色。我只是在后台试用了一下,看看是否正确使用了计时器。@mabu,您应该为类创建一个属性,如
    setDiscColor(…)
    。然后,当计时器触发时,调用此方法将属性设置为随机颜色。然后setDiscColor(…)方法将调用repaint()。然后在绘制方法中,使用“光盘颜色”属性绘制光盘。绘制方法不应随机设置颜色,因为您无法控制何时调用绘制方法。@AndrewThompson,谢谢,将g.drawArc(x,y,width,height,0,360)更改为g.fillArc(..)会按我的要求运行它,至少在主方法的给定帧中是这样。不幸的是,在GUI中使用这个drawPanel只能在使用GridbagLayout时起到一半的作用。说到一半,我的意思是,只有一部分的光盘改变颜色,但两个“角落”没有。调整窗口大小会改变整个圆圈的颜色,但当下一次颜色改变时,我也会遇到同样的问题。有什么建议说明这两件事为什么不一致吗?“有什么建议…”我建议你(在新的消息线程上)问一个新问题。