🏠 个人博客:狐狸半面添的客栈
1.问题描述
我们先看一段非常简单的代码来展示我们的问题:
import javax.swing.*;
/**
* @author 狐狸半面添
* @create 2023-09-19 1:26
*/
public class MyFrame extends JFrame {
/**
* 启动项目,创建容器
*/
public static void main(String[] args) {
new MyFrame();
}
public MyFrame() {
// 初始化界面
initJFrame();
// 初始化图片
initImage();
// 设置窗体可见
this.setVisible(true);
}
/**
* 初始化界面/容器
*/
private void initJFrame() {
// 设置窗体宽高
this.setSize(600, 600);
// 设置标题
this.setTitle("Demo");
// 设置窗体居中
this.setLocationRelativeTo(null);
// 设置窗体关闭方式
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
/**
* 初始化图片组件
*/
private void initImage() {
// 展示两张图片 0.jpg 和 1.jpg ,两张图片的宽高都是 105
for (int i = 0; i < 2; i++) {
// 创建一个管理容器
JLabel jLabel = new JLabel(new ImageIcon("D:\\image\\" + i + ".jpg"));
// 指定照片位置
jLabel.setBounds(105 * i, 0, 105, 105);
// 把管理容器加到界面当中
this.getContentPane().add(jLabel);
}
}
}
我们运行期待的结果是两张图片在第一行依次排列,但是实际上的效果是:
- 0.jpg 在 setBounds 设置的位置正确摆放;
- 1.jpg 在布局页面的中央位置显示,setBounds 设置没有生效。
2.问题分析
默认情况下,JFrame 使用 BorderLayout
作为其内容面板的布局管理器。
JFrame 使用 BorderLayout 作为布局管理器的底层逻辑:
- 当内容面板添加多个组件时,它们将按照 BorderLayout 的规则进行排列。
- 对于 BorderLayout,默认情况下,只有 **中央位置(CENTER)**处的组件会填充整个可见区域。
- 而 BorderLayout 只允许一个组件占据中央位置,因此先加入进来的组件会有两种处理方式:
- 如果设置了 setBounds(),则会放到设置的位置;
- 如果没设置 setBounds(),则先加入的组件仍会留在中间位置,但会被后加入的组件所覆盖掉。
因此,这就解释了为什么我们最后一张图片没有按照设置的 setBounds 摆放,而是一直处于界面的正中央。因为 BorderLayout 布局是生效的,换句话说,BorderLayout 布局设置优先级高于 setBounds。
因此,如果我们想让我们的所有组件位置布局生效,或者说是最后一个组件的位置布局生效,就需要移除默认的 BorderLayout 布局管理器
3.问题解决
通过设置 setLayout(null),我们将 JFrame 的布局管理器设置为空,这意味着我们需要手动控制组件的位置和大小,而不是依赖于自动布局。这对于我们在 setBounds() 方法中直接设置组件的位置和大小非常有用。
我们修改“问题描述”中提供的代码的 initJFrame() 方法,只需要在方法中加一段移除布局管理器的设置即可:
// 移除默认的 BorderLayout 布局管理器
this.getContentPane().setLayout(null);
最终效果: