1. 程式人生 > >《瘋狂Java講義》讀書筆記(七):Swing程式設計

《瘋狂Java講義》讀書筆記(七):Swing程式設計

第十二章 Swing程式設計

1Swing開發圖形介面比AWT更加優秀,它是一種輕量級元件,採用100%Java實現,不依賴於本地平臺的圖形介面,對跨平臺支援比較出色。依賴於本地平臺的AWT元件被稱為重量級元件。通常在AWT元件的元件名前新增“J”就變成了對應的Swing元件。

Swing中包含了4個元件直接集成了AWT元件,而不是從JComponent派生的,它們分別是:JFrameJWindowJDialogJApplet。它們是重量級元件,需要部分委託給執行平臺上的GUI元件的對等體。Swing除了Canvas之外的所有AWT元件都提供了相應的實現。

①使用setToolTipText()

為元件設定對使用者有幫組的提示資訊;②ImageIcon該實現類代表一個影象圖示;③支援拔插式的外觀風格,每個JComponent物件都有一個對應的ComponentUI物件,完成所有的繪畫、事件處理、決定尺寸大小等工作。每個Swing元件都有一個對應的UI類,例如JButton元件就有一個對應的ButtonUI類來作為UI代理。一般是將Swing元件類名去掉J,後面新增UI字尾。

frame.setLocationRelativeTo(null);//預設視窗居中位置

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//關閉視窗,點選右上角的 X

即可關閉視窗。

Swing選單不允許使用add(new JMenuItem("-"))的方式來新增選單分隔符,只能使用addSeparator()方法來新增選單分隔符。

Swing元件新增右鍵選單無須像AWT那樣繁瑣,只需要呼叫setComponentPopupMenu()方法來設定右鍵選單即可。簡而言之,如果希望讓JTextAreaJTable元件有滾動效果支援,只要將該元件放入JScrollPane中,再將該JScrollPane容器新增到視窗中即可。

JScrollPane對於JTable元件尤其重要,通常需要把JTable放在JScrollPane容器中才可以顯示出JTable元件的標題欄。

Swing元件的雙緩衝和鍵盤驅動:所有的Swing元件預設還有如下兩個功能:預設的雙緩衝繪圖技術和簡單的鍵盤驅動。JComponent元件預設啟用雙緩衝,無須自己實現,如果想關閉,可以在元件上呼叫setDoubleBuffered(false)方法。JComponent類提供了getInputMapgetActionMap兩個方法,getInputMap返回一個關聯,該物件用於將KeyStroke物件(代表鍵盤或其他類似輸入裝置的一次輸入事件)和名字關聯;getActionMap返回一個ActionMap物件,該物件用於將指定名字和ActionAction介面是ActionListener的子介面,可以作為一個事件監聽器使用)關聯,從而允許使用者通過鍵盤操作來代替滑鼠驅動GUI上的Swing元件,即快捷鍵。典型用法例子:

// 新增事件監聽器

button.addActionListener(senMessage);

// 將Ctrl+Enter作為鍵和 send關聯

textField.getInputMap().put(KeyStroke.getKeyStroke('\n',java.awt.event.InputEvent.CTRL_MASK), "send");

//將send和senMessage Action關聯

textField.getActionMap().put("send", senMessage);

//監聽事件實現

Action senMessage = newAbstractAction() {

publicvoid actionPerformed(ActionEvent e) {Date date = newDate();

SimpleDateFormat simpleDateFormat = newSimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");

String sendTime = simpleDateFormat.format(date);textArea.append(textField.getText() + "  " + sendTime + "\n");

textField.setText("");}};

☞使用JToolBar建立工具條:建立JToolBar物件時可以指定如下兩個引數:name指定工具條的名稱和orientation指定工具條的方向。一旦建立了JToolBar物件之後,JToolBar物件還有如下幾個常用方法:

JButton add(Action a)通過Action物件為JToolBar新增對應的工具按鈕;void addSeparator(Dimension size):向工具條中新增指定大小的分隔符,可以使用預設大小的分隔符;void setFloatable(boolean b):設定該工具條是否可以浮動,即該工具條是否可以拖動;void setMargin(Insets m)設定工具條邊框和工具按鈕之間的頁邊距;void setOrientation(int o)設定工具條的方向。

Clipboard clipboard=Toolkit.getDefaultToolkit().getSystemClipboard();//獲取系統剪貼簿

