首先說一下JFrame組件的構成,JFrame有一個唯一的子容器JRootPane,
一下是api中關于JRootPane的注解
JRootpane
由一個 glassPane
和一個可選的 menuBar
以及一個 contentPane
組成。(JLayeredPane
負責管理 menuBar
和 contentPane
。)glassPane
位于所有窗格之上,以便能夠截取鼠標移動。由于 glassPane
(與 contentPane
類似)可以是一個任意的組件,也可以設置 glassPane
來進行繪制。這樣 glassPane
上的線條和圖像可涵蓋其下的窗體,不受其邊界的限制。
盡管 menuBar
組件為可選,但 layeredPane
、contentPane
和 glassPane
總是存在的。試圖將它們設置為 null
將生成異常。
要將組件添加到 JRootPane
(可選的菜單欄除外),您可以將對象添加到 JRootPane
的 contentPane
,如下所示:
rootPane.getContentPane().add(child);
可用同樣的方法設置布局管理器、移除組件以及列出子級等。所有這些方法都是在 contentPane
上而不是 JRootPane
上調用的。
注:contentPane
的默認布局管理器是BorderLayout
管理器。但是,JRootPane
使用一個自定義的LayoutManager
。所以,如果您希望更改已添加到JRootPane
中的組件的布局管理器,一定要確保使用如下代碼:rootPane.getContentPane().setLayout(new BoxLayout());
如果已在 JRootPane
上設置了 JMenuBar
組件,它將沿窗體的上邊緣放置。contentPane
的位置和大小將進行調整以填充剩余的區域。(JMenuBar
和 contentPane
被添加到位于 JLayeredPane.FRAME_CONTENT_LAYER
層的 layeredPane
組件中。)
layeredPane
是 JRootPane
中所有子級的父級,既是菜單的直接父級,又是添加到 contentPane
中的所有組件的祖父級。它是 JLayeredPane
的實例,提供在若干層上添加組件的能力。在處理彈出菜單、對話框以及拖動時,即要求將組件置于窗格中所有其它組件之上的情況下,此功能非常有用。
glassPane
位于 JRootPane
中所有其它組件之上。這為在所有其它組件上繪圖和截取鼠標事件提供了方便,這對拖動和繪圖都非常有用。開發人員可在 glassPane
上使用 setVisible
控制 glassPane
在所有其它子級上面顯示的時間。默認情況下,glassPane
為不可見。
JRootPane
所使用的自定義 LayoutManager
可確保:
glassPane
填充了JRootPane
的整個可查看區域(邊界 - insets)。layeredPane
填充了JRootPane
的整個可查看區域。(邊界 - insets)menuBar
位于layeredPane
的上邊緣。contentPane
填充了整個可查看區域,減去menuBar
(如果有)。
JRootPane
視圖層次結構中的任何其它視圖均忽略。
如果您替換 JRootPane
的 LayoutManager
,您將負責管理所有這些視圖。所以通常情況下,應該確保更改的是 contentPane
的布局管理器,而不是 JRootPane
自身的布局管理器。
Swing 的繪制架構要求在所有其它組件之上的包含層次結構中有一個不透明的 JComponent
。這通常通過使用內容窗格來實現。如果要替換內容窗格,建議使用 setOpaque(true)
將內容窗格設置為不透明。另外,如果內容窗格重寫 paintComponent
,還需要在 paintComponent
中用不透明顏色將背景完全填充。
JLayeredPane
為 JFC/Swing 容器添加了深度,允許組件在需要時互相重疊。Integer
對象指定容器中每個組件的深度,其中編號較高的組件位于其他組件之上。有關面向任務的文檔和使用分層窗格的示例,請參閱《The Java Tutorial》中的 How to Use a Layered Pane 一節。
|
JLayeredPane
將該深度范圍分成幾個不同的層。將組件放入相應的層,這樣更容易確保組件正確地重疊,而不必擔心為具體的深度指定編號:
- DEFAULT_LAYER
- 大多數組件位于的標準層。這是最底層。
- PALETTE_LAYER
- 調色板層位于默認層之上。它們對于浮動工具欄和調色板很有用,因此可以位于其他組件之上。
- MODAL_LAYER
- 該層用于模式對話框。它們將出現在容器中所有工具欄、調色板或標準組件的上面。
- POPUP_LAYER
- 彈出層顯示在對話框的上面。這樣,與組合框、工具提示和其他幫助文本關聯的彈出式窗口將出現在組件、調色板或生成它們的對話框之上。
- DRAG_LAYER
- 拖動一個組件時,將該組件重分配到拖動層可確保將其定位在容器中的其他所有組件之上。完成拖動后,可將該組件重分配到其正常層。
可以使用 JLayeredPane
的方法 moveToFront(Component)
、moveToBack(Component)
和 setPosition
在組件所在層中對其進行重定位。還可以使用 setLayer
方法更改該組件的當前層。
詳細信息
JLayeredPane
以類似 Container
的方式管理其子級列表,但允許在其內部定義多個層。對同一層中子級的管理就像普通的 Container
對象一樣,但添加的功能是,當子組件重疊時,高層中的子組件顯示在低層中的子組件之上。
每一層都是一個不同的整數。可以在調用 add 的過程中通過傳遞 Integer
對象,從而在 Component
上設置 layer 屬性。
例如:
layeredPane.add(child, JLayeredPane.DEFAULT_LAYER); 或者 layeredPane.add(child, new Integer(10));
還可以通過在 JLayeredPane
上進行如下調用在 Component 上設置 layer 屬性:
layeredPaneParent.setLayer(child, 10)
JLayeredPane
是該 Component 的父組件。應該將子組件添加到父組件之前 設置 layer 屬性。
編號較高的層顯示在編號較低的層之上。因此,對于每個組件,使用其層編號和字母即可,有代表性的列表順序如下所示:
5a, 5b, 5c, 2a, 2b, 2c, 1a
其中最左邊的組件最接近顯示區的頂部。
可以通過調用 moveToFront
或 moveToBack
將組件移入到其所在層的頂部或底部位置。
還可以直接指定某層中組件的位置。有效的位置范圍是從 0 到該層中組件數減一所得的值。值 -1 指示最底層位置。值 0 指示最頂層位置。與層的編號不同,較高的位置值顯示在較低 處。
注: 此序列(通過 java.awt.Container 定義)與層的編號序列相反。可是通常使用的是moveToFront
、moveToBack
和setLayer
方法。
以下是使用方法 add(Component, layer, position) 的一些示例:調用 add(5x, 5, -1) 得到:
5a, 5b, 5c, 5x, 2a, 2b, 2c, 1a
調用 add(5z, 5, 2) 得到:
5a, 5b, 5z, 5c, 5x, 2a, 2b, 2c, 1a
調用 add(3a, 3, 7) 得到:
5a, 5b, 5z, 5c, 5x, 3a, 2a, 2b, 2c, 1a
使用正常的 paint/event 機制會使 1a 出現在底部,5a 出現在所有其他組件之上。
注: 這些層只是一個邏輯構造,LayoutManager 將影響此容器的所有子組件,而不管其層設置如何。
下面是一個使用layeredpane的示例
*
* @author: zhangtao
* msn: zht_dream@hotmail.com
* mail: zht_dream@hotmail.com
*/
public class InternalFrameTest extends JFrame {
public static void main(String[] args) {
InternalFrameTest test = new InternalFrameTest();
test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
test.setSize(500, 400);
test.setLocationRelativeTo(null);
test.setVisible(true);
}
public InternalFrameTest() {
JPanel panel = new JPanel();
for (int i = 0; i < 10; i++) {
JButton button = new JButton(i + "");
panel.add(button);
}
this.setContentPane(panel);
JPanel controlPanel = createControlPanel(this.getContentPane());
JInternalFrame frame = new JInternalFrame();
frame.getContentPane().add(controlPanel);
frame.putClientProperty("JInternalFrame.isPalette", Boolean.valueOf(true));
frame.setTitle("control");
frame.pack();
frame.setLocation(30, 30);
frame.setVisible(true);
this.getLayeredPane().add(frame, 0);
}
public JPanel createControlPanel(final Container parent) {
JPanel panel = new JPanel(new GridLayout(3, 1, 2, 2));
final Color color = parent.getBackground();
JPanel panel1 = new JPanel(new FlowLayout());
panel1.add(new JLabel("r"));
final JSlider sliderRed = new JSlider(0, 255);
sliderRed.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
parent.setBackground(new Color(sliderRed.getValue(), color.getGreen(), color.getBlue()));
}
});
sliderRed.setValue(color.getRed());
panel1.add(sliderRed);
JPanel panel2 = new JPanel(new FlowLayout());
panel2.add(new JLabel("g"));
final JSlider sliderGreen = new JSlider(0, 255);
sliderGreen.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
parent.setBackground(new Color(color.getRed(), sliderGreen.getValue(), color.getBlue()));
}
});
sliderGreen.setValue(color.getGreen());
panel2.add(sliderGreen);
JPanel panel3 = new JPanel(new FlowLayout());
panel3.add(new JLabel("b"));
final JSlider sliderBlue = new JSlider(0, 255);
sliderBlue.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
parent.setBackground(new Color(color.getRed(), color.getGreen(), sliderBlue.getValue()));
}
});
sliderBlue.setValue(color.getBlue());
panel3.add(sliderBlue);
panel.add(panel1);
panel.add(panel2);
panel.add(panel3);
return panel;
}
}