我现在已经在我的项目上工作了几个小时,但却一直对此感到沮丧。
我有一个父JFrame,它为它添加了一个JPanel,它将用于渲染和显示我正在开发的模拟。没有将要添加到JPanel的swing对象,因为我将仅使用它来使用图形对象渲染形状。
我的代码如下:
public class SimulationPanel extends JPanel {
private BufferedImage junction;
private Graphics2D graphics;
public SimulationPanel() {
super();
initPanel();
}
private void initPanel() {
this.setPreferredSize(new Dimension(600, 600)); //TODO: bug with not sizing the junction correctly.
junction = new BufferedImage(this.getWidth(), this.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
graphics = junction.createGraphics();
setBackground(Color.white);
System.out.println(getWidth());
}
代码专门在initPanel()方法的第二行中断,我尝试创建一个新的BufferedImage。
异常的输出指出“线程中的异常”AWT-EventQueue-0“java.lang.IllegalArgumentException:Width(0)和height(0)必须是> 0”
我真的不确定这是为什么。我试图使用Stack Overflow的过去的答案,但他们没有成功帮助。
这是我的第一篇文章,所以我希望它不是太糟糕。
感谢。
答案 0 :(得分:4)
当您设置首选大小时,您可以告诉各种Java布局管理器在将面板添加到容器后,您希望如何布置面板。但是直到它实际上被添加到容器中,它将没有宽度或高度,即使在它之后,它可能没有你要求的宽度和高度。
一个选项是直接使用600作为新缓冲图像的宽度和高度,当您将面板添加到JFrame时,请确保在JFrame上调用pack()
以允许窗口大小为您小组的首选尺寸。
答案 1 :(得分:3)
在组件的paintComponent方法中创建一个BufferedImage缓存。在那里,您将知道组件的实际大小,并将其考虑在内以进行渲染。该图像充当组件内容的缓存,但您没有考虑到它的大小是缓存信息的一部分。
@Override protected void paintComponent(Graphics g) {
// create cache image if necessary
if (null == image ||
image.getWidth() != getWidth() ||
image.getHeight() != getHeight() ||) {
image = new BufferedImage(getWidth(), getHeight());
imageIsInvalid = true;
}
// render to cache if needed
if (imageIsInvalid()) {
renderToImage();
}
// redraw component from cache
// TODO take the clip into account
g.drawImage(image, 0, 0, null);
}
答案 2 :(得分:1)
这不起作用的原因是pack()
未被调用(设置所有宽度和高度值),直到面板启动之后,这就是为什么还没有设置高度和宽度。如果宽度或高度是非正整数,BufferedImage将抛出异常。
那你为什么不自己设定价值呢?以下是如何在您的示例中执行此操作:
private void initPanel() {
final int width = 600;
final int height = 600;
this.setPreferredSize(new Dimension(width, height));
junction = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
graphics = junction.createGraphics();
setBackground(Color.white);
}
或者:如果您要求必须使用组件调整图像大小,则需要。我很确定调用pack()
时会触发ComponentListener.componentResized()
事件,因此即使您没有调整组件大小,这也应该在您启动组件时起作用。所以请在代码中执行此操作:
private void initPanel() {
this.setPreferredSize(new Dimension(600, 600));
this.addComponentListener(new ComponentListener() {
public void componentResized(ComponentEvent e) {
Component c = (Component) e.getSource();
Dimension d = c.getSize();
resizeImage(d);
}
});
this.setBackground(Color.white);
}
public void resizeImage(Dimension d) {
junction = new BufferedImage(d.getWidth(), d.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
graphics = junction.createGraphics();
}