Action pasteAction=new AbstractAction("貼上",new ImageIcon("ico/paste.png")){

public void actionPerformed(ActionEvent e){

if(clipboard.isDataFlavorAvailable(DataFlavor.stringFlavor))//如果剪貼簿中包含stringFlavor內容

{try{

//取出剪貼簿中的stringFlavor內容  

String content=(String)clipboard.getData(DataFlavor.stringFlavor);

//將選中內容替換成剪貼簿內容  

jta.replaceRange(content,jta.getSelectionStart(),jta.getSelectionEnd());}catch()

}}}

//複製的主要程式碼

StringSelection contents=new StringSelection(jta.getSelectedText());//將StringSelection物件放入剪貼簿中

clipboard.setContents(contents,null);   //如果剪貼簿中包含stringFlavor內容,則啟用“貼上”按鈕事件

if(clipboard.isDateFlavorAvailable(DataFlavor.stringFlavor)){

pasteAction.setEnabled(true);}

☞JFileChooser的功能與AWT中的FileDialog基本相似,與FileDialog不同的是,JFileChooser無需依賴本地平臺的GUI,由100%純Java實現。JFileChooser先建立一個對話方塊例項,有多個構造器,包含兩個引數currentDirectory、FileSystemView。JFileChooser並不是JDialog的子類,所以不能使用setVisible(true)方法來顯示該檔案對話方塊,而是使用showXXXDialog()方法來顯示檔案對話方塊。建立JFileChooser物件時可以指定初始化路徑,如下程式碼:

JFileChooser chooser=new JFileChooser(".");表示以當前路徑建立檔案選擇器。

☞JFileChooser大致有如下幾個常用方法:

setSelectedFile/setSelectedFiles指定該檔案選擇器預設選擇的檔案(也可以預設選擇多個檔案):chooser.setSelectedFile(new File("123.jpg"));    

setMultiSelectionEnabled(boolean b)預設情況下,該檔案選擇器只能選擇一個檔案,通過該方法可以設定允許選擇多個檔案(設定b為true即可)。   

setFileSelectionMode(int mode)在預設情況下,該檔案選擇器只能選擇一個檔案,該方法可以設定允許選擇檔案、路徑、檔案與路徑,設定引數值為:JFileChooser.FILES_ONLY、JFileChooser.DIRECTORIES_ONLY、JFileChooser.FILES_AND_DIRECTORIES。

☞如果讓檔案對話方塊實現檔案過濾功能,則需要結合FileFilter類來實現檔案過濾。JFileChooser提供了兩個方法來安裝檔案過濾器:addChoosableFileFilter(FileFilter filter)新增檔案過濾器,該方法允許該檔案對話方塊有多個檔案過濾器。

setFileFilter(FileFilter filter):設定檔案過濾器,一旦呼叫該方法,將導致檔案對話方塊只有一個檔案過濾器。

☞FileView類可以改變檔案對話方塊的外觀檢視。

☞呼叫showXXXDialog()方法可以開啟檔案對話方塊,通常有三個方法可以用:

int showDialog(Component parent,String approveButtonText)彈出檔案對話方塊,該對話方塊的標題、“同意”按鈕的文字(預設是 儲存 或 取消 按鈕)由approveButtonText指定。 

int showOpenDialog(Component parent)彈出檔案對話方塊,有預設標題,“同意”按鈕的文字是“開啟”。  

int showSaveDialog(Component parent)彈出檔案對話方塊,該對話方塊具有預設標題,“同意”按鈕的文字是“儲存”。

☞JFileChooser提供了兩個方法來獲取使用者選擇的檔案或檔案集:File getSelectedFile()返回使用者選擇的檔案。File[] getSelectedFiles()返回多個檔案。

預設情況下,JFileChooser總會在檔案對話方塊的“檔案型別”下拉列表中增加“所有檔案”選項,但可以呼叫JFileChooser的setAcceptAllFileFilterUsed(flase)來取消顯示該選項。

☞使用JOptionPane可以非常方便的建立一些簡單的對話方塊,有4個方法:

①showMessageDialog/showInternalMessageDialog:訊息對話方塊,告知使用者某事已經發生,使用者只能點選“確定”按鈕,類似JavaScript的alert函式。

②showConfirmDialog/showInternalConfirmDialog:確認對話方塊,使用者可以選擇yes、no、cancel選項。該方法返回使用者單擊了哪個按鈕;

