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
相关产品推荐
相关产品推荐

