Swing足够轻量可控,适合初学者理解事件驱动、布局与文件I/O协同;需检查JFileChooser返回值、用File对象而非路径、正确绘制到组件并缓存缩放图。
Java桌面端图片展示应用,用 Swing 足够轻量且可控,不需要引入 JavaFX 或第三方 UI 框架——尤其适合初学者理解事件驱动、组件布局和文件 I/O 的协同逻

JFileChooser 安全选择单张图片新手常直接调用 showOpenDialog 后忽略返回值,导致用户点“取消”时程序仍尝试加载空路径,抛出 NullPointerException 或 IOException。
JFileChooser 的返回值是否为 JFileChooser.APPROVE_OPTION
ImageIO.getReaderFileSuffixes() 可获取支持的后缀列表(如 "jpg", "png", "gif")getSelectedFile().getPath() 拼接路径;直接用 getSelectedFile() 得到 File 对象,再传给 ImageIO.read()
ImageIO.read() 读取成功却显示空白典型原因是图片被加载进 BufferedImage,但没正确绘制到组件上——尤其是新手习惯直接把图片塞进 JLabel 的 setIcon(),却忘了该 JLabel 是否已加入容器、是否设置了合适的布局约束。
JLabel 默认使用 FlowLayout,若父容器是 JFrame 的默认 BorderLayout,需显式指定位置:例如 frame.add(label, BorderLayout.CENTER)
paintComponent() 绘图,务必先调用 super.paintComponent(g),否则背景不刷新,旧图残留ImageIO.read() 返回 null 表示解码失败(不是文件不存在),常见于 WebP、HEIC 等格式——JDK 8 及更早版本原生不支持Graphics2D.drawImage() 参数怎么配想让大图自适应窗口大小,又不想失真或拉伸变形,核心是算出等比缩放后的目标宽高,而不是硬设固定尺寸。
Math.min((double)targetWidth / img.getWidth(), (double)targetHeight / img.getHeight()) 计算缩放比例(int)(img.getWidth() * scale) 和 (int)(img.getHeight() * scale),避免整数截断导致严重偏小g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR)
paintComponent 中重复创建缩放后的 BufferedImage,应缓存并监听窗口大小变化后才重绘
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
if (scaledImage != null) {
g2d.drawImage(scaledImage, 0, 0, this);
}
}缩放逻辑和图像缓存容易写错位置:有人把缩放代码放在按钮点击里一次性执行,结果窗口缩放后图片不更新;也有人在 paintComponent 里反复 createGraphics() 和 dispose(),造成资源泄漏。这些细节比功能本身更影响体验。