③showInputDialog/showInternalInputDialog:輸入對話方塊,該方法返回使用者輸入的字串;④showOptionDialog/showInternalInputDialog:自定義選項對話方塊,允許使用自定義選項,可以取代showConfirmDialog所產生的對話方塊,只是用起來複雜。JOptionPane產生的所有對話方塊都是模式的,在使用者完成對話方塊的互動之前,showXXXDialog方法都將一直阻塞當前執行緒。

1)輸入區:輸入區元件可以是普通文字框元件,也可以是下拉列表框元件;

2)圖示區:左上角的圖示會隨建立的對話方塊所包含訊息型別的不同而不同,JOptionPane提供5種訊息型別:

☞ERROR_MESSAGE:錯誤訊息,其圖示是一個紅X;☞INFORMATION_MESSAGE:普通訊息,藍色的感嘆號;☞WARNING_MESSAGE:警告訊息,黃色感嘆號;☞QUESTION_MESSAGE:問題訊息,綠色問號;☞PLAIN_MESSAGE:普通訊息,沒有預設圖示。

3)訊息區:不管哪種對話方塊,其訊息區總是存在的,訊息區的內容通過message引數來指定,該message引數可以是以下幾種:

①String型別:系統將該字串物件包裝成JLabel物件,然後顯示在對話方塊中;②Icon:該Icon被包裝成JLabel後作為對話方塊的訊息;③Component:將該Component在對話方塊的訊息區中顯示出來;④Object[] :物件陣列被解釋為在縱向排列的一系列message物件,每個message物件根據其實際型別又可以是字串、圖示、元件、物件陣列等。⑤其它型別:系統呼叫該物件的toString方法返回字串。

4)按鈕區:對話方塊底部的按鈕區也是一定存在的,底部總是包含“確定”和“取消”兩個標準按鈕,該引數可以取如下幾個值:①DEFAULT_OPTION:按鈕只包含一個“確定”按鈕;②YES_NO_OPTION:按鈕包含“是”、“否”兩個按鈕;③YES_NO_CANCEL_OPTION:按鈕包含“是”、“否”、“取消”三個按鈕;④OK_CANCEL_OPTION:按鈕包含“確定”、“取消”2個按鈕。

int str1 = JOptionPane.showConfirmDialog(frame, "這是彈出來的資訊");System.out.println(str1);

是:返回0。否:返回1。取消:返回2。右上角紅X:返回-1

String[] aa = { "深圳", "廣州", "北京", "上海" };

Object str = JOptionPane.showInputDialog(frame, "想去哪裡發展?","彈框的標題"

JOptionPane.WARNING_MESSAGE, null, aa, aa[0]);

System.out.println(str.toString());

其中JOptionPane.WARNING_MESSAGE可以使用數字1,2,3等表示,但是數字表示不直觀,不利於程式碼閱讀。倒數第一個引數表示選中的預設值。

Swing簡化的拖放功能:

textArea.setDragEnabled(true);//啟動文字域和單行文字框的拖放支援

frame.add(newJScrollPane(textArea));//滾動條,簡潔的程式碼編寫風格

使用JProgressBarProgressMonitorBoundedRangeModel建立進度條:

使用JProgressBar可以非常方便的建立進度條,步驟有仨:①建立JProgressBar物件,可以指定3個引數,用於設定進度條的排列方向(豎直和水平)、進度條的最大值和最小值。②呼叫該物件的常用方法設定進度條的普通屬性,JProgressBar除了提供設定排列方向、最小最大值的settergetter方法之外,還提供了3個方法:setBorderPainted(boolean b)設定該進度條是否使用邊框;setIndeterminate(boolean newValue),設定該進度條是否是進度不確定的進度條,如果指定一個進度條的進度不確定,將看到一個滑塊在進度條中左右移動;setStringPainted(boolean newValue):設定是否在進度條中顯示完成的百分比。③當程式中工作進度改變時,呼叫JProgressBar物件的setValue方法,當進度條的完成進度發生改變時,程式還可以呼叫進度條物件的如下2個方法:double getPercentComplete返回進度條的百分比,String getString()返回進度條字串的當前值。

使用匿名內部類來使用Timer,建立進度條:

import java.awt.FlowLayout;

import java.util.Timer;

import java.util.TimerTask;

