Почему JFrame Paint() отображает одну и ту же точку несколько раз (или не отображает вообще)?

Контекст

Я пишу программу, которая аппроксимирует значение π, используя метод Монте-Карло.
Мой план состоит в том, чтобы визуально отобразить количество X точек и рассчитать результат на основе этого графика.

Дизайн пока такой:

  1. Спросите пользователя, сколько точек он хочет использовать в аппроксимации.
  2. Спросите пользователя, насколько быстро он хотел бы, чтобы симуляция выполнялась.
  3. Выполните моделирование на основе этих входных данных.

Быстрое предупреждение: я новичок в Java — пожалуйста, простите за ужасную настройку кода или глупые вопросы.

Проблема

При запуске программы в зависимости от скорости ввода произойдет одно из двух:

а.) Для медленных или средних скоростей две точки наносятся еще до запуска таймера и первая «реальная» точка наносится на карту.



б.) Для высоких или очень высоких скоростей первая точка наносится дважды.



По какой-то причине это может произойти и со вторым пунктом вместо первого.



Я в недоумении, почему это происходит. Вот некоторые вещи, которые я пробовал:

  • Настройка количества входных точек
  • Настройка логических условий, при которых отображаются точки
  • Заставить JFrame использовать «фиктивную» точку для первой точки, а затем использовать обычные точки.
  • Настройка логических условий для перерисовки

Мои занятия

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());
    }
}  

Пользовательский ввод.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);
    }
}

Ваша панель должна переопределять paintComponent, а не paint.

g00se 21.04.2024 17:14

И вам следует 1. вызвать метод рисования супервизора (который будет super.paintComponent(g);, если переопределить PaintComponent), 2., вероятно, лучше всего рисовать на BufferedImage, а затем отображать указанное изображение в графическом интерфейсе. Либо это, либо рисование путем перебора точек. 3. Я бы не смешивал консольный ввод-вывод с графическим вводом-выводом. Поскольку это программа с графическим интерфейсом, я бы получал все входные данные и показывал весь вывод через графический интерфейс.

Hovercraft Full Of Eels 21.04.2024 17:20

Метод PaintComponent() (не Paint()) должен только рисовать текущее состояние компонента, а не изменять его. Утверждения: circlePoints++ и outsidePoints++; не должны быть в методе рисования. Для анимации вам следует использовать таймер поворота. Когда таймер сработает, вы обновите состояние этих переменных. Поэтому я предполагаю, что каждый раз, когда срабатывает таймер, вы добавляете новую точку в ArrayList. Затем метод рисования нарисует все точки в ArrayList.

camickr 21.04.2024 18:13

Вам стоит прочитать руководство Выполнение индивидуальной живописи.

VGR 21.04.2024 18:36
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
4
67
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я думаю, вы, возможно, упускаете из виду, что делает Component#paint(),
Когда JFrame обновляет экран, он очищает весь экран, и после этого все закрашивается.
Это означает, что весь ваш контент должен быть добавлен сразу
Надеюсь, это объясняет, что я имею в виду

Это означает, что в коде вам понадобится переменная в SimDrawing с именем

/**Vector2 is a base java class, i think, if not find one online*/
List<Vector2> plottedPoints = new ArrayList<>();

Затем нарисуйте эти точки в функции рисования.

for (Vector2 point : plottedPoints) {
   g2d.setColor(getColorOfPoint(point));
   g2d.drawOval(point.x-5, point.y-5, 10, 10);
}

Где-то еще в классе:

public static Color getColorOfPoint(Vector2 point) {
   return SimDrawing.isInsideCircle(point) ? Color.Red : Color.Blue;
}

И дополнительно в методе SimDrawing#actionPerformed(ActionEvent)

points.add(new Vector2(x, y));
//Also add to the points in or outside
if (isInsideCircle(point))
   pointsInside++;
else
   pointsOutside++;

Где-то еще в том же классе:

public static Color isInsideCircle(Vector2 point) {
   ..The code you used earlier
}
Ответ принят как подходящий

