# http://docs.oracle.com/javase/7/docs/api/
JSplitPane 繼承自 JComponent, 其 API 如下 :
# http://docs.oracle.com/javase/7/docs/api/javax/swing/JSplitPane.html
JSplitPane 有五個建構子如下 :
- JSplitPane() :
預設為水平分割, 各放一個按鈕. - JSplitPane(int oreintation) :
傳入一個整數指定分割方式, 有兩個值 :
JSplitPane.HORIZONTAL_SPLIT (水平分割=)
JSplitPane.VERTICAL_SPLIT (垂直分割=) - JSplitPane(int oreintation, boolean continousLayout) :
傳入的第二參數為布林值, true 表示移動分割邊框調整分割區域大小時, 各區域內的元件會同時調整大小, false 表示移動時元件大小不變直到停止移動時才改變. - JSplitPane(int oreintation, Component a, Component b) :
依上下 (垂直) 或左右 (水平) 順序將 a, b 兩元件放入分割區域中. - JSplitPane(int oreintation, boolean continousLayout, Component a, Component b) :
首先測試無參數建構子, 預設是水平分割, Swing 會自動在左右分割各放置一個按鈕, 範例如下 :
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class JSplitPane1 implements ActionListener {
JFrame f;
public static void main(String argv[]) {
new JSplitPane1();
}
public JSplitPane1() {
//Setup JFrame
JFrame.setDefaultLookAndFeelDecorated(true);
JDialog.setDefaultLookAndFeelDecorated(true);
f=new JFrame("JSplitPane Test");
f.setSize(400,300);
f.setLocationRelativeTo(null);
Container cp=f.getContentPane();
//cp.setLayout(null);
//Build Elements
JSplitPane split=new JSplitPane();
cp.add(split,BorderLayout.CENTER);
f.setVisible(true); //must be the last
String msg="getDividerLocation()=" +
split.getDividerLocation() + "\n" +
"getDividerSize()=" +
split.getDividerLocation() + "\n" +
"getMaximumDividerLocation()=" +
split.getMaximumDividerLocation() + "\n" +
"getMinimumDividerLocation()=" +
split.getMinimumDividerLocation() + "\n" +
"getOrientation()=" +
split.getOrientation() + "\n";
JOptionPane.showMessageDialog(f,msg);
//f.pack(); //for using Layout Mgr.
//Close JFrame
f.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
f.addWindowListener(new WindowHandler(f));
}
public void actionPerformed(ActionEvent e) {
//if (e.getSource()==id) {}
}
}
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);}
}
}
此例中我同時測試 JSplitPane 的七個方法 :
- int getDividerLocation() : 傳回從左方或上方算起的分割線位置 (px)
- int getDividerSize() : 傳回分割線粗細 (px)
- int getMaximumDividerLocation() : 傳回可設定的最大分割線位置 (px)
- int getMinimumDividerLocation() : 傳回可設定的最小分割線位置 (px)
- int getOrientation() : 傳回分割方向, 其值如下 :
JSplitPane.HORIZONTAL_SPLIT (=1)
JSplitPane.VERTICAL_SPLIT (=0) - boolean isContinuousLayout() : 傳回是否可連續調整元件大小
- boolean isOneTouchExpandable() : 傳回是否可單鍵展開
- setDividerLocation()
- setDividerSize()
- setOrientation()
- setOneTouchExpandable()
- setContinuousLayout()
- setTopComponent()
- setBottomComponent()
- setLeftComponent()
- setRightComponent()
如果要在移動 JSplitPane 的分割線時即時將分隔線位置顯示在 JLabel 上該怎麼做? 我參考了下面這篇文章 :
# Listening for JSplitPane Property Changes
可知移動 JSplitPane 的分割線會觸發 Property Change 事件, 此事件由 PropertyChangeEvent 類別負責處理, 而其事件監聽器為 PropertyChangeListener 介面, 其 API 參考 :
# PropertyChangeEvent
# PropertyChangeListener
此二者均屬於 java.beans 套件, 所以必須另行匯入 :
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
我們的類別必須實作 PropertyChangeListener 介面, 覆寫 propertyChange() 方法以監聽 JSplitPane 分隔線的移動動作. 當其移動時, PropertyChangeEvent 物件會記錄 JSplitPane 的 LAST_DIVIDER_LOCATION_PROPERTY 屬性, 只要呼叫事件物件的 getPropertyName(), 若傳回字串與此屬性相同, 就去更新 JLabel 的顯示文字, 動態呈現分隔線位置, 範例程式如下 :
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
public class JSplitPane2 implements PropertyChangeListener {
JFrame f;
JSplitPane split;
JLabel lb;
public static void main(String argv[]) {
new JSplitPane2();
}
public JSplitPane2() {
//Setup JFrame
JFrame.setDefaultLookAndFeelDecorated(true);
JDialog.setDefaultLookAndFeelDecorated(true);
f=new JFrame("JSplitPane Test");
f.setSize(400,300);
f.setLocationRelativeTo(null);
Container cp=f.getContentPane();
//Build Elements
split=new JSplitPane();
split.setOrientation(JSplitPane.VERTICAL_SPLIT);
split.setDividerLocation(0.5);
split.setDividerSize(30);
split.setOneTouchExpandable(true);
split.setContinuousLayout(true);
lb=new JLabel("Divider Location=");
split.setTopComponent(lb);
cp.add(split,BorderLayout.CENTER);
split.addPropertyChangeListener(this);
f.setVisible(true); //must be the last
//Close JFrame
f.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
f.addWindowListener(new WindowHandler(f));
}
public void propertyChange(PropertyChangeEvent e) {
String property=e.getPropertyName();
if (property.equals(JSplitPane.LAST_DIVIDER_LOCATION_PROPERTY)) {
lb.setText("Divider Location=" + split.getDividerLocation());
}
}
}
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);}
}
}
此例中, 我們將視窗改成垂直分割, 並將一個 JLabel 放到上方區域中, 當移動分隔線時, JLabel 會不斷更新顯示分隔線的位置. 注意, 因為要在事件處理函式中存取 JSplitPane 與 JLabel 物件, 故而需宣告為類別成員. 其次, setOneTouchExpandable(true) 會在分隔線上出現兩個三角形小按鈕, 按一下就會朝指定方向擴展區域至最大. 而 setContinuousLayout(true) 則會在移動分隔線時, 個區域內的元件會同時調整大小. 如果設為 false, 則移動時不會同步調整元件大小, 而是在移動停止時才調整. 當視窗中元件數目非常多時, 最好設為 false, 以免效能降低.
接下來要來測試較複雜的分割面板, 例如在上面的垂直分割中, 上方與下方區域再做水平分割, 程式碼如下 :
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class JSplitPane3 {
JFrame f;
public static void main(String argv[]) {
new JSplitPane3();
}
public JSplitPane3() {
//Setup JFrame
JFrame.setDefaultLookAndFeelDecorated(true);
JDialog.setDefaultLookAndFeelDecorated(true);
f=new JFrame("JSplitPane Test");
f.setSize(400,300);
f.setLocationRelativeTo(null);
Container cp=f.getContentPane();
//cp.setLayout(null);
//Build Elements
JLabel topLeft=new JLabel("左上",JLabel.CENTER);
JLabel topRight=new JLabel("右上",JLabel.CENTER);
JSplitPane top=new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
true,
topLeft,
topRight);
top.setOneTouchExpandable(true);
top.setDividerLocation(200);
JLabel bottomLeft=new JLabel("左下",JLabel.CENTER);
JLabel bottomRight=new JLabel("右下",JLabel.CENTER);
JSplitPane bottom=new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
true,
bottomLeft,
bottomRight);
bottom.setOneTouchExpandable(true);
bottom.setDividerLocation(200);
JSplitPane split=new JSplitPane(JSplitPane.VERTICAL_SPLIT,
true,
top,
bottom);
split.setOneTouchExpandable(true);
split.setDividerLocation(120);
cp.add(split,BorderLayout.CENTER);
f.setVisible(true); //must be the last
//Close JFrame
f.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
f.addWindowListener(new WindowHandler(f));
}
}
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);}
}
}
此例中利用套疊將視窗分割成四部份, 先各自製作了兩個水平分割面板, 再將它們當作元件放進外層的垂直分割面板. 當然也可以先製作兩個垂直分割面板, 再放進一個水平分割面板中, 效果一樣. 注意, 這裡分割線的位置設定採用 px 單位, 我試過用比例 (0.0~1.0) 卻無效, why? 再研究.
最後來測試一個較實際的應用-圖片瀏覽程式, 製作一個水平分割面板, 左邊用 JList 列出圖檔項目, 右邊顯示所選之圖檔, 因為要處理 JList 的選項動作, 故必須實作 ListSelectionListener 介面,程式碼如下 :
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class JSplitPane4 implements ListSelectionListener {
JFrame f;
JLabel img;
String[] pictures;
JSplitPane jsp;
public static void main(String argv[]) {
new JSplitPane4();
}
public JSplitPane4() {
//Setup JFrame
JFrame.setDefaultLookAndFeelDecorated(true);
JDialog.setDefaultLookAndFeelDecorated(true);
f=new JFrame("JSplitPane Test");
f.setSize(400,300);
f.setLocationRelativeTo(null);
Container cp=f.getContentPane();
//cp.setLayout(null);
//Build Elements
pictures=new String[]{"cat.jpg","family.jpg"};
JList
list.addListSelectionListener(this);
jsp=new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
jsp.setDividerLocation(100);
jsp.setLeftComponent(new JScrollPane(list));
img=new JLabel(new ImageIcon("cat.jpg"));
jsp.setRightComponent(new JScrollPane(img));
cp.add(jsp,BorderLayout.CENTER);
f.setVisible(true); //must be the last
//Close JFrame
f.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
f.addWindowListener(new WindowHandler(f));
}
public void valueChanged(ListSelectionEvent e) {
JList list=(JList)e.getSource();
img.setIcon(new ImageIcon(pictures[list.getSelectedIndex()]));
jsp.setDividerLocation(100); //避免分割線位置變化
jsp.setRightComponent(new JScrollPane(img));
}
}
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);}
}
}
此例中, 左方分割的 JList 與右方分割的 JLabel 都用 JScrollPane 包起來, 再放進 JSplitPane 中, 這樣就會在內容長度或寬度超過時自動出現捲軸. 而實作 ListSelectionListener 介面只要覆寫 valueChanged() 方法, 利用呼叫 JList 的 getSelectedIndex() 方法取得所選擇之選項索引, 取得圖檔名稱後更新右方分割中 JLabel 的圖檔. 因為要在事件處理方法中存取 JLabel, 圖檔名稱陣列, 以及 JSplitPane 物件, 故將此三者宣告為類別成員.
沒有留言 :
張貼留言