You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java repaint()函数困惑:未调用却可动态绘图的原因咨询

Understanding Your Swing Program's Behavior

Hey there! Let's break down why your Java Swing program works without explicitly calling repaint(), and why your update() method didn't seem to do anything when you added repaint() to it.

Why Your Program Runs Without Calling repaint()

Swing automatically triggers repaints in specific scenarios:

  • When you first make your frame visible with frame.setVisible(true), Swing fires a repaint event to draw all components on the screen. That's why your paintComponent() method runs once, drawing those random rectangles and ovals with randomized colors.
  • Other triggers include window resizing (though you set frame.setResizable(false) so this doesn't apply here) or when the window is uncovered after being hidden by another app.

Right now, this is a one-time draw—your program isn't refreshing the screen after that initial render, so you're just seeing a static image.

Why Your update() Method Didn't Change Anything

The simple answer: you never actually called the update() method! Your go() method sets up the frame and panel, but it never starts that infinite loop with Thread.sleep(10) and frame.repaint(). So that code was never executed at all.

On top of that, using a raw while(true) loop with Thread.sleep() in Swing is bad practice. Swing runs on a single thread called the Event Dispatch Thread (EDT)—any long-running loops or sleeps on this thread will freeze your UI. Instead, we should use a SwingTimer to schedule repaints safely on the EDT.

Fixed Version of Your Code

Here's a revised version of your program that fixes these issues, with key changes noted:

package epilepsy;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.BorderLayout;
import java.util.Random; // Use Java's built-in Random instead of custom Math class
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer; // Import Swing Timer

public class Epilepsy {
    JFrame frame;
    DrawPanel drawPanel;
    Random random = new Random(); // Replace custom Math with standard Random
    int screenW = 800;
    int screenH = 700;
    int red, green, blue;
    int x, y, w, h;

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

    private void go() {
        frame = new JFrame();
        drawPanel = new DrawPanel();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(BorderLayout.CENTER, drawPanel);
        frame.setSize(screenW, screenH);
        frame.setLocationRelativeTo(null);
        frame.setResizable(false);
        frame.setVisible(true);

        // Start the Swing Timer to trigger repaints every 10ms
        Timer timer = new Timer(10, e -> frame.repaint());
        timer.start();
    }

    class DrawPanel extends JPanel {
        private static final long serialVersionUID = 1L;

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g); // Always call this first to clear old graphics
            // Set the panel's background instead of the frame's
            randomize();
            setBackground(new Color(red, green, blue));

            // Draw random shapes
            randomize();
            g.setColor(new Color(red, green, blue));
            g.fillRect(x, y, w, h);

            randomize();
            g.setColor(new Color(red, green, blue));
            g.fillRect(x, y, w, h);

            randomize();
            g.setColor(new Color(red, green, blue));
            g.fillRect(x, y, w, h);

            randomize();
            g.setColor(new Color(red, green, blue));
            g.fillOval(x, y, w, h);

            randomize();
            g.setColor(new Color(red, green, blue));
            g.fillOval(x, y, w, h);

            randomize();
            g.setColor(new Color(red, green, blue));
            g.fillOval(x, y, w, h);
        }
    }

    private void randomize() {
        red = random.nextInt(256); // nextInt(256) gives 0-255 inclusive
        green = random.nextInt(256);
        blue = random.nextInt(256);
        x = random.nextInt(screenW);
        y = random.nextInt(screenH);
        w = random.nextInt(screenW/2);
        h = random.nextInt(screenH/2);
    }
}

Key Changes Explained:

  • Replaced custom Math class with java.util.Random: Java's standard Random class is reliable and designed for this kind of random number generation.
  • Added super.paintComponent(g): This clears the panel's previous drawing before rendering new shapes, preventing visual clutter from overlapping graphics.
  • Set JPanel background instead of JFrame: Since the JPanel covers the entire frame content pane, setting its background is the correct way to change the window's background color.
  • Used Swing Timer instead of a raw loop: The Timer safely schedules repaints on the EDT, ensuring your UI stays responsive while updating the screen every 10ms.
  • Removed unused update() method: The Timer handles the repeated repaint calls now.

Now when you run the program, you'll see the background and shapes changing continuously as expected!

内容的提问来源于stack exchange,提问作者Popolok11

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:19:10