У вас есть куча проблем с вашим кодом, большая часть которых описана в комментариях, но основные из них:

  • Вы смешиваете линейный консольный ввод-вывод (ввод и вывод) с управляемым событиями вводом-выводом Swing GUI. Это может привести к проблемам с многопоточностью и блокировке кода, поэтому лучше использовать либо одно, либо другое, здесь просто придерживайтесь Swing I/O, поскольку программа обязательно должна быть графической.
  • Вы переопределяете метод рисования JFrame. Этот метод рисует весь графический интерфейс, включая его границы и дочерние компоненты, и метод не имеет двойной буферизации, что почти всегда приводит к прерывистой анимации. Гораздо лучше переопределить метод рисования JPanel PaintComponent, который занимается только рисованием и по умолчанию использует двойную буферизацию, что приводит к более плавной анимации.
  • Вы полагаетесь на графику рисования, чтобы «запомнить» предыдущие состояния, графические остатки, которые не стабильны. Чтобы показать, что это так, после запуска программы сверните графический интерфейс, а затем восстановите его и посмотрите, сохраняются ли нарисованные точки. Чтобы это исправить, либо нарисуйте BufferedImage, а затем отобразите то же самое буферизованное изображение в методе рисования, либо используйте цикл for в методе рисования для рисования каждой точки.
  • Вы не вызываете метод суперрисования метода рисования, что приводит к отсутствию «служебного» рисования, которое может зависеть от оставшихся «грязных» пикселей в вашем графическом интерфейсе и может привести к сохранению графических артефактов, загрязняющих ваш графический интерфейс. Если вы переопределяете PaintComponent, что вам следует сделать, вам следует вызвать super.paintComponent в этом переопределении, чтобы позволить JPanel выполнить служебную очистку графики.

Лично я бы рассмотрел несколько изменений, в том числе:

  • Я бы создал отдельный класс модели (или классы) без графического пользовательского интерфейса, начиная с класса, который, возможно, называется «MonteCarloPoint», который содержит поле java.awt.Point и логическое поле, вызываемое внутри. Это будет представлять одну точку, и точка будет знать, находится ли она внутри или за пределами назначенной вами границы.
  • Я бы создал еще один класс модели без графического интерфейса, скажем, под названием MonteCarloModel, дал ему массив MonteCarloPoints и дал ему код для рандомизации и создания точек. Я бы дал этому классу Swing Timer и дал бы ему возможность уведомлять другие классы, если и когда он изменяется, чтобы они могли извлекать любые новые или изменяющиеся данные из модели, а затем реагировать на эти изменения (например, путем построения графика точки данных в представлении, графическом интерфейсе).
  • Я бы создал перечисление PlotSpeed, чтобы представить возможные скорости анимации: от медленной до очень быстрой. Я бы также придал очень быстрому значению более разумное значение, поскольку 1 мс не является реалистичным интервалом времени для таймера качания. Подумайте, возможно, от 10 до 14.
  • Я бы создал класс (или классы) графического интерфейса, который прослушивает изменения в классе модели, а затем отображает состояние модели.
  • Я бы получал числовой ввод от пользователя из JSpinner, который похож на текстовое поле, но принимает только числа.
  • Я бы отобразил выбор скорости в JComboBox.
  • Я бы показал точки, созданные в JList.
  • И я бы показывал прогресс в JProgressBar.
  • Точки будут отображаться в JPanel, скажем, с именем PointPanel, который будет отслеживать изменения в объекте MonteCarloModel, а затем будет отображать новую точку при уведомлении о ее создании.
  • JList и JProgressBar также будут отслеживать изменения модели, а затем соответствующим образом менять свое отображение.

Например:

import javax.swing.*;

public class MonteCarloMain {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("Random Points");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(new MonteCarloView());
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        });
    }

}
import java.awt.Point;

public record MonteCarloPoint(Point point, boolean inside) {
}
public enum PlotSpeed {
    // let's use a log scale for speeds
    SLOW(300), MEDIUM(102), FAST(35), VERY_FAST(12);

    private final int speed;

    PlotSpeed(int speed) {
        this.speed = speed;
    }

    public int getSpeed() {
        return speed;
    }
}
import java.awt.Point;
import java.beans.PropertyChangeListener;
import javax.swing.Timer;

import javax.swing.event.SwingPropertyChangeSupport;

public class MonteCarloModel {
    public static final String POINT = "point";
    public static final String FINISHED = "finished";
    private SwingPropertyChangeSupport pcSupport = new SwingPropertyChangeSupport(this);
    private int pointsInsideCircle = 0;
    private int pointsOutsideCircle = 0;
    private int totalPoints = 0;
    private Timer timer;
    private int pointsToPlot;
    private PlotSpeed plotSpeed;
    private MonteCarloPoint[] points;
    private int size = 0;
    private int circleRadius = 0;
    
    public MonteCarloModel(int points, PlotSpeed medium, int size, int circleRadius) {
        pointsToPlot = points;
        plotSpeed = medium;
        this.size = size;
        this.circleRadius = circleRadius;
    }

