Java frame.repaint()不工作

Java frame.repaint()不工作,java,swing,awt,actionlistener,Java,Swing,Awt,Actionlistener,这是我直接从“headfirstjava”获得的一个源代码,但无论我做什么,我似乎都无法使它工作,我不知道我可能缺少什么 import javax.swing.*; import java.awt.*; import java.awt.event.*; public class SimpleGui3C implements ActionListener { JFrame frame; public static void main(String[] args) {

这是我直接从“headfirstjava”获得的一个源代码,但无论我做什么,我似乎都无法使它工作,我不知道我可能缺少什么

import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

public class SimpleGui3C implements ActionListener {

    JFrame frame;

    public static void main(String[] args) {

        SimpleGui3C gui = new SimpleGui3C();
        gui.go();
    }

public void go() {

    MyDrawPanel drawPanel = new MyDrawPanel();

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

    JButton button = new JButton("Change colors");
    button.addActionListener(this);

    frame.getContentPane().add(BorderLayout.SOUTH, button);
    frame.getContentPane().add(BorderLayout.CENTER, drawPanel);
    frame.setSize(300, 300);
    frame.setVisible(true);
}

public void actionPerformed(ActionEvent event) {


    frame.repaint();
    }
}

class MyDrawPanel extends JPanel {

    public void paintComponent(Graphics g) {

        g.setColor(Color.white);
        g.fillRect(0, 0, 300, 300);

    int red = (int) (Math.random() * 255);
    int green = (int) (Math.random() * 255);
    int blue = (int) (Math.random() * 255);

    Color randomColor = new Color(red, green, blue);
    g.setColor(randomColor);
    g.fillOval(70, 70, 100, 100);

}
}
我试图找到另一种方法,不涉及重新绘制,而是在事件发生时创建MyDrawPanel的新实例,但它仍然不起作用,因为我没有找到正确清除面板的方法,到目前为止,我发现的唯一一种方法就是这样做,但这不是我想要实现的

import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

public class SimpleGui3C implements ActionListener {

    JFrame frame;

    public static void main(String[] args) {

    SimpleGui3C gui = new SimpleGui3C();
    gui.go();
}

public void go() {

    MyDrawPanel drawPanel = new MyDrawPanel();

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

    JButton button = new JButton("Change colors");
    button.addActionListener(this);

    frame.getContentPane().add(BorderLayout.SOUTH, button);
    frame.getContentPane().add(BorderLayout.CENTER, drawPanel);
    frame.setSize(300, 300);
    frame.setVisible(true);
}

    public void actionPerformed(ActionEvent event) {
        go();
    }
}



class MyDrawPanel extends JPanel {

    int red;
    int green;
    int blue;

    public MyDrawPanel() {

    this.red = (int) (Math.random() * 255);
    this.green = (int) (Math.random() * 255);
    this.blue = (int) (Math.random() * 255);
}

public void paintComponent(Graphics g) {

    g.setColor(Color.white);
    g.fillRect(0, 0, 300, 300);

    Color randomColor = new Color(this.red, this.green, this.blue);
    g.setColor(randomColor);
    g.fillOval(70, 70, 100, 100);

}
}

这会做你想做的

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

public class SimpleGui3C implements ActionListener {

    static JFrame frame = null;  // changed here...

    public static void main(String[] args) {
        frame = new JFrame();  // changed here....
        SimpleGui3C gui = new SimpleGui3C();
        gui.go();
    }

    public void go() {
        MyDrawPanel drawPanel = new MyDrawPanel();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JButton button = new JButton("Change colors");
        button.addActionListener(this);
        frame.getContentPane().add(BorderLayout.SOUTH, button);
        frame.getContentPane().add(BorderLayout.CENTER, drawPanel);
        frame.setSize(300, 300);
        frame.setVisible(true);
    }

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

class MyDrawPanel extends JPanel {

    public void paintComponent(Graphics g) {
        g.setColor(Color.white);
        g.fillRect(0, 0, 300, 300);
        int red = (int) (Math.random() * 255);
        int green = (int) (Math.random() * 255);
        int blue = (int) (Math.random() * 255);
        Color randomColor = new Color(red, green, blue);
        g.setColor(randomColor);
        g.fillOval(70, 70, 100, 100);
    }
}
在您的
go()
方法中。。。每次通过
JFrame=newjframe()创建新对象时因此,每次单击屏幕上都会出现一个新的帧

通过在
main()
方法中创建对象,我们每次只在同一
jframe
对象上调用
repaint()
方法,而不是创建新对象


希望它能帮上忙……

这会满足你的要求

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

public class SimpleGui3C implements ActionListener {

    static JFrame frame = null;  // changed here...

    public static void main(String[] args) {
        frame = new JFrame();  // changed here....
        SimpleGui3C gui = new SimpleGui3C();
        gui.go();
    }

    public void go() {
        MyDrawPanel drawPanel = new MyDrawPanel();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JButton button = new JButton("Change colors");
        button.addActionListener(this);
        frame.getContentPane().add(BorderLayout.SOUTH, button);
        frame.getContentPane().add(BorderLayout.CENTER, drawPanel);
        frame.setSize(300, 300);
        frame.setVisible(true);
    }

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

class MyDrawPanel extends JPanel {

    public void paintComponent(Graphics g) {
        g.setColor(Color.white);
        g.fillRect(0, 0, 300, 300);
        int red = (int) (Math.random() * 255);
        int green = (int) (Math.random() * 255);
        int blue = (int) (Math.random() * 255);
        Color randomColor = new Color(red, green, blue);
        g.setColor(randomColor);
        g.fillOval(70, 70, 100, 100);
    }
}
在您的
go()
方法中。。。每次通过
JFrame=newjframe()创建新对象时因此,每次单击屏幕上都会出现一个新的帧

通过在
main()
方法中创建对象,我们每次只在同一
jframe
对象上调用
repaint()
方法,而不是创建新对象


希望它能有所帮助……

在处理Swing时,应该记住一些事情。当我看到你使用的代码时,我想指出给你看,让你走在正确的轨道上

  • Swing
    基础应用程序从各自的 线程,称为
    EventDispatcherThread(EDT)
    ,而不是直接调用 从main。有关该主题的更多信息,请访问
  • 尽量不要在
    paintComponent(。。。
    )
    方法,改为在其他地方执行这些计算,然后 只需调用
    repaint()
  • paintComponent(…)
    的访问说明符受保护
  • 并且 not
    public
    ,因此在重写超类的方法时,请尝试not 要尽可能多地更改方法访问,直到 必要的
  • JPanel
    上绘图时,只需调用
    JPanel
    的实例,而不是顶级容器的
  • 扩展任何
    JComponenet/JPanel
    时,请始终尝试 覆盖所述的
    JComponent/JPanel
    getPreferredSize()
    ,如下所示 许多布局将返回
    0
    ,如果未指定任何布局,则不会返回任何布局 我们会画画的
  • 请记住调用
    super.paintComponent(g)
    ,作为第一行 内部
    油漆组件(…)
    。添加了一条注释以更清晰
  • 不要在
    JFrame
    上设置大小,而是尝试调用
    pack()
    ,如下所示 在所附的福利中说明。包装法 调整框架的大小,使其所有内容都位于其上 首选尺寸。包装的另一种选择是确定框架尺寸 通过调用setSize或setBounds(这也会设置 帧位置)。一般来说,使用pack比调用 设置大小,因为pack让框架布局管理器负责 框架大小和布局管理器善于根据平台进行调整 影响组件大小的依赖项和其他因素
  • 以下是修改后的代码(刚刚在
    DrawPanel
    中添加了一个方法,称为
    setValues()
    ,在这里进行计算并调用
    repaint()
    ),基于以上几点:

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    
    public class SimpleGui implements ActionListener {
    
        private MyDrawPanel drawPanel;
    
        public static void main(String[] args) {
            Runnable r = new Runnable () {
                @Override
                public void run () {
                    new SimpleGui ().go ();
                }
            };
            EventQueue.invokeLater ( r );
        }
    
        public void go() {
            drawPanel = new MyDrawPanel();
    
            JFrame frame = new JFrame();
            frame.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
            JButton button = new JButton( "Change colors" );
            button.addActionListener( this );
    
            frame.add( drawPanel, BorderLayout.CENTER );
            frame.add( button, BorderLayout.PAGE_END );
            frame.pack ();
            frame.setLocationByPlatform ( true );
            frame.setVisible(true);
        }
    
        public void actionPerformed(ActionEvent event) {
            drawPanel.setValues ();
        }
    }
    
    class MyDrawPanel extends JPanel {
    
        private int width = 300;
        private int height = 300;
    
        private int red;
        private int green;
        private int blue;
    
        private Color randomColor;
    
        /*
         * Make this one customary habbit,
         * of overriding this method, when
         * you extends a JPanel/JComponent,
         * to define it's Preferred Size.
         * Now in this case we want it to be 
         * as big as the Image itself.
         */
        @Override
        public Dimension getPreferredSize () {
            return new Dimension ( width, height );
        }
    
        public void setValues () {
            red = ( int ) ( Math.random() * 255 );
            green = ( int) ( Math.random() * 255 );
            blue = ( int ) ( Math.random() * 255 );
    
            randomColor = new Color( red, green, blue );
    
            repaint ();
        }
    
        /*
         * This is where the actual Painting
         * Code for the JPanel/JComponent goes.
         * Here the first line super.paintComponent(...),
         * means we want the JPanel to be drawn the usual 
         * Java way first (this usually depends on the opaque
         * property of the said JComponent, if it's true, then
         * it becomes the responsibility on the part of the
         * programmer to fill the content area with a fully
         * opaque color. If it is false, then the programmer
         * is free to leave it untouched. So in order to 
         * overcome the hassle assoicated with this contract,
         * super.paintComponent(g) is used, since it adheres
         * to the rules, and performs the same task, depending
         * upon whether the opaque property is true or false),
         * then later on we will add our image to it, by 
         * writing the other line, g.drawImage(...).
         */
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent ( g );
    
            g.setColor(randomColor);
            g.fillOval(70, 70, 100, 100);
        }
    }
    

    在处理
    Swing
    时,应该记住一些事情。当我看到你使用的代码时,我想指出给你看,让你走在正确的轨道上

  • Swing
    基础应用程序从各自的 线程,称为
    EventDispatcherThread(EDT)
    ,而不是直接调用 从main。有关该主题的更多信息,请访问
  • 尽量不要在
    paintComponent(。。。
    )
    方法,改为在其他地方执行这些计算,然后 只需调用
    repaint()
  • paintComponent(…)
    的访问说明符受保护
  • 并且 not
    public
    ,因此在重写超类的方法时,请尝试not 要尽可能多地更改方法访问,直到 必要的
  • JPanel
    上绘图时,只需调用
    JPanel
    的实例,而不是顶级容器的
  • 扩展任何
    JComponenet/JPanel
    时,请始终尝试 覆盖所述的
    JComponent/JPanel
    getPreferredSize()
    ,如下所示 许多布局将返回
    0
    ,如果未指定任何布局,则不会返回任何布局 我们会画画的
  • 请记住调用
    super.paintComponent(g)
    ,作为第一行 内部
    油漆组件(…)
    。添加了一条注释以更清晰
  • 不要在
    JFrame
    上设置大小,而是尝试调用
    pack()
    ,如下所示 在所附的福利中说明。包装法 调整框架的大小,使其所有内容都位于其上 首选尺寸。包装的另一种选择是确定框架尺寸 通过调用setSize或setBounds(这也会设置 帧位置)。一般来说,使用pack比调用 设置大小,因为pack让框架布局管理器负责 框架大小和布局管理器善于根据平台进行调整 影响组件大小的依赖项和其他因素
  • 以下是修改后的代码(刚刚在
    DrawPanel
    中添加了一个方法,称为
    setValues()
    ,在这里进行计算并调用
    repaint()
    ),基于以上几点:

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    
    public class SimpleGui implements ActionListener {
    
        private MyDrawPanel drawPanel;
    
        public static void main(String[] args) {
            Runnable r = new Runnable () {
                @Override
                public void run () {
                    new SimpleGui ().go ();
                }
            };
            EventQueue.invokeLater ( r );
        }
    
        public void go() {
            drawPanel = new MyDrawPanel();
    
            JFrame frame = new JFrame();
            frame.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
            JButton button = new JButton( "Change colors" );
            button.addActionListener( this );
    
            frame.add( drawPanel, BorderLayout.CENTER );
            frame.add( button, BorderLayout.PAGE_END );
            frame.pack ();
            frame.setLocationByPlatform ( true );
            frame.setVisible(true);
        }
    
        public void actionPerformed(ActionEvent event) {
            drawPanel.setValues ();
        }
    }
    
    class MyDrawPanel extends JPanel {
    
        private int width = 300;
        private int height = 300;
    
        private int red;
        private int green;
        private int blue;
    
        private Color randomColor;
    
        /*
         * Make this one customary habbit,
         * of overriding this method, when
         * you extends a JPanel/JComponent,
         * to define it's Preferred Size.
         * Now in this case we want it to be 
         * as big as the Image itself.
         */
        @Override
        public Dimension getPreferredSize () {
            return new Dimension ( width, height );
        }
    
        public void setValues () {
            red = ( int ) ( Math.random() * 255 );
            green = ( int) ( Math.random() * 255 );
            blue = ( int ) ( Math.random() * 255 );
    
            randomColor = new Color( red, green, blue );
    
            repaint ();
        }
    
        /*
         * This is where the actual Painting
         * Code for the JPanel/JComponent goes.
         * Here the first line super.paintComponent(...),
         * means we want the JPanel to be drawn the usual 
         * Java way first (this usually depends on the opaque
         * property of the said JComponent, if it's true, then
         * it becomes the responsibility on the part of the
         * programmer to fill the content area with a fully
         * opaque color. If it is false, then the programmer
         * is free to leave it untouched. So in order to 
         * overcome the hassle assoicated with this contract,
         * super.paintComponent(g) is used, since it adheres
         * to the rules, and performs the same task, depending
         * upon whether the opaque property is true or false),
         * then later on we will add our image to it, by 
         * writing the other line, g.drawImage(...).
         */
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent ( g );
    
            g.setColor(randomColor);
            g.fillOval(70, 70, 100, 100);
        }
    }
    

    它应该做什么?我该怎么办