【Swing 填坑】JFrame的背景颜色和消失的组件+坐标的范围+ 设置组件大小
记得有人说过Swing的坑多,使用了一个多月的我,这两天在想拖放组件的问
题时遇到了两个坑。
参考: 设置界面背景颜色
http://blog.csdn.net/pc620/article/details/6056507
附: 今天在做鼠标手势的时候,又他妈发现一个坑,看来,哥的人生就是注定来填坑
的。假如我们设置的窗口/界面是new JFrame().setSize(100, 100);那么, 实际上
横纵坐标的取值都是0~99像素
——2017.3/6
1. 背景颜色的坑
你想和其它组件(如按钮)或JPanel容器一样用setBackground()为JFrame
设置背景颜色嘛?好吧,甭捣鼓了。看看下面的示例
1 package demo; 2 3 import javax.swing.*; 4 5 public class MiniMusic { 6 public static void main(String[] args) { 7 new MiniMusic(); 8 } 9 public MiniMusic() { 10 JFrame f = new JFrame(); 11 12 f.add(new JButton("提交")); // 添加按钮 13 14 // 在关闭窗口时结束javaw.exe进程, 释放内存 15 f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 16 f.setLocation(200, 200); 17 f.pack(); // 让JFrame自适应大小, 也就是显示刚好能够容纳按钮的空间 18 f.setVisible(true); 19 } 20 }
一切正常。按钮被添加到JFrame中, 如果没加方位的话, 默认加到窗口的中间
。但是,当我们把JFrame的ContentPane容器隐藏之后,
f.getContentPane().setVisible(false);
看到了吧,一切空白。只是因为我们把Content Pane给设成了不可见。这
说明组件都是加在JFrame的Content Pane容器上。(即f.getContentPane())
也就是说,是不能直接在顶级容器类JFrame上添加组件的。而上面的f.add(),
其实就是f.getContentPane().add(); 所以,如果不想把Content Pane容器隐
藏掉的话,(这样就不能再添加组件了)。正确设置背景颜色的方式应该是
f.getContentPane().setBackground(Color.pink);
2. 消失的组件
这一切都不会发生,如果你在f.setVisible(true);之前就都添加好所有组件
和话。可是,如果你一不小心,比如像下面这样,
【注意: setLayout(null), 也就是绝对定位不受下面示例的影响】
情景1: f.setSize()和f.setVisible(true)顺序正常, 所有组件在setVisible()
之后被添加。(包括声明和初始化组件后再add()或者直接add())。
结果: 只有标签会显示, 其它组件不可见。但标签的add()不能被其它不可见的
组件挡住, 如 JLabel lab = ...; JTextField text = ...; f.add(lab); 这样标签即不可见,
把 f.add(lab); 放前面就OK了。
特例: 如果组件在f.setVisible(true)之前, (可以是f.setSize()之后)被声明并初始化
,则该组件可见。
1 package demo; 2 3 import javax.swing.*; 4 5 public class MiniMusic { 6 public static void main(String[] args) { 7 new MiniMusic(); 8 } 9 public MiniMusic() { 10 JFrame f = new JFrame(); 11 12 // 在关闭窗口时结束javaw.exe进程, 释放内存 13 f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 14 f.setSize(400, 300); 15 f.setVisible(true); 16 f.add("North", new JButton("北风")); // 添加按钮 17 f.add("South", new JButton("南阳")); 18 f.add(new JTextField("请输入内容")); // 添加文本框 19 } 20 }
情景2: 顺序是f.setVisible(true);和f.setSize(); 所有组件的声明和初始
化(或是直接add())都是放在f.setSize()后。
结果: 只有文本框会被隐藏,且它的声明和初始化代码会让在它后面声明和
初始化(或者是直接add())的组件不可见。
特例: 如果文本框的声明和初始化是放在f.setVisible(true)之前, 则所有不
可见的组件都可见。
1 package demo; 2 3 import javax.swing.*; 4 5 public class MiniMusic { 6 public static void main(String[] args) { 7 new MiniMusic(); 8 } 9 public MiniMusic() { 10 JFrame f = new JFrame(); 11 12 // 在关闭窗口时结束javaw.exe进程, 释放内存 13 f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 14 f.setVisible(true); 15 f.setSize(400, 300); // 让JFrame自适应大小, 也就是显示刚好能够容纳按钮的空间 16 f.add("North", new JButton("北风")); // 添加按钮 17 f.add("South", new JButton("南阳")); 18 f.add(new JTextField("请输入内容")); // 添加文本框 19 } 20 }
这里面只有文本框被隐藏了。那么,如果我们调换文本框和南边的按钮顺序呢?
1 // 其它内容不变,调换文本框和位于南边的按钮的顺序 2 f.add(new JTextField("请输入内容")); // 添加文本 3 f.add("South", new JButton("南阳"));
这下连南边的按钮也消失了。这是为什么呢?So sorry! 这个坑,我也不知道
原因。写在这里只是想提醒自己和大家。尽量把要添加的组件都放在JFrame容器的
fsetSize()和f.setVisible(true); 前面,要是实在得放在后面的话, 在所有组件都
添加完后加上必杀技:
f.setVisible(true);
或 f.setValidate();
或 f.setSize() / f.pack();
最后一句重新绘制界面大小, 效果和我们直接拉伸窗口, 组件就会显示出来一样, 其
实就相当于再刷新一次, f.pack()同理。所以要和原来的大小不一样才行, 所以设置的
长和宽不能和原来完全一样。(至少要有一个改变的.)
—— 2017/3/3
3. setBounds()和setLocation()不要乱用
今天,又有坑出现了,真不幸又被我撞到了,就是当setBounds()或者setLocatin()
用在三大布局管理器时,对FlowLayout和BoxLayout都是无效的, 但是若用在边界管理器,
那事就多了。
因为在BorderLayout管理器的管理下,所有组件或者容器必须放在东南西北中的其中
一个地方,所以如果被你用setBounds()设置的那个组件所在的方位(add()时设置的那个方
位)刚好被其它组件占据了, 那么这条语句才有用,别以为这样就值得高兴。更大的麻烦还在
后面。
1 JFrame f = new JFrame(); 2 3 JButton b = new JButton("按钮"); 4 b.setBounds(300, 300, 80, 20); 5 6 // 像这样按钮的方位刚好被其它组件占去的话,上面绝对定位设置的坐标才会管用 7 f.add(b); 8 f.add(new JButton("中间位置的按钮")); 9 10 f.setSize(400, 400); 11 f.setVisible(true);
如果该按钮是被标签挡住了,那真是不幸中的万幸,因为按钮会覆盖在标签上面; 如果是
被文本框挡住了,那真是棋差一招, 被文本框挡住的话,就需要用鼠标移动到按钮上面,这样
它自己就会显示出来了。如果你拉伸窗口的话,按钮一会消失,一会又出现。能力有限,无法
解释; 如果是被另一个更大的按钮挡住的话, I'm so sorry, 只要鼠标一离开小按钮, 它又会被
挡住。
所以千万不要在不是绝对定位的时候使用setBounds()或setLocation();
只有取消使用布局管理器的时候,f.setLayout(null); 才去用这两种语句
4. 在BorderLayout和FlowLayout布局中setSize()无法对组件发挥作用
这个我也解释不了
解决方法: 使用setPreferredSize(new Dimension(int width, int height)); 设置首选
大小, 当然了, 对于边界布局和流式布局, 就算能改变大小, 也只是改变高度而已。
5. BoxLayout布局只适用于JPanel, 不能用于JFrame, 而三大布局管理器都能用于JPanel
别问我了,天知道。
——2017/3/7