一、引入
刚刚我们已经在页面中添加了图片了,代码并不是很难。
但是代码这样写,会有一点小问题,因为图片都是默认放在正中央的,如果我们添加的图片超过一张,这些图片就会重叠在一起。
我的需求是:第一张图片在左上角显示,然后剩余的图片依次往后放。
想要实现这个效果,就会涉及到左边的概念。
二、介绍
坐标以左上角为原点,向右为 x轴
,向下为 y轴
。
图片所在的位置其实就是 图片左上角的点
在坐标上的位置。

如果是 x、y
都设置为0,那么该图片会显示在屏幕的左上角。

与此同时,图片的 宽高
也可以一起设置,之前带大家看过,所有的这种小图片都是 105个像素
。
三、引出问题
找到 GameJFrame
游戏的主界面,然后再找到构造方法,再看里面的 initImage方法
,我们是在添加图片的时候,给图片去指定它的位置。
指定位置的时候要注意了,一定要在 把管理容器添加到界面中
之前才可以。

调用 setBounds()
方法,ctrl + p 查看参数,x、y
表示图片的位置,width、height
表示图片的宽高,单位都是像素。
因此位置这里就写 0, 0
,宽高写 105, 105
// 指定图片的位置,调用方法:setBounds
jLabel1.setBounds(0, 0, 105, 105);
你觉得这个代码就行了吗?不知道,打开App,右键运行,来启动一下看下效果是不是跟我们想的一样。
程序运行完毕,你发现它的位置并不在 (0, 0)
。

这是因为在这里其实还有一个小细节。
四、解决问题
右边是一个 JFrame
主窗体界面,在刚刚我们要把一张图片添加到界面中,默认是显示在正中央。
但是我刚刚已经指定了x、y的位置了,它应该显示在左上角,那为什么还是显示在正中央呢?

不着急,听我来跟你慢慢分析。
这个主窗体现在我们可以把它看成是三个部分。
第一个部分:上面的标题;
第二个部分:中间的菜单;
第三个部分:在最下面,它其实还有一个隐藏的容器。
此时这个隐藏的容器它就说话了:JFrame
只是个大的架子,我才是用来装载所有组件的。(图片、文字、按钮、进度条等,我们都可以叫做组件,组件是一个统称)。

我们在代码中,可以通过 getContentPane()
去获取这个隐藏容器。
细节:隐藏的容器不需要我们自己创建对象,因为它是 JFrame对象
里面的东西,当我们创建了 JFrame窗体对象
的时候,它就会出现了,一会会带着大家看源码。
因此我们可以直接通过 get方法
就能获取到这个隐藏容器了,那么我们在添加图片的时候,需要将要显示的图片添加给这个隐藏的容器。
在添加的时候没有什么特殊要求,它会把要添加的图片默认放在正中央。

但如果我不想让你放到正中央呢?就需要将默认的机制给取消。
因此在代码中我们还需要去调用一个方法 setLayout(null)
,这个方法我们可以通过它的名字去猜一猜它的意思。
set
:设置,layout
:布局,null
:没有。因此这个方法的大概意思:将布局设置为 null
,这里的布局指的就是它的排列方式。
因此这个方法的真正意思:我要取消默认的居中方式。
一旦取消了这个居中方式,那就会完全按照我们自己指定的 x、y
的坐标来放置图片了。
五、代码示例
在 GameJFrame类
中的构造方法中,找到 initJFrame
方法,我们需要在初始化界面的时候,就将默认的居中放置给取消。
选中方法 ctrl + b 跟进,跳转到方法中。
private void initJFrame() {
..... // 之前写的代码
// 取消默认的居中方式,只有取消了,才会安装xy轴的形式添加组件
this.setLayout(null);
}
回到 initImage()
方法中,首先我们将图片改为加载 1.jpg
这张图片。
然后在添加的时候,将我们之前添加的代码注释掉,然后使用 this(当前界面的对象)
调用方法 getContentPane()
,获取到 JFrame(界面)
中隐藏的容器,然后再去调用 add方法
,把 jLabel1
添加到隐藏容器中。
// 初始化图片
private void initImage() {
// 创建一个图片 ImageIcon 对象
ImageIcon icon = new ImageIcon("E:\\learning_notes\\JAVA\\code\\basic-code\\puzzlegame\\image\\animal\\animal3\\1.jpg");
// 创建一个 JLabel对象(管理容器)
JLabel jLabel1 = new JLabel(icon);
// 指定图片的位置,调用方法:setBounds
jLabel1.setBounds(0, 0, 105, 105);
// 把管理容器添加到界面中,调用JFrame的add方法
// 添加进去后,默认会放在页面的正中央
// this.add(jLabel1);
this.getContentPane().add(jLabel1);
}
然后重新运行 App
,右键运行,可以发现第一张图片 1.jpg
已经放在左上角了。

六、扩展
在刚刚我们说了,那个隐藏的容器不需要我们自己创建,它是在创建界面对象的时候自动就创建出来了。那我能不能看一看呢?必须是可以的。
首先找到 GameJFrame
的构造方法,它的第一行其实有一个隐藏的 super()
,表示调用父类的空参构造。
ctrl + b 跟进它的父类 JFrame
,ctrl + F12 找到空参构造。
在它的空参构造中,又调用了 frameInit()
方法,这就是说,我们在创建界面对象的时候,Java底层其实也做了很多的初始化动作。
ctrl + b 跟进 frameInit()
方法,此时可以看见Java底层对界面做的初始化。
最终要的是 258行
,setRootPane():设置隐藏容器
。set
:设置;root
:根,其实就是那个隐藏容器;pane
:是隐藏容器的名字 pane
,其实它完整的名字是 panel(面板)
,pane
只是它一个简写名字。
它的参数是 createRootPane():创建一个隐藏的容器
。
选中 createRootPane()
,ctrl + b 跟进。
在这个方法中,它就帮我们去创建了一个对象。

此时我们就知道了,这个隐藏容器的对象不需要我们自己创建。
在我们创建界面 JFrame
对象的时候,在底层,就帮我们自动的去创建了这个隐藏容器。
所以我们在代码中,直接通过 getContentPane()
方法获取出来就行了。