更新JPanel的图形时无限循环

Hri*_*tov 2 java graphics swing awt

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

Hov*_*els 5

当您调整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();
         }
      });
   }
}
Run Code Online (Sandbox Code Playgroud)