2014年5月20日 星期二

Java Swing 測試 : 捲軸面板 JScrollPane

捲軸面板 JScrollPane 類別是用來捲動視窗的, 當 GUI 容器元件的內容 (例如圖檔) 大於視窗時, 只能看到局部的內容, 無法看到完整的全貌. 例如下面範例中, 有一張解析度為 640*430 的貓咪圖片, 如果做成 JLabel 再直接放入內容面板中, 因為 JFrame 大小設為 400*300, 執行後只能看到局部圖片 :

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

public class JScrollPane1 implements ActionListener {
  JFrame f;
  public static void main(String argv[]) {
    new JScrollPane1();
    }
  public JScrollPane1() {
    //Setup JFrame
    JFrame.setDefaultLookAndFeelDecorated(true);
    JDialog.setDefaultLookAndFeelDecorated(true);
    f=new JFrame("JFrame Test");
    f.setSize(400,300);
    f.setLocationRelativeTo(null);
    Container cp=f.getContentPane();
    //cp.setLayout(null); //不要自行排版, 用預設 BorderLayout

    //Build Elements
    JLabel picture=new JLabel(new ImageIcon("cat.jpg"));  //內容為圖片之 JLabel
    cp.add(picture,BorderLayout.CENTER);  //JLabel 直接放入內容面板
    f.setVisible(true);

    //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);}
    }  
  }
小時候天真無邪的樣子

可見只有局部圖片能顯示於 JFrame 視窗中, 當然, 只要調整 JFrame 大小就可以看到整個圖片了, 但如果 JFrame 設定成不可調整呢? 或者圖片很大, 即使 JFrame 放到最大仍然小於圖檔大小, 那就無論如何也無法看到全貌了. 這時只要使用 JScrollPane 的建構子, 將 JLable 先放進 JScrollPane, 再放進內容面板即可 :

JScrollPane(Component view)

如下列範例所示 :

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

public class JScrollPane2 implements ActionListener {
  JFrame f;
  public static void main(String argv[]) {
    new JScrollPane2(); 
    }
  public JScrollPane2() {
    //Setup JFrame
    JFrame.setDefaultLookAndFeelDecorated(true);
    JDialog.setDefaultLookAndFeelDecorated(true);
    f=new JFrame("JScrollPane Test");
    f.setSize(400,300);
    f.setLocationRelativeTo(null);
    Container cp=f.getContentPane();
    //cp.setLayout(null);

    //Build Elements
    JLabel picture=new JLabel(new ImageIcon("cat.jpg"));
    JScrollPane jsp=new JScrollPane(picture);   //JLabel 放入 JScrollPane
    cp.add(jsp,BorderLayout.CENTER);
    f.setVisible(true);

    //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);}
    }   
  }

可見當圖片大小大於視窗容器時, 就會自動出現捲動軸.

JScrollPane 類別主要是由 JViewPort 與 JScrollBar 兩個物件實體組成 (還有標題與轉角等元件), JViewPort 是容器, 用來裝要呈現的元件內容, 後者是用在當內容比 JViewPort 容器還大時, 在右邊或底邊裝上捲軸以便使用者捲動內容. 當移動捲軸時, JScrollPane 會自動處理捲軸事件來移動視圖, 我們不需要特別去處理.

從建構子可知, JScrollPane 面板只能放一個元件, 而且它有自己的版面管理員, 我們無法改變. 如果要放多個元件, 可以先放到 JPanel 中, 可指定所要的版面管理員, 再把 JPanel 放進 JScrollPane 即可.

其 API 參考 :

http://docs.oracle.com/javase/7/docs/api/
http://docs.oracle.com/javase/7/docs/api/javax/swing/JScrollPane.html

產生捲軸面板是利用其建構子, 上面範例所使用的建構子是只有一個傳入參數, 即要顯示的元件 JLabel, 我們也可以先用無參數建構子 JScrollPane(), 然後再呼叫 setViewportView() 方法設定 JViewport 的內容, 如下範例所示 :

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

