是的,最外面的window的大小是包括标题栏在内的,而且标题栏是native修饰的,高度不定。(windows下和linux下不同,windows xp和2000下都不同)
计算内置子组件的位置不要用window作为相对坐标的参考系,用contentpane,就是Container.getContentPane()得到的那个,对于最外层window来说,这个就是剥掉外层修饰可以放子组件的最大范围了,就是最高不能高过contentpane的y,最左左不过contentpane的x。
补充:
由于对于一定的native的修饰,比如标题栏的高度之类是固定的,所以最外层window的size定下来后,contentpane理论上也是固定下来的。但是contentpane其实作为window的一个子组件,其size的计算不是在构造时候完成的,也就是下面这段code里得到的contentpane的size还是(0,0)
JFrame aFrame = new JFrame();
aFrame.setSize(100, 100);
Container contentPane = aFrame.getContentPane();
两种解决方法:
1 最常用的方法布局时利用各种现成的LayoutManager,而不推荐自己去从头写代码来计算内部组件的大小。(SUN的一些现成的一些LayoutManager已经基本可以满足要求,还有一些第三方的LayoutManager可以做进一步补充,自己也可以在其基础上重载定制,但实用中几乎没有必要)。这样只要告诉LayoutManager各个内部组件相对的位置和占有的大小比例关系即可。
2 非要自己来计算确切的位置大小也不是不可以,但除非所有组件的大小都由你来确定,此外一般不在构造的时候确定,原因就在于一开始的问题,window大小确定后,默认布局计算算法是lazy的,这是contentPane的大小还是0,直到必须计算的时候才确定。所以要确保自己写的计算位置和大小的代码也要在parent的布局计算完成后才能调用。比如计算contentPane里面子组件位置代码可以让其被contentPane的doLayout()回调。当然你一般不想重载contentPane,那么就在其里面直接套一层JPanel好了,重载该JPanel的doLayout(). 这种方法不推荐,不如把算法放在LayoutManager更能使得逻辑耦合度降低。
针对补充的再补充:方法一就是用LayoutManager,方法二就是对某个container整个跳过或在LayoutManager调整之后再进行附加调整,通过重载Container.doLayout()在该方法内直接通过计算setBounds。
关于"针对补充的再补充"的再三补充:重载JDK Container里的doLayout(),在该函数内,可以完全用自己的计算代码,也可以调用过super之后再用自己的算法调整,super就是调用默认LayoutManager(设成null就不动作)。所以super之后(不能在之前)的定制调整会是能够覆盖默认布局效果的。在Container里调整的是子componet。
不明白为何不用方法一中逻辑清晰的方法,非要折腾这个呢?