Метод repaint() не работает должным образом

У меня есть две кнопки: кнопка сброса и кнопка вычисления.
Кнопка сброса предназначена только для перерисовки JPanel под названием p1.
Цель кнопки расчета, чтобы сделать расчет и обновить JLabel.

Проблема в том, что при нажатии кнопки сброса, за которой следует кнопка расчета, JPanel перерисовывается, а этого быть не должно (см. код ниже, где метод перерисовки отсутствует в ActionListener() для calculateButton) .

Мне интересно, почему это происходит, и что я могу сделать, чтобы остановить перерисовку JPanel при нажатии этой кнопки (кнопка сброса работает точно так, как ожидалось, перекрашивая панель).

public class DrawCircles extends JFrame {


    //the following are x and y locations of the centers of the circles
    int center1X;
    int center1Y;
    int center2X;
    int center2Y;
    int center3X;
    int center3Y;

    public DrawCircles(){


        final CircleDraw c = new CircleDraw();   //create a circledraw object to get the area of the triangle between them

        final JPanel p1 = new JPanel();          //first panel to hold all other panels making the layout
        JPanel buttonPanel = new JPanel();

        p1.setLayout(new BorderLayout());  //set the layout of the panel to a border layout

        JButton areaTriangle = new JButton("Calculate area of triangle");
        JButton perimeterTriangle = new JButton("Calculate perimeter of triangle");
        JButton reset = new JButton("Reset");

        buttonPanel.setLayout(new BoxLayout(buttonPanel,0));
        buttonPanel.add(areaTriangle);
        buttonPanel.add(Box.createRigidArea(new Dimension(15,0)));
        buttonPanel.add(perimeterTriangle);
        buttonPanel.add(Box.createRigidArea(new Dimension(15,0)));
        buttonPanel.add(reset);      //add a button that says reset

        reset.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
               p1.repaint();  //redraw the circles and triangle
               areaLabel.setText(""); //clear the label

            }
        });


        calculateButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {

               areaLabel.setText("Area is "+ String.valueOf(2.0*c.getArea()));

            }
        });

        resetButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                areaLabel.setText("");  
            }
        });

        add(p1);                                      


    }


    public class CircleDraw extends JPanel {

    int radius;   
    double s;     
    double area;  

    public CircleDraw(){

    }

    @Override
    protected void paintComponent(Graphics g){
        super.paintComponent(g);


        Random rand = new Random(System.currentTimeMillis());
        center1X=rand.nextInt(507);
        center1Y=rand.nextInt(320);
        center2X=rand.nextInt(507);
        center2Y=rand.nextInt(320);
        center3X=rand.nextInt(507);
        center3Y=rand.nextInt(320);

        //draw the 3 circles
        g.drawOval(center1X, center1Y, 100,100);
        g.drawOval(center2X, center2Y,100,100);
        g.drawOval(center3X, center3Y, 100, 100);

        //connect the centers of the circles with lines
        g.drawLine(center1X+50, center1Y+50, center2X+50, center2Y+50);
        g.drawLine(center2X+50, center2Y+50, center3X+50, center3Y+50);
        g.drawLine(center3X+50, center3Y+50, center1X+50, center1Y+50);


    }


    }
    public static void main(String[] args)  {
    DrawCircles frame = new DrawCircles();
    frame.setSize(700,500);
    frame.setLocationRelativeTo(null);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);


    }


    }

person ez4nick    schedule 25.03.2014    source источник
comment
Ваш текущий код не компилируется. Но несмотря ни на что, мои отредактированные рекомендации остаются в силе.   -  person Hovercraft Full Of Eels    schedule 26.03.2014
comment
хорошо, я сейчас работаю над реализацией этого изменения. Логично, что это должно работать   -  person ez4nick    schedule 26.03.2014
comment
Пожалуйста, смотрите редактирование, чтобы ответить для примера того, что я имею в виду.   -  person Hovercraft Full Of Eels    schedule 26.03.2014


Ответы (1)


Вы заявляете:

Проблема в том, что при нажатии кнопки сброса, а затем кнопки расчета панель перекрашивается, а этого быть не должно. (См. код ниже, где метод перерисовки отсутствует в ActionListener() для calculateButton). Мне интересно, почему это происходит, и что я могу сделать, чтобы панель не перерисовывалась при нажатии этой кнопки. (Кнопка сброса работает именно так, как и ожидалось, перекрашивая панель).

Невозможно догадаться, что может быть не так, основываясь на коде, который вы разместили до сих пор. Я призываю вас подумать о создании и публикации минимальной программы-примера, которая позволит нам самим увидеть вашу проблему.

Но, сказав это, я добавлю, что у вас никогда не будет полного контроля над тем, когда компонент отрисовывается или нет, поскольку многие отрисовки управляются JVM, реагирующей на операционную систему. Это одна из причин, по которой программная логика никогда не должна находиться внутри переопределения метода paint(Graphics g) или paintComponent(Graphics g).

Таким образом, ваша проблема на самом деле является замаскированной проблемой XY. Вы спрашиваете, как управлять перерисовкой компонента, тогда как вместо этого вы должны спрашивать, как вывести логику вашей программы из одного из методов перерисовки, и на самом деле это мое предположение о решении вашей проблемы — убедитесь, что ваша перерисовка Метод используется исключительно для покраски и больше ничего.


Изменить
Да, у вас есть программная логика в методе paintComponent, а именно этот код:

Random rand = new Random(System.currentTimeMillis());
center1X=rand.nextInt(507);
center1Y=rand.nextInt(320);
center2X=rand.nextInt(507);
center2Y=rand.nextInt(320);
center3X=rand.nextInt(507);
center3Y=rand.nextInt(320);

Получите его из paintComponent и в его собственном методе, который позволит вам контролировать, когда он вызывается.


Редактировать 2
Например, вы можете сделать следующее:

public class CircleDraw extends JPanel {
  private int radius;
  private double s;
  private double area;
  private Random rand = new Random(); // make this a field

  // call this when you want to change the random images
  public void randomizeDrawing() {
     center1X = rand.nextInt(507);
     center1Y = rand.nextInt(320);
     center2X = rand.nextInt(507);
     center2Y = rand.nextInt(320);
     center3X = rand.nextInt(507);
     center3Y = rand.nextInt(320);
     repaint();
  }

  // and only do painting in paintComponent
  @Override
  protected void paintComponent(Graphics g) {
     super.paintComponent(g);

     // draw the 3 circles
     g.drawOval(center1X, center1Y, 100, 100);
     g.drawOval(center2X, center2Y, 100, 100);
     g.drawOval(center3X, center3Y, 100, 100);

     // connect the centers of the circles with lines
     g.drawLine(center1X + 50, center1Y + 50, center2X + 50, center2Y + 50);
     g.drawLine(center2X + 50, center2Y + 50, center3X + 50, center3Y + 50);
     g.drawLine(center3X + 50, center3Y + 50, center1X + 50, center1Y + 50);
  }
person Hovercraft Full Of Eels    schedule 25.03.2014