【问题标题】:Using the repaint() method in a JPanel without erasing what is already drawn在 JPanel 中使用 repaint() 方法而不擦除已绘制的内容
【发布时间】:2019-06-15 12:34:38
【问题描述】:

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

【问题讨论】:

  • 不要做super.paintComponent

标签: java jframe jpanel paintcomponent repaint


【解决方案1】:

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

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

【讨论】:

  • 感谢您的帮助,但这似乎不起作用。调用setOpaque(false); 甚至不会绘制黑色背景,并且每次调用repaint(); 时都会擦除蓝点。
猜你喜欢
  • 2016-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-15
  • 2023-03-23
  • 1970-01-01
  • 2011-09-08
  • 2018-08-23
相关资源
最近更新 更多