java - BufferedImage 没有出现在 JFrame 中
问题描述
这是我的第二个 Java 项目,我对编程完全陌生,但我已经为此工作了很长一段时间。但是代码可能是一团糟。我正在尝试在 JFrame 中重现图像,但我不知道如何解决所述问题。会不会是文件格式的问题?当我将包文件夹和图像文件作为路径插入时,它编译时不会出现错误消息,即使它似乎没有绘制任何内容。在我更改了我的桌面(或其他任何东西)的路径后,我得到了以下异常:
Exception in thread "main" java.lang.IllegalArgumentException: input == null!
at javax.imageio.ImageIO.read(Unknown Source)
at Informatik.Timezones.main(Timezones.java:287)
显然没有找到源,这意味着它之前被正确识别。也许我在 JFrame 而不是 Label 或 Panel 上绘图,这会导致问题。
这是生成面板并绘制图像的 main 方法中的部分代码。
JFrame zeichnen = new JFrame();
face = new JLabel();
face.setVisible(true);
face.setSize(1000, 1000);
face.setLayout(null);
face.setLocation(0, 0);
zeichnen.add(face);
zeichnen.setVisible(true);
zeichnen.setSize(1000, 1000);
zeichnen.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
zeichnen.setLocationRelativeTo(null);
zeichnen.setResizable(false);
zeichnen.setLayout(null);
try {
bildchen = ImageIO.read(Timezones.class.getClassLoader().getResourceAsStream("Info rmatik/a.jpg"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
这是我的代表:
package Informatik;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import java.awt.RenderingHints;
import javax.swing.*;
public class Test extends JPanel{
static JLabel face;
static BufferedImage bildchen;
@Override
public void paintComponent(Graphics maler) {
super.paintComponent(maler);
Graphics2D maler2 = (Graphics2D) maler;
maler2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
maler.drawImage(bildchen, 1000, 1000, null);
}
public static void main (String args []) {
JFrame zeichnen = new JFrame();
face = new JLabel();
face.setVisible(true);
face.setSize(1000, 1000);
face.setLayout(null);
face.setLocation(0, 0);
zeichnen.add(face);
zeichnen.setVisible(true);
zeichnen.setSize(1000, 1000);
try {
bildchen = ImageIO.read(Timezones.class.getClassLoader().getResourceAsStream("/Informatik/a.jpg"));
} catch (IOException e) {
//catch block
e.printStackTrace();
}
zeichnen.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
zeichnen.setLocationRelativeTo(null);
zeichnen.setResizable(false);
zeichnen.setLayout(null);
}
}
这是新的工作版本:
package Informatik;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.print.DocFlavor.URL;
import javax.swing.*;
public class TestImageLoad extends JPanel {
JLabel face;
BufferedImage bildchen;
TestImageLoad() {
initUI();
}
private void initUI() {
JFrame zeichnen = new JFrame();
face = new JLabel("face");
face.setForeground(Color.RED);
zeichnen.add(this);
this.add(face);
try {
java.net.URL url = this.getClass().getResource("/Informatik/a.jpg");
System.out.println(url);
bildchen = ImageIO.read(url);
} catch (IOException e) {
e.printStackTrace();
}
zeichnen.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
zeichnen.pack();
zeichnen.setLocationRelativeTo(null);
zeichnen.setVisible(true);
}
@Override
public void paintComponent(Graphics maler) {
super.paintComponent(maler);
maler.drawImage(bildchen, 0, 0, this);
}
public static void main(String args[]) {
Runnable r = () -> {
new TestImageLoad();
};
SwingUtilities.invokeLater(r);
}
}
解决方案
对新(工作)代码的评论
类加载器是加载应用程序资源的方便工具,但有一些技巧可以让它们正常工作:
(但首先是个人的)getResourceAsStream
出于各种原因,我避免使用该方法。其中主要有:
getResource
返回一个URL
. 出错时更容易调试,因为我们可以打印出 URL 并检查它指向我们认为应该的位置。如果找不到该资源,它将是null
,但是当我们在类路径中有两个同名资源并且它没有获取我们想要的资源时,它也会发出警告。后者非常罕见,但确实会发生。- 如果我们需要
InputStream
来自 URL,它只是一个方法调用。简单的。URL
OTOH 许多方法使用 a或(aString
表示)File
等或 a (特别适用于 Java Sound,可能的其他事物)更好地(甚至仅)工作BufferedInputStream
,并且从该getResourceAsStream
方法返回的流通常不被缓冲。同样,它只是一行代码来解决这个问题,但它可以让我们绊倒。如果该方法接受一个 URL,这一切都会自动处理。 - 他们使用不同的规则来寻找资源。这似乎是 Sun/Oracle 的一个愚蠢的决定,但是……无论如何。我通常建议人们在路径前加上前缀,
/
以确保他们直接从类路径的根开始。这适用于getResource
,但 .. 与 .. 不同getResourceAsStream
。老实说,人们试图解释这些差异的复杂性,但我却置之不理。getResource
有效,这就是我使用的。
好的,现在我已经解释了为什么我建议使用getResource
, 回到技巧。
- 好吧,你已经用过一个,上面提到过。即通过添加
/
作为前缀。 - 但最重要的是,根类加载器和上下文类加载器之间的区别。我在尝试获取
main
方法中的资源时遇到了无数麻烦(为 host 设置图标JFrame
)。事实证明,该调用正在使用系统或根类加载器,它仅用于加载系统(例如 JRE API 类)资源。它有一个非常有限的类路径,以使搜索更快。上下文类加载器是我们可以从中获取嵌入式资源的类加载器。但是像这样的调用TimeZone.class.getClassLoader()
通常会获取根类加载器,而不是上下文。要获取上下文类加载器,它总是可以从构造函数或我们自定义类的方法调用代码,并使用实例化对象(如this
)。
旧代码
原始代码将标签添加到框架,而不是绘制图像的自定义绘制面板!这样做的方法是将自定义绘制面板添加到框架,然后将标签添加到该面板。
原始代码一团糟。我在这样做的同时对其进行了重组并修复了许多事情。很多东西我都忘了是什么。请参阅此代码以获取详细信息。
首先检查此代码是否适用于您的系统/环境,然后让此代码与您的图像一起使用,这似乎仍然是一个问题。
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
public class TestImageLoad extends JPanel {
JLabel face;
BufferedImage bildchen;
TestImageLoad() {
initUI();
}
private void initUI() {
JFrame zeichnen = new JFrame();
face = new JLabel("face");
face.setForeground(Color.RED);
zeichnen.add(this);
this.add(face);
try {
URL url = new URL("https://i.stack.imgur.com/OVOg3.jpg");
bildchen = ImageIO.read(url);
} catch (IOException e) {
e.printStackTrace();
}
zeichnen.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
zeichnen.pack();
zeichnen.setLocationRelativeTo(null);
zeichnen.setVisible(true);
}
@Override
public void paintComponent(Graphics maler) {
super.paintComponent(maler);
maler.drawImage(bildchen, 0, 0, this);
}
public static void main(String args[]) {
Runnable r = () -> {
new TestImageLoad();
};
SwingUtilities.invokeLater(r);
}
}
推荐阅读
- python - 如何停止遍历 for 循环,以便玩家可以在 Python 迷宫游戏中移动?
- gradle - 如何在 gradle 生成的 startScripts 中修复类路径
- regex - RegEx 用于删除 Notepad++ 中具有相同 id 的行
- php - 数据表js和查询次数php mysql
- javascript - 传递的道具未被识别为字符串
- mysql - 从函数获取数据并保存在 mongodb 上时出错
- javascript - 在 AmCharts 4 Bullet Tooltip 中换行长文本
- scala - 列表模式匹配返回每个其他元素的新列表
- google-speech-api - 如何从谷歌语音异步检索数据
- python - os.path.split(path) 正在用字母替换数字。帮我防止这种情况