因此,我正在使用 Grahics2D
在 JPanel
对象中绘制图形。
当我的图形大于窗口时,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/