import javax.swing.JFrame;

import javax.swing.JProgressBar;

publicclassTestProgressBar {

JFramejframe = newJFrame("測試");

JProgressBarbar = newJProgressBar(JProgressBar.HORIZONTAL);//水平的

publicvoid init() {

jframe.setLayout(newFlowLayout());

jframe.add(bar);bar.setStringPainted(true);// 繪製百分比

finalSimulateClass target = newSimulateClass(100);

newThread(target).start();

// 啟動一條執行緒的方式來執行一個耗時任務

bar.setMinimum(0);

bar.setMaximum(target.getAmount());

Timer timer=newTimer();

timer.schedule(newTimerTask() {

@Override

publicvoid run() {

bar.setValue(target.getCurrent());

System.out.println("完成了工作量的:"+target.getCurrent());}}, 

1000, 2000);

//實際上,Java實時性很差,如果呼叫TimerscheduleAtFixedRate方法,那麼Timer會盡量讓Task執行頻率保持在2秒一次,如果某一次延遲,Timer會記錄下這個延遲,並嘗試在下一個任務時彌補這個延遲。

jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);jframe.pack();

jframe.setVisible(true);}

publicstaticvoid main(String[] args) {newTestProgressBar().init();}}

classSimulateClassimplements Runnable {

privatevolatileintcurrent;

privateintamount;

publicint getCurrent() {

returncurrent;}

publicint getAmount() {returnamount;}

public SimulateClass(int amount) {current = 0;this.amount = amount;}

@Override

publicvoid run() {

while(current<amount){

try {

Thread.sleep(150);} 

catch (Exception e) {

e.printStackTrace();}

current++;}}}

注:自定義的classSimulateClassimplements Runnable實現了Runnable介面,這是一個特殊的介面,實現該介面可以實現多執行緒功能。

建立進度對話方塊:

ProgressMonitor的用法與ProgressBar的用法基本相似,只是ProgressMonitor可以直接建立一個進度對話方塊,構造器如下:ProgressMonitorComponent parentComObject messageString noteint minint max):該構造器中的parentCom引數用於設定該進度對話方塊的父元件,message用於設定該進度條對話方塊的描述資訊,note用於設定該進度條的提示文字,minmax用於設定對話方塊所包含進度條的最小值和最大值。

finalProgressMonitor dialog=newProgressMonitor(null, "等待任務的完成...", "已完成:", 0, target.getAmount());

使用JTable和TableModel建立表格:

使用JTable建立表格非常容易,JTable可以把一個二維資料包裝成一個表格,資料既可以是二維陣列,也可也是集合元素為Vector的物件,為了給表格的每一列指定列標題,還需要傳入一個一維資料作為列標題,一維資料既可以是一維陣列,也可也是Vector物件。

JFrameframe = newJFrame("測試表格");JTabletable;

Object[][] tableData = { newObject[] { "張三", 28, "男", "沒有列名嗎" },

newObject[] { "哈哈", 20, "女", "沒有列名嗎" },newObject[] { "麼麼噠", 22, "女", "沒有列名嗎" },

newObject[] { "lili", 28, "男", "沒有列名嗎" },newObject[] { "斯諾克", 30, "男", "沒有列名嗎" }, };

Object[] columnTitle = { "姓名", "年齡", "性別", "資料可以多,但是標題不能多" };

publicvoid init() {

// 以二維陣列和一維陣列來建立一個JTable物件

table = newJTable(tableData, columnTitle);

// 將表放入JScrollPane中

frame.add(newJScrollPane(table));

frame.pack();

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.setLocationRelativeTo(null);

frame.setVisible(true);}

注:表頭只能少,不能多出一列,表頭少的僅僅顯示前面的資料,而後面的資料將不能正常顯示。如果不把JTable放在JScrollPane中顯示,JTable預設不會顯示列標題。

使用JPasswordFieldJPasswordFieldJTextField的一個子類,當用戶向JPasswordField輸入內容時,JPasswordField會顯示星號或者黑點來代替使用者輸入的字串。除此之外,JPasswordField重寫了JTextComponentgetText()方法,並且不再推薦使用getText()方法返回字串密碼框的字串,因為getText()方法返回的字串會一直停留在虛擬機器中,直到垃圾回收,這可能導致一些安全隱患,所以JPasswordField提供了一個getPassword()方法,有更好的機制。