java - 更新 JPanel 图形时出现无限循环

标签 java swing graphics awt

因此,我正在使用 Grahics2DJPanel 对象中绘制图形。
当我的图形大于窗口时,JPanel 被放置在 JScrollPane 中。
但是在我绘制图形之后,JPanel 的大小没有改变,并且我无法滚动查看图形的其余部分,因此我找到最低点和最左边的点,并在方法中手动设置大小进行绘图(方法称为 drawTrack())。
当我切换窗口或执行其他操作使 JPanel 再次绘制时,我的图形消失,因此我重写了 paint()repaint()validate ()invalidate() 方法,并在其中调用 drawTrack() 方法在重绘 JPanel 的每种可能情况下绘制图形。
问题是,当 JPanel 调用执行重绘的方法之一时,我会在其中调用 drawTrack() ,在重绘图形后手动设置大小,以便我可以滚动 JScrollPane 并查看我的整个图形。但是当我在 JPanel 上调用 setSize() 方法时,它会再次重绘,这意味着调用 drawTrack() 等等。
出现滚动条是因为尺寸正确,但它会创建一个无限循环,一遍又一遍地重绘我的图形。如果我不调用 setSize() 方法,我的 JPanel 将获得默认大小,以便它可以适合 JScrollPane 的视口(viewport),从而我无法滚动它来查看我的图形。
有什么建议吗?

最佳答案

当您调整 JPanel 的大小时,您会刺激重新绘制,因此,如果您更改 Paint 或 PaintComponent 方法或在这两种方法中调用的方法中的大小,对我来说,您有可能导致无限的风险,这是有道理的。循环。

解决方案:不要在paint或paintComponent方法中调整任何内容的大小。这个方法只是为了绘画而已。相反,如果您想设置 JPanel 的大小,请重写其 getPreferredSize() 方法。

这是一个“多彩”的例子:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

@SuppressWarnings("serial")
public class ImageReSize extends JPanel {
   private static final int INIT_WIDTH = 400;
   private static final int MAX_WIDTH = 1200;

   private static final int TIMER_DELAY = 20;
   protected static final int WIDTH_STEP = 5;
   private int width = INIT_WIDTH;
   private int height = INIT_WIDTH;
   private boolean growing = true;

   public ImageReSize() {
      new Timer(TIMER_DELAY, new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            if (growing && width < MAX_WIDTH) {
               width += WIDTH_STEP;
               height += WIDTH_STEP;
            } else {
               growing = false;
            }

            if (!growing && width > INIT_WIDTH) {
               width -= WIDTH_STEP;
               height -= WIDTH_STEP;
            } else {
               growing = true;
            }
            // get the parent container which is the scrollpane's viewport
            JComponent parent = (JComponent)getParent();
            parent.revalidate(); // let it relayout the changed size JPanel
            parent.repaint();  // and repaint all
         }
      }).start();
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D)g;
      float x = (float)width / 10;
      float y = (float)height / 10;
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
      g2.setPaint(new GradientPaint(x, 0, Color.green, 0, y, Color.black, true));
      g2.fillRect(0, 0, getWidth(), getHeight());
      g2.setPaint(new GradientPaint(0, 0, Color.blue, x, y, Color.red, true));
      g2.fillOval(0, 0, width, height);
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(width, height);
   }

   private static void createAndShowUI() {
      ImageReSize imageReSize = new ImageReSize();
      JFrame frame = new JFrame("ImageReSize");
      frame.getContentPane().add(new JScrollPane(imageReSize));
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      java.awt.EventQueue.invokeLater(new Runnable() {
         public void run() {
            createAndShowUI();
         }
      });
   }
}

关于java - 更新 JPanel 图形时出现无限循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7546163/

相关文章:

java - 如何使方法将任何类型的数组作为参数?

java - 如何制作具有固定日期格式的 jtextfield?

java - 将 jFrame 输出到 jpeg 或位图

java - 其他类中改变颜色 "lamp"

java - java中的数字模式程序

java - 为什么我收到此错误 : java. sql.SQLException : Prepared statement needs to be re-prepared?

java - 检索从组中选择的 Swing 单选按钮

java - 在 JDialog 中使用自定义图标实现最小化功能的最简单方法

forms - windows.forms 和重绘位图

java - 访问另一个类中的可观察列表