public class JScrollPane3 implements ActionListener {
  JFrame f;
  public static void main(String argv[]) {
    new JScrollPane3(); 
    }
  public JScrollPane3() {
    //Setup JFrame
    JFrame.setDefaultLookAndFeelDecorated(true);
    JDialog.setDefaultLookAndFeelDecorated(true);
    f=new JFrame("JScrollPane Test");
    f.setSize(400,300);
    f.setLocationRelativeTo(null);
    Container cp=f.getContentPane();
    //cp.setLayout(null);

    //Build Elements
    JLabel picture=new JLabel(new ImageIcon("cat.jpg"));
    JScrollPane jsp=new JScrollPane();  //先呼叫無參數建構子
    jsp.setViewportView(picture);  //再將 JLabel 放入 viewport
    cp.add(jsp,BorderLayout.CENTER);
    f.setVisible(true);

    //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);}
    }   
  }

除了上述兩個建構子外, JScrollPane 還有兩個建構子 :

JScrollPane(Component view, int vsbPolicy, int hsbPolicy)
JScrollPane(int vsbPolicy, int hsbPolicy)

其中 hsbPolicy 參數水平捲軸的顯示政策, 其值如下 :
  1. JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS(=32)
  2. JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED(=31, 預設)
  3. JScrollPane.HORIZONTAL_SCROLLBAR_NEVER(=30)
而 vsbPolicy 參數為垂直捲軸的顯示政策, 其值如下 :
  1. JScrollPane.VERTICAL_SCROLLBAR_ALWAYS(=22)
  2. JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED(=21, 預設)
  3. JScrollPane.VERTICAL_SCROLLBAR_NEVER(=20)
在下面範例中, 我使用了六個按鈕來分別控制垂直水平共 6 個捲軸政策 :

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

public class JScrollPane4 implements ActionListener {
  JFrame f;
  JScrollPane jsp;
  public static void main(String argv[]) {
    new JScrollPane4();
    }
  public JScrollPane4() {
    //Setup JFrame
    JFrame.setDefaultLookAndFeelDecorated(true);
    JDialog.setDefaultLookAndFeelDecorated(true);
    f=new JFrame("JScrollPane Test");
    f.setSize(400,300);
    f.setLocationRelativeTo(null);
    Container cp=f.getContentPane();
    //cp.setLayout(null);

    //Build Elements
    JPanel panel=new JPanel(new GridLayout(6,1));
    JButton btn=new JButton("顯示垂直捲軸");
    btn.addActionListener(this);
    panel.add(btn);
    btn=new JButton("不顯示垂直捲軸");
    btn.addActionListener(this);
    panel.add(btn);
    btn=new JButton("需要時顯示垂直捲軸");
    btn.addActionListener(this);
    panel.add(btn);
    btn=new JButton("顯示水平捲軸");
    btn.addActionListener(this);
    panel.add(btn);
    btn=new JButton("不顯示水平捲軸");
    btn.addActionListener(this);
    panel.add(btn);
    btn=new JButton("需要時顯示水平捲軸");
    btn.addActionListener(this);
    panel.add(btn);
    cp.add(panel,BorderLayout.WEST); //JPanel 放在左方
    JLabel picture=new JLabel(img);
    jsp=new JScrollPane(picture); //JLabel 放入 JScrollPane
    cp.add(jsp,BorderLayout.CENTER); //JScrollPane 放在中央
    f.setVisible(true);

    //Close JFrame      
    f.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
    f.addWindowListener(new WindowHandler(f));
    }
  public void actionPerformed(ActionEvent e) {
    String cmd=e.getActionCommand();
    if (cmd.equals("顯示垂直捲軸")) {
      int policy=JScrollPane.VERTICAL_SCROLLBAR_ALWAYS;
      jsp.setVerticalScrollBarPolicy(policy);
      }
    if (cmd.equals("不顯示垂直捲軸")) {
      int policy=JScrollPane.VERTICAL_SCROLLBAR_NEVER;
      jsp.setVerticalScrollBarPolicy(policy);
      }
    if (cmd.equals("需要時顯示垂直捲軸")) {
      int policy=JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED;
      jsp.setVerticalScrollBarPolicy(policy);
      }
    if (cmd.equals("顯示水平捲軸")) {
      int policy=JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS;
      jsp.setHorizontalScrollBarPolicy(policy);
      }
    if (cmd.equals("不顯示水平捲軸")) {
      int policy=JScrollPane.HORIZONTAL_SCROLLBAR_NEVER;
      jsp.setHorizontalScrollBarPolicy(policy);
      }
    if (cmd.equals("需要時顯示水平捲軸")) {
      int policy=JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED;
      jsp.setHorizontalScrollBarPolicy(policy);
      }
    jsp.revalidate(); //重整捲軸面板
    }
  }
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);}
    }  
  }