    // add prop change listeners
    public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
        pcSupport.addPropertyChangeListener(propertyName, listener);
    }

    public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
        pcSupport.removePropertyChangeListener(propertyName, listener);
    }

    public void startPlotting() {
        points = new MonteCarloPoint[pointsToPlot];
        pointsInsideCircle = 0;
        pointsOutsideCircle = 0;
        totalPoints = 0;
        timer = new Timer(plotSpeed.getSpeed(), e -> {
            if (totalPoints < pointsToPlot) {
                int x = (int) (Math.random() * size);
                int y = (int) (Math.random() * size);
                Point newPoint = new Point(x, y);
                boolean inside = isInsideCircle(x, y);
                MonteCarloPoint newMyPoint = new MonteCarloPoint(newPoint, inside);
                points[totalPoints] = newMyPoint;
                if (inside) {
                    pointsInsideCircle++;
                } else {
                    pointsOutsideCircle++;
                }
                pcSupport.firePropertyChange(POINT, null, newMyPoint);
                totalPoints++;
            } else {
                timer.stop();
                pcSupport.firePropertyChange(FINISHED, false, true);
            }
        });
        timer.start();
    }

    public void stopPlotting() {
        if (timer != null) {
            timer.stop();
            pcSupport.firePropertyChange(FINISHED, false, true);
        }
    }

    private boolean isInsideCircle(int x, int y) {
        int dx = x - size / 2;
        int dy = y - size / 2;
        return dx * dx + dy * dy <= circleRadius * circleRadius;
    }

    public int getPointsInsideCircle() {
        return pointsInsideCircle;
    }

    public int getPointsOutsideCircle() {
        return pointsOutsideCircle;
    }

    public int getTotalPoints() {
        return totalPoints;
    }

    public int getPointsToPlot() {
        return pointsToPlot;
    }

    public MonteCarloPoint[] getPoints() {
        return points;
    }
}
import java.awt.BorderLayout;
import java.awt.event.KeyEvent;
import javax.swing.*;

public class MonteCarloView extends JPanel {
    public static final int MAX_POINTS = 100000;
    public static final int PADDING = 20;
    private static final int SIZE = 600;
    private static final int CIRCLE_RADIUS = 250;
    private PointPanel pointPanel = new PointPanel(CIRCLE_RADIUS, SIZE);
    private JSpinner pointSpinner = new JSpinner(new SpinnerNumberModel(200, 1, MAX_POINTS, 1));
    private JComboBox<PlotSpeed> speedCombo = new JComboBox<>(PlotSpeed.values());
    private JButton startButton = new JButton("Start");
    private JButton stopButton = new JButton("Stop");
    private DefaultListModel<String> listModel = new DefaultListModel<>();
    private JList<String> pointList = new JList<>(listModel);
    private JProgressBar progressBar = new JProgressBar();
    private MonteCarloModel pointModel = null;

    public MonteCarloView() {
        JPanel controlPanel = new JPanel();
        controlPanel.add(new JLabel("Number of points: "));
        controlPanel.add(pointSpinner);
        controlPanel.add(new JLabel("Speed: "));
        speedCombo.setSelectedItem(PlotSpeed.FAST);
        controlPanel.add(speedCombo);
        controlPanel.add(startButton);
        controlPanel.add(stopButton);
        startButton.setMnemonic(KeyEvent.VK_S);
        stopButton.setMnemonic(KeyEvent.VK_T);
        startButton.addActionListener(e -> startPlotting());
        stopButton.addActionListener(e -> stopPlotting());

        pointList.setVisibleRowCount(10);
        pointList.setPrototypeCellValue("Point 123456: Outside");
        pointList.setLayoutOrientation(JList.VERTICAL);
        JScrollPane pointListScrollPane = new JScrollPane(pointList);
        JPanel pointListWrapperPanel = new JPanel(new BorderLayout());
        pointListWrapperPanel.add(pointListScrollPane, BorderLayout.CENTER);
        pointListWrapperPanel.setBorder(BorderFactory.createTitledBorder("Points"));

        progressBar.setStringPainted(true);
        progressBar.setString(String.format("%d%%", 0));
        JPanel progressPanel = new JPanel(new BorderLayout());
        progressPanel.add(progressBar, BorderLayout.CENTER);
        progressPanel.setBorder(BorderFactory.createTitledBorder("Progress"));

        setBorder(BorderFactory.createEmptyBorder(PADDING, PADDING, PADDING, PADDING));

        setLayout(new BorderLayout(PADDING, PADDING));
        add(pointPanel, BorderLayout.CENTER);
        add(controlPanel, BorderLayout.PAGE_END);
        add(pointListWrapperPanel, BorderLayout.LINE_END);
        add(progressPanel, BorderLayout.PAGE_START);
    }

