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

JFrame的paint()方法重复绘制同一点或异常绘制问题求助

背景

我正在编写一个用蒙特卡洛法近似计算π值的程序,计划让程序可视化绘制指定数量的点,再根据这些点的分布计算π值。

当前设计流程:

  • 询问用户近似计算时使用的点数
  • 询问用户模拟运行的速度
  • 根据输入执行模拟

说明:我是Java新手,代码结构可能存在不足或问题比较基础。

问题

运行程序时,根据选择的速度会出现两种情况:

  • 选择慢速或中速时,计时器启动并绘制第一个“真正的”点之前,已经绘制了两个点
  • 选择快速或极快时,第一个点会被绘制两次,有时第二个点也会重复绘制

我尝试过以下方法,但没解决问题:

  • 调整输入的点数
  • 调整绘制点的布尔条件
  • 让JFrame先使用一个“虚拟”点,之后再用常规点
  • 调整repaint的布尔条件
我的类代码

Main.java

public class Main {

    public static void main(String[] args) {
        SimSetup simSetup = new SimSetup();
        simSetup.simSetup();
        SimFrame frame = new SimFrame();
        SimDrawing d = new SimDrawing();
        frame.add(d);
        frame.setVisible(true);
    }
}

SimSetup.java

public class SimSetup {

    private final UserInput userInput = new UserInput();


    public void simSetup() {
        title.displayTitle();
        boolean startupSuccess = false;
        while (!startupSuccess) {
            userInput.setPoints();
            userInput.setPlotSpeed();
            if ((userInput.setVerification(userInput.getPoints(), 
                    userInput.getPlotSpeed()))) {
                break;
            }
        }
        SimDrawing.setPoints(userInput.getPoints());
        SimDrawing.setSpeed(userInput.getPlotSpeed());
    }
}  

UserInput.java

import java.util.InputMismatchException;
import java.util.Objects;
import java.util.Scanner;

public class UserInput {

    private int numPoints;
    private short plotSpeed;
    private String verification;


    public int getPoints() {
        return numPoints;
    }

    public short getPlotSpeed() {
        return plotSpeed;
    }

    public String getVerification() {
        return verification;
    }


    public int setPoints() {
        System.out.print("Enter the number of points to be plotted using a positive integer between 1 and 100,000: ");


        try {
            Scanner scanner = new Scanner(System.in);
            numPoints = scanner.nextInt();

            if (numPoints < 0) {
                System.out.println("\nNumber of points must be a positive integer. Please try again.\n");
                setPoints();
            } else if (numPoints == 0) {
                System.out.println("\nCan't generate a plot using zero points! Please try again.\n");
                setPoints();
            } else if (numPoints > 100000) {
                System.out.println("\nNumber of points is too large. Please try again.\n");
                setPoints();
            }

        } catch (InputMismatchException e) {
            System.out.println("\nThe number of points must be an integer between 1 and 100,000. Please try again.\n");
            setPoints();
        }
        return numPoints;
    }

    public short setPlotSpeed() {
        System.out.print("\nSelect a plotting animation speed from the choices below:");
        System.out.println("\n0 -- Slow\n1 -- Medium\n2 -- Fast\n3 -- Very Fast\n");

        try {
            Scanner scanner = new Scanner(System.in);
            short speedChoice = scanner.nextShort();

            if (speedChoice == 0) {
                plotSpeed = 100;
            } else if (speedChoice == 1) {
                plotSpeed = 50;
            } else if (speedChoice == 2) {
                plotSpeed = 10;
            } else if (speedChoice == 3) {
                plotSpeed = 1;
            }

        } catch (InputMismatchException e) {
            System.out.println("Speed must be an integer between 0 to 3. Please try again.");
        }
        return plotSpeed;
    }

    public boolean setVerification(long numPoints, short plotSpeed) {

        if (numPoints > 50000 && (plotSpeed == 100 || plotSpeed == 50)) {
            System.out.println("This combination of points and animation speed will result in long completion time.");
            System.out.println("Are you sure? (Y to continue, N to re-enter choices.)");

            try {
                Scanner scanner = new Scanner(System.in);
                verification = scanner.nextLine();
                verification = verification.toLowerCase();

                if (Objects.equals(verification, "n")) {
                    System.out.println("\nProcess aborted.\n");
                    return false;
                } else if (!Objects.equals(verification, "n") && !Objects.equals(verification, "y")) {
                    System.out.println("\nVerification input not recognized. Please try again.");
                    setVerification(numPoints, plotSpeed);
                    return false;
                }

            } catch (Exception e) {
                System.out.println("Exception: " + e);
            }
        }
        return true;
    }
}  

SimDrawing.java

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

public class SimDrawing extends JPanel implements ActionListener {


    int count = 0;
    int max = 525;
    int min = 75;
    int circleRadius = 450;
    int x = min + (int) (Math.random() * (max - min + 1));
    int y = min + (int) (Math.random() * (max - min + 1));
    private static int points;
    private static short speed;
    private int circlePoints;
    private int outsidePoints;
    Timer t = new Timer(speed, this);


    public static void setPoints(int numPoints) {
        points = numPoints;
    }

    public static void setSpeed(short plotSpeed) {
        speed = plotSpeed;
    }

    public SimDrawing() {
        t.start();
    }

    @Override
    public void actionPerformed(ActionEvent e) {

        System.out.println("\nCount: " + count);

        x = min + (int) (Math.random() * (max - min + 1));
        y = min + (int) (Math.random() * (max - min + 1));

        System.out.println("\nPoint generated: " + "(" + x + "," + y + ")");
        repaint();

        if (count == points) {
            t.stop();
            pointCheck();
        }
        count++;
    }

    public void paint(Graphics g) {

        Graphics2D g2d = (Graphics2D) g;
        double distanceFromCenter = (Math.sqrt(Math.pow((x - 75), 2) + Math.pow((y - 525), 2)));

        g2d.setColor(Color.BLACK);
        g2d.setStroke(new BasicStroke(2));
        g2d.drawLine(74, 74, 526, 74);
        g2d.drawLine(74, 74, 74, 526);
        g2d.drawLine(74, 526, 526, 526);
        g2d.drawLine(526, 74, 526, 526);


        g2d.setStroke(new BasicStroke(3));
        if (distanceFromCenter <= circleRadius) {
            g2d.setColor(Color.BLACK);
            g2d.drawLine(x, y, x, y);
            System.out.println("Plotting inside point: " + "(" + x + "," + y + ")");
            circlePoints++;
        }
        if (distanceFromCenter > circleRadius) {
            g2d.setColor(Color.RED);
            g2d.drawLine(x, y, x, y);
            System.out.println("Plotting outside point: " + "(" + x + "," + y + ")");
            outsidePoints++;
        }
    }

    public void pointCheck() {
        System.out.println("\nThe number of points inside the circle is: " + circlePoints);
        System.out.println("The number of points outside the circle is: " + outsidePoints);

        int totalMappedPoints = circlePoints + outsidePoints;

        System.out.println("The total number of points is: " + totalMappedPoints);
    }
}  

SimFrame.java

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

public class SimFrame extends JFrame {
    public SimFrame() {

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setAlwaysOnTop(true);
        setTitle("Monte Carlo Method of Approximating π");
        setSize(616, 639);
        setResizable(false);
        setLayout(new GridLayout());
        setLocationRelativeTo(null);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 10:35:58