此例中六個按鈕都註冊了動作事件, 放進 GridLayout 的 JPanel 中, 然後呼叫 JScrollPane 的 setVerticalScrollBarPolicy() 或 setHorizontalScrollBarPolicy() 方法去設定捲軸政策, 由於要在 actionPerform() 方法中存取 JScrollPane 物件, 因此要將其宣告為類別成員. 要注意的是, 更改了捲軸政策後, 必須呼叫 revalidate() 方法才會生效, 此方法繼承自 JComponent 類別.

JScrollPane 除了 JViewport 與 JScrollBar 物件外, 還包括左方的列標頭 (row header), 上方的欄標頭 (column header), 以及四個邊角. 其架構如下 (取自 Java 文件) :


現在就來測試如何加上列標題與欄標題, 最常用的就是加上尺規. 根據下列 API 文件的說明, 需要下載 Rule.java 這個類別來產生尺規 :

Using Swing Components: Examples
http://docs.oracle.com/javase/tutorial/uiswing/components/scrollpane.html

但是這個 Rule.java 必須加以修改, 拿掉第一行的 package 宣告, 存檔後編譯即可. 然後就可以建立水平與垂直的 Rule 物件, 並利用 setColumnHeaderView() 與 setRowHeaderView() 方法將其加入 JScrollPane 中, 如下列範例所示 :

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

public class JScrollPane5 implements ActionListener {
  JFrame f;
  JScrollPane jsp;
  public static void main(String argv[]) {
    new JScrollPane5();
    }
  public JScrollPane5() {
    //Setup JFrame
    JFrame.setDefaultLookAndFeelDecorated(true);
    JDialog.setDefaultLookAndFeelDecorated(true);
    f=new JFrame("JScrollPane Test");
    f.setSize(400,300);
    f.setLocationRelativeTo(null);
    Container cp=f.getContentPane();
    //cp.setLayout(null);

    //Build Elements
    ImageIcon img=new ImageIcon("cat.jpg");
    JLabel picture=new JLabel(img);
    jsp=new JScrollPane(picture); //JLabel 放入 JScrollPane
    jsp.setPreferredSize(new Dimension(400, 300));
    Rule columnView=new Rule(Rule.HORIZONTAL, true); //建立欄尺規
    Rule rowView=new Rule(Rule.VERTICAL, true); //建立列尺規
    columnView.setPreferredWidth(img.getIconWidth()); //設定欄尺規寬度
    rowView.setPreferredHeight(img.getIconHeight()); //設定列尺規高度
    jsp.setColumnHeaderView(columnView); //加上欄尺規
    jsp.setRowHeaderView(rowView); //加上列尺規
    cp.add(jsp,BorderLayout.CENTER); //JScrollPane 放在中央
    f.setVisible(true);

    //Close JFrame    
    f.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
    f.addWindowListener(new WindowHandler(f));
    }
  public void actionPerformed(ActionEvent e) {
    String cmd=e.getActionCommand();
    }
  }
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);}
    }
  }

在此例中, 使用 ImageIcon 的 getIconWidth() 與 getIconHeight() 分別取得圖片的寬與高, 以便設定欄尺規的寬度與列尺規的高度, 這是必要的, 否則尺規不會顯現. 這個尺規預設是以公分為單位的, 在 Rule.java 類別中, setIsMetric() 方法會呼叫 setIncrementAndUnits() 方法將公分與英寸進行換算, 因此只要呼叫 setIsMetric 就可以了.