    private void startPlotting() {
        if (pointModel != null) {
            pointModel.stopPlotting();
        }
        pointModel = new MonteCarloModel((int) pointSpinner.getValue(), (PlotSpeed) speedCombo.getSelectedItem(), SIZE, CIRCLE_RADIUS);
        pointModel.addPropertyChangeListener(MonteCarloModel.POINT, evt -> {
            MonteCarloPoint newPoint = (MonteCarloPoint) evt.getNewValue();
            listModel.addElement(String.format("Point %d: %s", pointModel.getTotalPoints(), newPoint.inside() ? "Inside" : "Outside"));
            pointPanel.setModel(pointModel);
            int value = (pointModel.getTotalPoints() + 1) * 100 / pointModel.getPointsToPlot();
            value = Math.min(100, value);
            progressBar.setValue(value);
            progressBar.setString(String.format("%d%%", value));
        });
        pointModel.addPropertyChangeListener(MonteCarloModel.FINISHED, evt -> {
            startButton.setEnabled(true);
            pointSpinner.setEnabled(true);
            speedCombo.setEnabled(true);
        });
        startButton.setEnabled(false);
        pointSpinner.setEnabled(false);
        speedCombo.setEnabled(false);
        listModel.clear();
        progressBar.setValue(0);
        pointModel.startPlotting();
    }

    private void stopPlotting() {
        if (pointModel != null) {
            pointModel.stopPlotting();
        }
    }
}
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;

import javax.swing.*;


public class PointPanel extends JPanel {
    private static final int DIAMETER = 5;
    private MonteCarloModel pointModel;
    private int circleRadius = 0;
    private int size = 0;

    public PointPanel(int circleRadius, int size) {
        setBackground(Color.WHITE);
        setBorder(BorderFactory.createLineBorder(Color.BLACK));
        this.circleRadius = circleRadius;
        this.size = size;
    }

    @Override
    public Dimension getPreferredSize() {
        Dimension dim = super.getPreferredSize();
        if (isPreferredSizeSet()) {
            return dim;
        } else {
            int w = Math.max(size, dim.width);
            int h = Math.max(size, dim.height);
            return new Dimension(w, h);
        }
    }

    public void setModel(MonteCarloModel pointModel) {
        // remove old listeners
        if (this.pointModel != null) {
            this.pointModel.removePropertyChangeListener(MonteCarloModel.POINT, evt -> {
                repaint();
            });
        }
        this.pointModel = pointModel;
        pointModel.addPropertyChangeListener(MonteCarloModel.POINT, evt -> {
            repaint();
        });
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (pointModel == null) {
            return;
        }
        g.setColor(Color.BLACK);
        // rendering hints for better circle rendering
        ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g.drawOval(size / 2 - circleRadius, size / 2 - circleRadius, 2 * circleRadius, 2 * circleRadius);
        MonteCarloPoint[] points = pointModel.getPoints();

        for (int i = 0; i < pointModel.getTotalPoints(); i++) {
            g.setColor(points[i].inside() ? Color.BLUE : Color.RED);
            g.fillOval(points[i].point().x - DIAMETER / 2, points[i].point().y - DIAMETER / 2, DIAMETER, DIAMETER);
        }
    }

}

Спасибо, что нашли время подробно все это описать! Ваша версия визуально ошеломляет. Очень признателен за объяснение недостатков моего кода. Однако есть одна вещь. Когда я попытался воссоздать вашу версию локально, она пожаловалась на PointPanel в верхней части класса MonteCarloView. Intellij продолжает спрашивать, является ли это зависимостью Maven, которую нужно импортировать, что не может быть правдой... Я думаю, вы сказали, что это JPanel. Должно ли быть это вместо этого? частная точка JPanel pointPanel = новая JPanel (CIRCLE_RADIUS, SIZE)

trb7074 21.04.2024 22:30

@trb7074: извини. Забыл выложить, а сейчас добавил. Не публикуйте это как решение для домашнего задания, поскольку оно, скорее всего, будет помечено.

Hovercraft Full Of Eels 21.04.2024 22:35

Другие вопросы по теме