методът repaint() не функционира според очакванията

Имам 2 бутона, бутон за нулиране и бутон за изчисляване.
Единствената цел на бутона за нулиране е да пребоядиса 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