我试图在JFrame中包含的JPanel上呈现特定预定义大小的BufferedImages。我可以严格定义JPanel的大小,但似乎设置JFrame的大小设置总外部区域,包括标题和边框,并且这些在不同的图形环境中看起来具有不同的值。设置太大的大小会在JPanel的外边缘和JFrame的内边缘之间留下空白,并且设置太小的尺寸会导致图像根本无法渲染。
有没有办法在运行时确定填充JFrame大小的额外空间,以确保这些事情都不会发生?或者有没有办法根据内边框而不是外边框来调整JFrame的大小?
当JPanel是显示器的大小并且JFrame的extendedState设置为JFrame.MAXIMIZED_BOTH并且未修饰设置为true时,没有问题,但我还想支持窗口显示模式,该模式在不同的图形环境中是一致的,这是我遇到这个问题的地方。
我最初尝试使用常量填充我正在测试代码的计算机上的JFrame的大小,这在我尝试在不同的计算机上使用它之前一直运行良好。在具有不同监视器的不同计算机上运行相同的代码(尽管分辨率相同)导致边界之间出现额外的空白,因此似乎常量不是答案。
知道Swing如何确定这些区域的大小会很有用,但到目前为止我还没有找到任何解释。
覆盖JPanel的getPreferredSize()
以匹配它所拥有的图像的大小,将其添加到JFrame,然后在添加所有组件后在JFrame上调用pack()
。让Java为您正确调整大小。
例如,
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
@SuppressWarnings("serial")
public class ImagePanel extends JPanel {
public static final String IMG_URL_PATH = "https://upload.wikimedia.org/"
+ "wikipedia/commons/thumb/1/1a/"
+ "WomanFactory1940s.jpg/773px-WomanFactory1940s.jpg";
private BufferedImage image;
public ImagePanel(BufferedImage image) {
this.image = image;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// if the image isn't null, draw it in the JPanel
if (image != null) {
g.drawImage(image, 0, 0, this);
}
}
@Override
public Dimension getPreferredSize() {
// if either the image is null or the panel's preferred size
// has been set, then must use the super's value
if (isPreferredSizeSet() || image == null) {
return super.getPreferredSize();
} else {
// otherwise use the image's size for the panel's pref'd size
int width = image.getWidth();
int height = image.getHeight();
return new Dimension(width, height);
}
}
private static void createAndShowGui(BufferedImage img) {
ImagePanel mainPanel = new ImagePanel(img);
JFrame frame = new JFrame("Image Panel Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// first add all components to the JFrame
frame.getContentPane().add(mainPanel);
// pack the JFrame to allow it to size all its components and itself
frame.pack();
// call this *after* packing only if you want the size fixed
frame.setResizable(false);
frame.setLocationRelativeTo(null);
// then display it
frame.setVisible(true);
}
public static void main(String[] args) {
try {
URL imageUrl = new URL(IMG_URL_PATH);
final BufferedImage img = ImageIO.read(imageUrl);
SwingUtilities.invokeLater(() -> createAndShowGui(img));
} catch (IOException e) {
e.printStackTrace();
}
}
}
选项二(作为camickr指出)是简单地将图像显示为JLabel中的ImageIcon,JLabel是一个将其首选大小自动设置为它所拥有的图标大小的组件。如果您不打算将图像用作动画的背景或者不希望具有可调整大小的图像,则此功能非常有用。例如:
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
public class ImageDisplay {
public static final String IMG_URL_PATH = "https://upload.wikimedia.org/"
+ "wikipedia/commons/thumb/1/1a/"
+ "WomanFactory1940s.jpg/773px-WomanFactory1940s.jpg";
private static void createAndShowGui() {
BufferedImage img = null;
try {
URL imageUrl = new URL(IMG_URL_PATH);
img = ImageIO.read(imageUrl);
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
Icon icon = new ImageIcon(img);
JLabel label = new JLabel(icon);
JFrame frame = new JFrame("Image Display");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(label);
frame.pack();
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}