Java 文件的範例是在左上角的 corner 放一個 JToggleButton 來切換, 只要呼叫 JScrollPane 的 setCorner() 方法就可以在 JScrollPane 的四個邊角放置元件, 此方法須傳入兩個參數 :

setCorner(String key, Component corner)

第一個參數為一個表示邊角位置的字串常數, 有如下四個 :
  1. ScrollPaneConstants.LOWER_LEFT_CORNER
  2. ScrollPaneConstants.LOWER_RIGHT_CORNER
  3. ScrollPaneConstants.UPPER_LEFT_CORNER
  4. ScrollPaneConstants.UPPER_RIGHT_CORNER
我們這裡要用到的是 ScrollPaneConstants.UPPER_LEFT_CORNER.

第二個參數就是要放到邊角的元件, 此處是一個 JToggleButton 元件.

如下範例所示 :

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

public class JScrollPane6 implements ItemListener {
  JFrame f;
  JScrollPane jsp;
  Rule columnView;
  Rule rowView;
  public static void main(String argv[]) {
    new JScrollPane6();
    }
  public JScrollPane6() {
    //Setup JFrame
    JFrame.setDefaultLookAndFeelDecorated(true);
    JDialog.setDefaultLookAndFeelDecorated(true);
    f=new JFrame("JScrollPane Test");
    f.setSize(400,300);
    f.setLocationRelativeTo(null);
    Container cp=f.getContentPane();
    //cp.setLayout(null);

    //Build Elements
    ImageIcon img=new ImageIcon("cat.jpg");
    JLabel picture=new JLabel(img);
    jsp=new JScrollPane(picture); //JLabel 放入 JScrollPane
    jsp.setPreferredSize(new Dimension(400, 300));
    //set Ruler
    columnView=new Rule(Rule.HORIZONTAL, true); //建立欄尺規
    rowView=new Rule(Rule.VERTICAL, true); //建立列尺規
    columnView.setPreferredWidth(img.getIconWidth()); //設定欄尺規寬度
    rowView.setPreferredHeight(img.getIconHeight()); //設定列尺規高度
    jsp.setColumnHeaderView(columnView); //加上欄尺規
    jsp.setRowHeaderView(rowView); //加上列尺規
    //set corner
    JToggleButton cmin=new JToggleButton("cm", true);  //cm/in 切換按鈕
    cmin.addItemListener(this);  //註冊選項事件
    jsp.setCorner(ScrollPaneConstants.UPPER_LEFT_CORNER, cmin); //設定邊角
    cp.add(jsp,BorderLayout.CENTER); //JScrollPane 放在中央
    f.setVisible(true);

    //Close JFrame    
    f.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
    f.addWindowListener(new WindowHandler(f));
    }
  public void itemStateChanged(ItemEvent e) {  //實作選項事件
    if (e.getStateChange()==ItemEvent.SELECTED) { //切換為公制
      rowView.setIsMetric(true); 
      columnView.setIsMetric(true);
      }
    else {  //切換為英制
      rowView.setIsMetric(false);
      columnView.setIsMetric(false);
      }
    }
  }
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);}
    }
  }

上圖為切換成英吋單位, 注意 JToggleButton 按鈕註冊的事件為 ItemAction, 所以必須實作 ItemActionListener. 如果按鈕被按下, 就將尺規物件設為公制 (cm), 否則設為英制 (in). 為了要在 Item 事件處理中存取尺規物件, 所以把 rowView 與 columnView 這兩個尺規物件改為類別成員.

最後, JScrollPane 還有一個最常用的場合, 就是配合 JList 一起使用. 在 AWT 中, List 元件的項目如果超過元件高度時會自動出現捲軸, 不需要使用 ScrollPane 物件; 但很奇怪的是, 到了 Swing 時代, JList 卻沒有這個功能了, 如下範例所示 :

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

