Использование метода repaint () в JPanel без удаления уже нарисованного - PullRequest
0 голосов
/ 22 января 2019

Первоначально я сделал программу следующим образом. Я использовал расширяет Canvas и метод обновления, чтобы постоянно рисовать больше точек. Насколько я понимаю, каждый раз, когда вызывается repaint (), новые точки добавляются в существующий Canvas с помощью метода update (). Если бы метод вызывал paint () вместо update () каждый раз, когда вызывался repaint (), он рисовал бы новый Canvas, содержащий только пятьдесят точек. Это мой класс BarnsleyFern, который расширяет Canvas.

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Color;
import java.awt.Canvas;
import java.lang.Math;
import java.awt.event.*;
import javax.swing.*;
public class BarnsleyFern extends Canvas
{
   private double newX,x=0;
   private double newY,y=0;
   public BarnsleyFern(int width, int height)
   {
      setBackground(Color.BLACK);
      setSize(width,height);
      setVisible(true);
      ActionListener action = new ActionListener()
      {
         public void actionPerformed(ActionEvent event)
         {  
            repaint();
         }
      };
      Timer timer = new Timer(100,action);
      timer.start();
   }
   public void update(Graphics window)
   {
      Graphics2D g2d = (Graphics2D)window;
      window.translate(360,800);
      //g2d.rotate(Math.toRadians(180));
      fern(window);
   }
   public void fern(Graphics window)
   {
      Color newColor = new Color((int)(Math.random()*256),(int)(Math.random()*256),(int)(Math.random()*256));
      for(int i=0;i<50;i++)
      {
         window.setColor(Color.BLUE);
         int rand = (int)(Math.random()*100);
         if(rand<1)
         {
            newX=0;
            newY=0.16*y;
         }
         else if(rand<86)
         {
            newX=0.85*x + 0.04*y;
            newY=0.85*y - 0.04*x + 1.6;
         }  
         else if(rand<93)
         {
            newX=0.20*x - 0.26*y;
            newY=0.23*x + 0.22*y + 1.6;
         }
         else
         {
            newX=0.28*y - 0.15*x;
            newY=0.26*x + 0.24*y + 0.44;
         }
         window.fillOval((int)(newX*165.364),-(int)(newY*80.014),2,2);   
         x=newX;
         y=newY;
      }
   }
}

Следующий код является классом BarnsleyFernRunner, который расширяет JFrame. Это устанавливает JFrame и содержит основной метод.

import javax.swing.JFrame;
public class BarnsleyFernRunner extends JFrame
{
   public BarnsleyFernRunner()
   {
      setTitle("Barnsley Fern");
      setSize(800,800);
      add(new BarnsleyFern(800,800));
      setVisible(true);
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   }
   public static void main(String[] args)
   {  
      BarnsleyFernRunner runner = new BarnsleyFernRunner();
   }
}

Затем я решил немного изменить свой код, расширив JPanel вместо Canvas. Я решил сделать это, потому что JPanel и JFrame оба из пакета javax.swing. Новый класс BarnsleyFern использует класс BarsnleyFernRunner сверху. Этот класс работает не так, как раньше. Каждый раз, когда вызывается repaint (), пятьдесят новых точек рисуются, а старые исчезают. Насколько я понимаю, это так, потому что каждый раз, когда repaint () вызывается, создается новый JPanel. Мой вопрос заключается в том, как я могу вызвать метод repaint () в JPanel, не создавая полностью новую JPanel. Есть ли способ вызвать repaint () без "стирания" того, что я уже нарисовал. Есть ли способ, которым я могу дублировать то, что я сделал в первом классе с помощью метода update (). Это мой класс BarnsleyFern, который расширяет JPanel

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Color;
import java.awt.Canvas;
import java.lang.Math;
import java.awt.event.*;
import javax.swing.*;
public class BarnsleyFern extends JPanel
{
   private double newX,x=0;
   private double newY,y=0;
   public BarnsleyFern(int width, int height)
   {
      setBackground(Color.BLACK);
      setSize(width,height);
      setVisible(true);
      ActionListener action = new ActionListener()
      {
         public void actionPerformed(ActionEvent event)
         {  
            repaint();
         }
      };
      Timer timer = new Timer(100,action);
      timer.start();
   }
   public void paintComponent(Graphics window)
   {
      super.paintComponent(window);
      Graphics2D g2d = (Graphics2D)window;
      window.translate(360,800);
      //g2d.rotate(Math.toRadians(180));
      fern(window);
   }
   public void fern(Graphics window)
   {
      Color newColor = new Color((int)(Math.random()*256),(int)(Math.random()*256),(int)(Math.random()*256));
      for(int i=0;i<50;i++)
      {
         window.setColor(Color.BLUE);
         int rand = (int)(Math.random()*100);
         if(rand<1)
         {
            newX=0;
            newY=0.16*y;
         }
         else if(rand<86)
         {
            newX=0.85*x + 0.04*y;
            newY=0.85*y - 0.04*x + 1.6;
         }  
         else if(rand<93)
         {
            newX=0.20*x - 0.26*y;
            newY=0.23*x + 0.22*y + 1.6;
         }
         else
         {
            newX=0.28*y - 0.15*x;
            newY=0.26*x + 0.24*y + 0.44;
         }
         window.fillOval((int)(newX*165.364),-(int)(newY*80.014),2,2);   
         x=newX;
         y=newY;
      }
   }
}

1 Ответ

0 голосов
/ 22 января 2019

Когда вы вызываете super.paintComponent(window); в вашем paintComponent() методе, вы просите JPanel нарисовать вашу рамку и фон. Нарисовать фон - значит забить все, что было раньше.

Самый простой способ справиться с этим - просто пропустить вызов super.paintComponent(window);. Другой способ - позвонить setOpaque(false);. Это говорит панели, что вы сами отвечаете за рисование фона.

...