# JInternalFrame
# JDesktopPane
JInternalFrame 與 JFrame 用法完全一樣, 都有 ContentPane, 預設都是 BorderLayout, 但兩者還是有差別的 :
- JFrame 為重量級元件, 是 Swing 的四個最上層容器之一 (另外三個是 JWindow, JApplet 與 JDialog), 是獨立的視窗. 而 JInternalFrame 則為輕量級元件, 不是獨立視窗, 必須依附於四個最上層容器.
- 內部框架是以與平台無關方式實做, 比 JFrame 擁有更大彈性, 我們對 JInternalFrame 擁有較多控制權.
- 內部框架不是視窗, 因此不會觸發視窗事件 (window event), 而是觸發內部框架事件, 但其處理方式與視窗事件幾乎一樣 (使用 InternalFrameListener).
JinternalFrames 相關類別繼承關係如下 :
java.awt.Container
|__ javax.swing.JComponent
| |__ javax.swing.JLayeredPane
| | |__ javax.swing.JDesktopPane
| |__ javax.swing.JInternalFrame
|__ java.awt.Window
|__ java.awt.Frame
|__ javax.swing.JFrame
JInternalFrame 的建構子通式如下 :
JInternalFrame(String title [, boolean resizable
[,boolean closable
[, boolean maximizable
[, boolean iconifiable]]]])
後面四個參數乃選項, 通常全給 true, 分別表示可縮放, 可關閉, 可最大化, 以及可最小化 :
JInternalPane inf=new JInternalPane(“標題”, true, true, true, true);
內部框架的使用方式 :
先建立 JDesktopPane 與 JInternalFrame 物件, 然後用 JDesktopPane 之 add() 方法將內部視窗放進桌面面板即可. 內部框架與 JFrame 一樣, 有各自的內容面板用來擺放元件, 一樣是用 getContentPane() 取得內容面板. 在下列範例中, 我在 JFrame 中放了一個按鈕, 每按一次就新增一個內部框架 :
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class JIF1 implements ActionListener {
JFrame f;
JDesktopPane dp;
int count=0;
public static void main(String argv[]) {
new JIF1();
}
public JIF1() {
//Setup JFrame
JFrame.setDefaultLookAndFeelDecorated(true);
JDialog.setDefaultLookAndFeelDecorated(true);
f=new JFrame("JInternalFrame Test");
f.setSize(400,300);
f.setLocationRelativeTo(null);
Container cp=f.getContentPane();
cp.setLayout(new BorderLayout());
f.setVisible(true);
//Build Elements
JButton newInf=new JButton("新增內部框架");
newInf.addActionListener(this);
cp.add(newInf, BorderLayout.NORTH);
dp=new JDesktopPane();
cp.add(dp);
//Close JFrame
f.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
f.addWindowListener(new WindowHandler(f));
}
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand()=="新增內部框架") {
//Setup JInternalFrame
JInternalFrame inf;
inf=new JInternalFrame("內部框架 " + (++count),true,true,true,true);
inf.setSize(200,100);
inf.setLocation(25*count,25*count);
inf.setVisible(true);
dp.add(inf);
//Build Elements
Container icp=inf.getContentPane();
final JTextArea ta=new JTextArea("Hello World! #" + count);
JButton btn=new JButton("清除內容");
btn.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {ta.setText("");}
});
icp.add(ta,"Center"); //也可用 BorderLayout.CENTER
icp.add(btn,"South");
try {inf.setSelected(true);}
catch (Exception ine) {ine.printStackTrace();}
}
}
}
class WindowHandler extends WindowAdapter {
JFrame f;
public WindowHandler(JFrame f) {this.f=f;}
public void windowClosing(WindowEvent e) {
int result=JOptionPane.showConfirmDialog(f,
"確定要結束程式嗎?",
"確認訊息",
JOptionPane.YES_NO_OPTION,
JOptionPane.WARNING_MESSAGE);
if (result==JOptionPane.YES_OPTION) {System.exit(0);}
}
}
由於 JFrame 與 JInternalFrame 預設都是 BorderLayout, 其實不需要用 setLayout() 方法特別去設定為 BorderLayout. 我在 JFrame 上方放置一個新增內部框架的按鈕, 每按一次就會在 CENTER 位置產生一個內部框架, 利用計數器 count 讓 setLocation() 把內部框架左上角位置下移 25px, 就能顯現層次堆疊效果, 否則全部新增的內部框架將重疊在一起, 感覺不到有新增.
另外 JInternalFrame 也有自己的 ContentPane, 我在每個內部框架產生時, 放一個 JTextArea 在 CENTER, 一個 JButton 在 SOUTH, 而且用內部類別方式為此按鈕註冊一個動作事件監聽器, 按下時清除 JTextArea 內預設的文字.
上面範例沒有處理 JInternalFrame 的事件, 所以關閉時就直接關掉了. JInternalFrame 的事件不是視窗事件, 而是要用 InternalFrameListener 來監聽內部框架事件.
參考 :
# Writing Event Listeners: Examples
參考資料 :
# 精通java swing開發[7]
沒有留言:
張貼留言