public class JScrollPane7 {
  JFrame f;
  public static void main(String argv[]) {
    new JScrollPane7();
    }
  public JScrollPane7() {
    //Setup JFrame
    JFrame.setDefaultLookAndFeelDecorated(true);
    JDialog.setDefaultLookAndFeelDecorated(true);
    f=new JFrame("JScrollPane Test");
    f.setSize(300,200);
    f.setLocationRelativeTo(null);
    Container cp=f.getContentPane();
    cp.setLayout(new GridLayout(1,2));

    //Build Elements
    String[] nations={
      "美國 +1 United States of America",
      "英國 +44 United Kindom",
      "日本 +81 Japan",
      "法國 +33 France",
      "俄羅斯 +7 Russia",
      "剛果 +243 Democratic Republic of Congo",
      "赤道幾內亞 +240 Equatorial Guinea",
      "蓋亞那 +592 Guyana",
      "薩爾瓦多 +503 Elsalvador",
      "委內瑞拉 +58 Venezuela"
      };
    String[] components={
      "JList",
      "JComponet",
      "JButton",
      "JTree",
      "JFileChooser",
      "JOptionPane",
      "JInternalPane",
      "JTable",
      "JCheckBox",
      "JComboBox"
      };
    JList<String> list1=new JList<String>(nations);
    JList<String> list2=new JList<String>(components);
    list1.setBorder(BorderFactory.createTitledBorder("國家"));
    list2.setBorder(BorderFactory.createTitledBorder("元件"));
    cp.add(list1);
    cp.add(list2);
    f.setVisible(true);

    //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);}
    }
  }

可見寬度與高度超出的部分就看不到了, 也不會像 AWT 的 List 元件那樣自動加上捲軸, 當然, 只要視窗為可調整大小, 還是可以看到全部內容的. 注意, 這裡 JList 已經改用泛型重新定義了, 內容為字串要指定為 String.

JList 必須配合 JScrollPane 才會在項目太多或太長超過清單高度或寬度時出現捲軸, 如下面範例 所示 :

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

public class JScrollPane8 {
  JFrame f;
  public static void main(String argv[]) {
    new JScrollPane8();
    }
  public JScrollPane8() {
    //Setup JFrame
    JFrame.setDefaultLookAndFeelDecorated(true);
    JDialog.setDefaultLookAndFeelDecorated(true);
    f=new JFrame("JScrollPane Test");
    f.setSize(300,200);
    f.setLocationRelativeTo(null);
    Container cp=f.getContentPane();
    cp.setLayout(new GridLayout(1,2));

    //Build Elements
    String[] nations={
      "美國 +1 United States of America",
      "英國 +44 United Kindom",
      "日本 +81 Japan",
      "法國 +33 France",
      "俄羅斯 +7 Russia",
      "剛果 +243 Democratic Republic of Congo",
      "赤道幾內亞 +240 Equatorial Guinea",
      "蓋亞那 +592 Guyana",
      "薩爾瓦多 +503 Elsalvador",
      "委內瑞拉 +58 Venezuela"
      };
    String[] components={
      "JList",
      "JComponet",
      "JButton",
      "JTree",
      "JFileChooser",
      "JOptionPane",
      "JInternalPane",
      "JTable",
      "JCheckBox",
      "JComboBox"
      };
    JList<String> list1=new JList<String>(nations);
    JList<String> list2=new JList<String>(components);
    list1.setBorder(BorderFactory.createTitledBorder("國家"));
    list2.setBorder(BorderFactory.createTitledBorder("元件"));
    cp.add(new JScrollPane(list1)); 
    cp.add(new JScrollPane(list2)); 
    f.setVisible(true);
    f.pack();  //不是自行排版要加上 pack()

    //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);}
    }
  }

當資料過長時, JScrollPane 就會適時加上捲軸. 總之, 如果要確保使用者能看到全部資料, 就把元件用 JScrollPane 包起來就行了.




1 則留言:

  1. 您好 我想請問一下 我自己在練習
    jLabel 為何會顯示null 一開始輸入可以正確,可是清除資料後 在輸入 label就會顯示null 為什麼呢?
    是不是要先把資料初始化?

    回覆刪除