在JPanel中使用repaint()方法而不删除已绘制的内容

时间:2019-01-22 04:56:27

标签: java jframe jpanel paintcomponent repaint

我最初制作程序如下。我使用了Extended Canvas和update方法来不断绘制更多点。我的理解是,每次调用repaint()时,都会通过使用update()方法将新点添加到现有的Canvas上。如果每次调用repaint()时方法是paint()而不是update(),则它将仅用五十个点绘制一个新的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;
      }
   }
}

以下代码是扩展JFrame的BarnsleyFernRunner类。这将设置JFrame并包含main方法。

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。我的问题是如何在JPanel中调用repaint()方法而不创建一个全新的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 :(得分:0)

super.paintComponent(window);方法调用paintComponent()时,您正在要求JPanel绘制边框和背景。绘制背景意味着破坏以前的所有内容。

处理此问题的最简单方法是简单地忽略对super.paintComponent(window);的调用。另一种方法是调用setOpaque(false);。这告诉面板您有责任自己绘制背景。