Java Swing:为什么我不能在 JFrame 实例上使用 drawImage()?
Java Swing: Why can't I drawImage() on an instance of JFrame?
在不深入细节的情况下,我正致力于在 Swing 中创建类似桌面的程序,在背景图像上绘制图标。通常我子类化 JPanel 或另一个 JComponent 并在其上进行绘制,但想尝试一些新的东西只是为了好玩,并尝试在 JFrame 的 instance 上进行绘制,而不是让我的程序成为它的子类。
我知道这不是公认的做法,但发现图像不是绘制的,这暴露了我对 Swing 的理解中缺失的 link(我想是众多缺失之一)以及它如何绘制组件。
让我感到困惑的是,如果我的程序子类化 JFrame 并且我重写了 paint() 方法(换句话说,可接受的方式),它会将图像绘制到 JFrame 中,但它不会这样做我的非子类程序中的 JFrame 实例。
希望基本上显示我想做的事情的代码能有所帮助:
public class ImageLoader
{
BufferedImage img = null;
JFrame window = null;
public ImageLoader()
{
try
{
img = ImageIO.read(new File("src/strawberry.jpg"));
}catch(IOException e)
{
e.printStackTrace();
}
window = new JFrame("Strawberry Viewer");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.pack();
window.setVisible(true);
//Why can't I do something akin to the following to draw on an instance of JFrame?
Graphics g = window.getGraphics();
paint(g);
}
public void paint(Graphics g)
{
g.drawImage(img, 0, 0, null);
}
public static void main(String[] args)
{
new ImageLoader();
}
}
我已经阅读了 Oracle 的页面 "Painting in AWT and Swing",但我仍然不明白为什么我不能在 JFrame 的实例上绘图。在任何情况下我都可以在一个组件的实例上绘制,或者如果我想在它们上绘制它们是否都必须被子类化?
最后,如果问题主要是由于我对 Swing 工作原理的严重误解,有哪些推荐的书籍或其他资源可以帮助您理解 Swing?
提前感谢您的帮助。我很感激。
不要使用 getGraphics() 进行绘画。
您对该 Graphics 对象所做的任何操作都只是暂时的。然后下次 Swing 确定框架需要重新绘制时,您将失去绘画。
在您的情况下,您使用 pack() 以便将框架最小化。当您调整框架大小时,正常的框架绘画将覆盖您的图像。所以尝试使用 setSize(500, 500);
.
然而,即使这样也行不通,因为您的图像将在正常绘制完成之前进行绘制。并非所有代码都按顺序执行。
尝试以下方法来延迟图像的绘制:
try
{
Thread.sleep(1000);
Graphics g = window.getGraphics();
paint(g);
}
catch(Exception e) { e.printStackTrace(); }
当图像显示时,然后尝试调整框架大小,您将丢失图像。
if my program subclasses JFrame and I override the paint() method
不要重写 JFrame 的 paint()(是的,它会起作用,但它不是设计用于在 Swing 中完成绘画的方式)。自定义绘画是通过覆盖 JPanel 的 paintComponent() 然后将面板添加到框架来完成的。
if the problem is based largely on my gross misunderstanding of how Swing works
Swing 教程是学习 Swing 基础知识的最佳起点。请参阅 Custom Painting 部分以开始使用。
有关更多技术文章,请参阅 Painting in AWT and Swing。
在不深入细节的情况下,我正致力于在 Swing 中创建类似桌面的程序,在背景图像上绘制图标。通常我子类化 JPanel 或另一个 JComponent 并在其上进行绘制,但想尝试一些新的东西只是为了好玩,并尝试在 JFrame 的 instance 上进行绘制,而不是让我的程序成为它的子类。
我知道这不是公认的做法,但发现图像不是绘制的,这暴露了我对 Swing 的理解中缺失的 link(我想是众多缺失之一)以及它如何绘制组件。
让我感到困惑的是,如果我的程序子类化 JFrame 并且我重写了 paint() 方法(换句话说,可接受的方式),它会将图像绘制到 JFrame 中,但它不会这样做我的非子类程序中的 JFrame 实例。
希望基本上显示我想做的事情的代码能有所帮助:
public class ImageLoader
{
BufferedImage img = null;
JFrame window = null;
public ImageLoader()
{
try
{
img = ImageIO.read(new File("src/strawberry.jpg"));
}catch(IOException e)
{
e.printStackTrace();
}
window = new JFrame("Strawberry Viewer");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.pack();
window.setVisible(true);
//Why can't I do something akin to the following to draw on an instance of JFrame?
Graphics g = window.getGraphics();
paint(g);
}
public void paint(Graphics g)
{
g.drawImage(img, 0, 0, null);
}
public static void main(String[] args)
{
new ImageLoader();
}
}
我已经阅读了 Oracle 的页面 "Painting in AWT and Swing",但我仍然不明白为什么我不能在 JFrame 的实例上绘图。在任何情况下我都可以在一个组件的实例上绘制,或者如果我想在它们上绘制它们是否都必须被子类化?
最后,如果问题主要是由于我对 Swing 工作原理的严重误解,有哪些推荐的书籍或其他资源可以帮助您理解 Swing?
提前感谢您的帮助。我很感激。
不要使用 getGraphics() 进行绘画。
您对该 Graphics 对象所做的任何操作都只是暂时的。然后下次 Swing 确定框架需要重新绘制时,您将失去绘画。
在您的情况下,您使用 pack() 以便将框架最小化。当您调整框架大小时,正常的框架绘画将覆盖您的图像。所以尝试使用 setSize(500, 500);
.
然而,即使这样也行不通,因为您的图像将在正常绘制完成之前进行绘制。并非所有代码都按顺序执行。
尝试以下方法来延迟图像的绘制:
try
{
Thread.sleep(1000);
Graphics g = window.getGraphics();
paint(g);
}
catch(Exception e) { e.printStackTrace(); }
当图像显示时,然后尝试调整框架大小,您将丢失图像。
if my program subclasses JFrame and I override the paint() method
不要重写 JFrame 的 paint()(是的,它会起作用,但它不是设计用于在 Swing 中完成绘画的方式)。自定义绘画是通过覆盖 JPanel 的 paintComponent() 然后将面板添加到框架来完成的。
if the problem is based largely on my gross misunderstanding of how Swing works
Swing 教程是学习 Swing 基础知识的最佳起点。请参阅 Custom Painting 部分以开始使用。
有关更多技术文章,请参阅 Painting in AWT and Swing。