在不深入讨论细节的情况下,我正在努力在 Swing 中创建一个类似桌面的程序,并在背景图像之上绘制图标。通常我会子类化 JPanel 或另一个 JComponent 并在其上进行绘制,但只是想尝试一些新的东西,并尝试在 JFrame 的实例上进行绘制,而不使我的程序成为它的子类。
我知道这不是公认的做法,但是发现图像没有绘制,暴露了我对 Swing 及其如何绘制组件的理解中缺失的链接(我想是众多链接之一)。
令我困惑的是,如果我的程序子类化了 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 .
关于Java Swing : Why can't I drawImage() on an instance of JFrame?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31486698/