我制作了一个MRE,您可以在底部找到它,以及我正在使用的图像文件。不知道仅上传我的src文件夹是否会更好,但是有人可以告诉我是否可以这样做。首先,它确实填充了JFrame。但是有一个陷阱。仅在contentpane尺寸为(我相信是54的倍数)时,它才能正确填充。我附带了一张图片,因为它很容易看到,所以很容易解释。
现在,如果我调整JFrame
的大小。如果将宽度再增加一个像素,则JPanel
将水平填充。如果我将JFrame垂直扩展一个像素,则高度也一样。JPanel将垂直填充,如下图所示。
两个图像之间的唯一区别是,我在第二个图像中将JFrame的高度/宽度又增加了1个像素
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
class UIPanel extends JPanel {
private BufferedImage[] textures;
GridBagConstraints c = new GridBagConstraints();
JLayeredPane jp = new JLayeredPane();
BufferedImage PewterCityMap;
UIPanel() {
this.setLayout(new BorderLayout());
jp.setLayout(new GridBagLayout());
c.fill = 1;
c.weightx = 1;
c.weighty = 1;
c.gridwidth = 1;
c.gridheight = 1;
try {
PewterCityMap = ImageIO.read(new File("src/imagesUI/PewterCityMap.jpg"));
final int width = 16;
final int height = 16;
final int rows = 55;
final int cols = 53;
textures = new BufferedImage[rows * cols];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
textures[(i * cols) + j] = PewterCityMap.getSubimage(
j * width, i * height,
width, height
);
}
}
} catch (
IOException ex) {
ex.printStackTrace();
}
int count = 0;
for (int i = 0; i < 55; i++) {
c.gridy = i;
c.gridx = 0;
for (int j = 0; j < 53; j++) {
c.gridx = j;
CanEnterLbl canEnterLbl = new CanEnterLbl(new ImageIcon(textures[count]));
jp.add(canEnterLbl, c);
jp.setLayer(canEnterLbl, 0);
count++;
}
}
this.add(jp, BorderLayout.CENTER);
}
public static void main(String[] args) {
JFrame jf = new JFrame();
jf.setLayout(new BorderLayout());
UIPanel ui = new UIPanel();
jf.add(ui, BorderLayout.CENTER);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.pack();
jf.setVisible(true);
}
}
class CanEnterLbl extends JLabel{
private Image img;
CanEnterLbl(ImageIcon imageIcon){
img = imageIcon.getImage();
this.setIcon(imageIcon);
}
@Override
protected void paintComponent(Graphics g){
//In reply to @Frakcool.
//Firstly, thank you! Are the next two lines what you were thinking? I
doesn't fill correctly when using just this line though
//super.paintComponent(g);
//What I was doing before
g.drawImage(img, 0, 0, getWidth(), getHeight(), this);
}
}
我需要调整图像大小
然后,您不应使用JLabel显示图像。您不需要JLabel UI的所有额外开销。
相反,您可以通过扩展JComponent
来创建自定义组件。然后,您可以自定义paintComponent()
方法以缩放绘制时的图像。
[仅在内容窗格尺寸为,我认为是54的倍数时,才能正确填充。
我猜水平方向为53的倍数,垂直方向为55的倍数。
GridBagLayout
将首先以其首选大小为每个组件分配空间。
然后,如果有多余的空间,它将根据weightx / y约束为每个组件分配空间。
您无法将像素的一小部分分配给一个组件。因此,最好的办法是分配一个像素,这就是为什么根据大小方向需要53或55的原因。
我不知道JDK中的任何布局管理器都可以防止面板边缘周围的多余空间
一种可能的解决方案是使用Relative Layout。 Relative Layout
允许相对于可用空间调整组件的大小。给定组件的相对大小后,您可以指定应如何分配“额外”像素。
要使用此方法,您需要一个垂直使用RelativeLayout的主面板,然后是水平使用RelativeLayout的每一行的子面板。
所以逻辑可能类似于:
RelativeLayout verticalLayout = new RelativeLayout(RelativeLayout.Y_AXIS); verticalLayout.setRoundingPolicy( RelativeLayout.EQUAL ); verticalLayout.setFill(true); JPanel mapPanel = new JPanel( vertcalLayout ); for (int i = 0; i < rows; i++) { RelativeLayout rowLayout = new RelativeLayout(RelativeLayout.X_AXIS); rowLayout.setRoundingPolicy( RelativeLayout.EQUAL ); rowLayout.setFill(true); JPanel row = new JPanel( rowLayout ); for (int j = 0; j < cols; j++) { CanEnterLbl canEnterLbl = new CanEnterLbl(…); row.add(canEnterLbl, new Float(1)); } mapPanel.add(row, new Float(1)); }
注意,RelativeLayout不会计算初始的首选大小,因此您需要进行设置,以便frame.pack()方法可以正常工作。