1、理論知識部分html
設計模式(Design pattern)是設計者一種流行的思考設計問題的方法,是一套被反覆使用,多數人知曉的,通過分類編目的,代碼設計經驗的總結。使用設計模式是爲了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。每個模式描述了一個不斷重複發生的設計問題,以及該問題的核心解決方案java
模型-視圖-控制器設計模式(Model –ViewController )是Java EE平臺下建立 Web 應用程序 的重要設計模式。數據庫
MVC設計模式 – Model(模型):是程序中用於處理程序數據邏輯的部分,一般模型負責在數據庫中存取數據。– View(視圖):是程序中處理數據顯示的部分,一般視圖依據模型存取的數據建立。 – Controller(控制器):是程序中處理用戶交互的部分。一般控制器負責從視圖讀取數據,控制用戶輸入,並向模型發送數據。設計模式
MVC模式可應用於Java的GUI組件設計中。MVC模式GUI組件設計的惟一的模式,還有不少設計的模式(設計方法)。數組
Java組件有內容、外觀、行爲三個主要元素;這三個主要元素與模型—視圖—控制器模式的 三部件的對應關係爲:內容——控制器(做用:處理用戶輸入) 外觀——視圖(做用:顯示內容)行爲——模型(做用:存儲內容)閉包
佈局管理器是一組類。實現 java.awt.LayoutManager 接口;決定容器中組件的位置和大小app
Java.awt包中定義了5種佈局管理類,每一種佈局管理類對應一種佈局策略。每一個容器都有與之相關的默認佈局管理器。當一個容器選定一種佈局策略時,它應該建立該 策略對應的佈局管理器對象,並將此對象設置爲 本身的佈局管理器。框架
5種佈局管理器:(1)FlowLayout:流佈局(Applet和Panel的默認佈局管理器) (2)BorderLayout:邊框佈局( Window、Frame和Dialog的默認佈局管理器)(3)GridLayout:網格佈局(4)GridBagLayout: 網格組佈局(5)CardLayout :卡片佈局less
FlowLayout Manager 組件採用從左到右,從上到下逐行擺放。ide
GridBagLayout不須要組件的尺寸一致,允許組件擴展到多行、多列。
每一個容器對象在沒有設置新的佈局前,在容器中添加組件都按照該容器的缺省佈局排列。經過setLayout( )方法爲容器設置新的佈局。格式 : 容器組件名.setLayout( 佈局類對象名)
FlowLayout (流佈局管理器):用於對組件逐行地定位,每完成一行,一個新行便又開始。與其餘佈局管理器不一樣的是,流佈局管理器不限制它所管理組件的大小,容許它們有本身的最佳大小。
構造函數有:FlowLayout( ):生成一個默認的流式佈局對象 ; FlowLayout(int align): 設定每一行組件的對齊方式(FlowLayout.LEFT, FlowLayout.CENTER, FlowLayout.RIGHT);FlowLayout(int align,int hgap,int vgap):能夠設定組件間的水平和垂直距離(缺省時組件之間沒有空隙)
流佈局是面板的默認佈局管理器
BorderLayout (邊框佈局管理器):邊框佈局管理器是每一個JFrame的內容窗格的默認佈局管理器;流佈局管理器可將組件置於內容窗格的中部,北 部、南部、東部或西部位置。流佈局管理器會擴展組件尺寸並填滿指定方位區域。
BorderLayout的使用方法:設置容器的佈局管理器爲BorderLayout ;向容器中加入組件時,若使用兩個參數的add() 方法,第二個參數必須說明加入組件在容器中的放置位置;位置參數是BorderLayout 類的常量:CENTER、 NORTH、SOUTH、EAST、WEST 例如: frame.add(component,BorderLayout.SOUTH);
BorderLayout( ) :建立新的BorderLayout,組件之間沒有間距 ;setHgap(int hgap) :將組件間的水平間距設置爲指定的值; setVgap(int vgap) :將組件間的垂直間距設置爲指定的值
GridLayout (網格佈局管理器):網格佈局按行列排列全部的組件;在網格佈局對象的構造器中,須要指定行數和列數: panel.setLayout(new GridLayout(6,10));放置組件的每一個單元具備相同的尺寸。添加組件,從第一行和第一列開始,而後是第一行的第二列。以此類推。
GridLayout:指定網格中的行數和列數,建立網格佈局
GridLayout的使用方法:GridLayout的構造函數以下:(1)GridLayout():生成一個單行單列的網格佈局(2)GridLayout(int rows,int cols):生成一個設定行數和列數的網格佈局 (3)GridLayout(int rows,int columns,int hgap,int vgap): 能夠設置組件之間的水平和垂直間隔
因爲網格中全部單元的寬度、高度是相同的,因此Grid佈局管理器老是忽略組件的最佳大小。將組件添加到網格中的命令次序決定組件佔有的單元。單元的列數是從左到右填充,而行是從上到下由行填充。
文本域(JTextField) : 用於獲取單行文本輸入。文本域的使用方法:JPanel panel = new JPanel(); JTextField textField = new JTextField("Default input", 20); panel.add(textField);第一個參數「Default input」:將文本域的缺省顯示值爲Default input ;第二個參數20:表示文本域顯示寬度爲20列。若要從新設置列數,可以使用setColumns方法。
文本輸入經常使用API:用於文本輸入的組件繼承於JTextComponent抽象類, java.swing.text.JTextComponent 1.2:String getText() ; void setText(String text) 獲取或設置文本組件中的文本 。 boolean isEditable() ; void setEditable(boolean b) 獲取或設置editable特性,這個特性決定了用戶是否能夠編輯文本組件中的內容。 Java.swing. JComponent : void revalidate( ) :從新計算容器內全部組件的大小和位置,並對它們從新佈局。 如 panel.revalidate()
文本域JTextField經常使用API : Java.swing. JTextField: JTextField(int cols) 構造一個指定列數的空JTextField對象。 JTextField(String text,int cols) 構造一個指定列數、指定初始字符串的JTextField對象 。 int getColumns(int cols) ; void setColumns(int cols) 獲取或設置文本域使用的列數
文本域初始化 :只要不爲JTextField構造器提供字符串參數,就能夠構造一個空白文本域。 JTextField textField=newJTextField(20);可在任什麼時候候調用setText方法改變文本域內容。 textField.setText("Hello!"); 可調用getText方法獲取鍵入的文本。要將返回的文本域內容的先後空格去掉,就需調用trim方法:String text=textField.getText().trim();若想改變顯示文本的字體,則調用setFont方法。
文本區(JTextArea)組件可以讓用戶輸入多行文本。生成JTextArea組件對象時,能夠指定文本區的行數和列數: textArea = new JTextArea(8, 40); // 8行40列。輸入時,若是文本區的文本超出顯示範圍,則其他的文本會被剪裁;可使用換行來避免過長的行被裁減: textArea.setLineWrap(true);在Swing中,文本區沒有滾動條,須要手動安裝 :JScrollPane scrollPane = new JScrollPane(textArea)
文本區與文本域的異同相同之處: 文本域和文本區組件均可用於獲取文本輸入。 不一樣之處:文本域只能接受單行文本的輸入;文本區可以接受多行文本的輸入。
文本區JTextArea的經常使用API:JTextArea(int rows, int cols) 構造一個rows行cols列的文本區對象 。JTextArea(String text,int rows, int cols) 用初始文本構造一個文本區對象。void setRows(int rows) 設置文本域使用的行數。 void append(String newText) 將給定文本附加到文本區中已有文本的後面。 void setLineWrap(boolean wrap) 打開或關閉換行。
標籤是容納文本的組件。它們沒有任何修飾(如沒有邊界 ),也不響應用戶輸入。標籤的經常使用用途之一就是標識組件,例如標識文本域。其使用步驟以下: 1. 建立一個JLabel組件。例: JLabel label = new JLabel(「hours」, SwingConstants.RIGHT); 或者 JLabel label = new JLabel(「hours」, JLabel.RIGHT);以上代碼建立了一個label,並指定label的對齊方式爲右對齊。 2. 將標籤組件放置在距離被標識組件足夠近的地方。
標籤組件經常使用API:JLable(String text) JLable(Icon icon) JLable(String text,int align) JLable(String text,Icon icon,int align) 構造一個標籤。 String getText() void setText(String text) 獲取或設置標籤的文本。 Icon getIcon() void setIcon(Icon icon) 獲取或設置標籤的圖標
密碼域是一種特殊類型的文本域。每一個輸入的字符都用回顯字符實現,典型的回顯字符爲*。
複選框( JCheckBox ):若是想要接收的輸入只是「是」或「非」,就可使用複選框組件。用戶經過單擊某個複選框來選擇相應的選項,再點擊則取消選擇。當複選框得到焦點時,用戶也能夠經過空格鍵來切換選擇。
複選框構造器:1.bold = new JCheckBox("Bold"); 複選框自動地帶有表示標籤。 2. JCheckBox(String label,Icon icon); 構造帶有標籤與圖標的複選框,默認初始未被選擇。 3.JCheckBox(String label,boolean state); 用指定的標籤和初始化選擇狀態構造一個複選框
複選框經常使用API: 1.void setSelected(boolean state); 設置複選框的選擇狀態 2.boolean isSelected(); 獲取複選框的選擇狀態
單選按鈕:當須要用戶只選擇幾個選項中的一個。即當用戶選擇另外一項的時候,前一項就自動的取消選擇。
單選按鈕的構造器:1.JRadioButton(String label,Icon icon); 建立一個帶標籤和圖標的單選按鈕 2.JRadioButton(String label,boolean state); 用指定的標籤和初始化狀態構造單選按鈕
按鈕組:爲單選按鈕組構造一個ButtonGroup的對象。 而後,再將JRadioButton類型的對象添加到按鈕組中。按鈕組負責在新按鈕被按下的時,取消前一個按鈕的選擇狀態。 ButtonGroup group = new ButtonGroup() group.add(JRadioButton對象); 注意:按鈕組僅僅控制按鈕的行爲,若是想把這些按鈕組織在一塊兒佈局,還須要把它們添加到容器中 ,如JPanel.
邊框:若是在一個窗口中有多組複選框或單選按 鈕,就須要可視化的形式指明哪些按鈕屬於同 一組。Swing提供了一 組頗有用的邊框 ( borders)來解決這個問題。
邊框的建立方法:能夠調用BorderFactory類的靜態方法建立。可選的風格有:凹斜面:BorderFactory.createLoweredBevelBorder() 凸斜面:BorderFactory.createRaisedBevelBorder() 蝕刻:BorderFactory.createEtchedBorder() 直線:BorderFactory.createLineBorder(Color) 不光滑:BorderFactory.createMatteBorder()還能夠給邊框加標題 BorderFactory.createTitledBorder()
組合框:若是有多個選擇項,使用單選按鈕佔據的屏幕空間太大時,就能夠選擇組合框。
組合框構造器與經常使用方法:faceCombo = new JComboBox(); faceCombo.setEditable(true); 讓組合框可編輯 faceCombo.addItem("Serif"); faceCombo.insertItemAt("Monospace",0); 增長組合框選項 faceCombo.removeItem("Monospace"); faceCombo.removeItemAt(0); 刪除組合框選項內容
滑動條( JSlider ):可讓用戶從一組離散值中進行選擇,而且它還容許進行連續值得選擇。
滑動條的修飾可經過顯示標尺(tricks)對滑動條進行修飾。 slider.setMajorTickSpacing(20); 大標尺標記 slider.setMinorTickSpacing(5); 小標尺標記要想顯示以上標記,還需調用: slider.setPaintTicks(true);
能夠調用下列方法爲大標尺添加標尺標籤: slider.setPaintLabels(true); 會根據構建標尺時的min,max,和大標尺的間距自動添加 還能夠提供其餘形式的標尺標記: Hashtable<integer,component> labelTable = new Hashtable<integer,component>(); 構造一個鍵爲Integer類型且值爲Component類型 的散列表。
菜單的建立:首先建立一個菜單欄菜單欄是一個能夠添加到容器組件任何位置的組件。一般放置在框架的頂部。 JMenuBar menuBar=new JMenuBar();調用框架的setJMenuBar方法可將一個菜單欄對象添加到框架上 frame.setJMenuBar(menuBar); 建立菜單對象,並將菜單對象添加到菜單欄中 JMenu editMenu=new Jmenu("Edit"); menuBar.add(editMenu);向菜單對象添加一個菜單項。 JMenItem pasteItem=new JMenItem(); editMenu.add(pasteItem); 向菜單對象添加分隔符行。 editMenu.addSeperator();向菜單對象項添加子菜單。 JMenu optionsMenu=new Jmenu(「option」); editMenu.add(optionsMenu);
彈出菜單是不固定在菜單欄中隨處浮動的菜單。
建立彈出菜單:建立一個彈出菜單與建立一個常規菜單的方法相似,可是彈出菜單沒有標題: JPopupMenu popup = new JPopupMenu();而後用常規方法爲彈出菜單添加菜單項: JMenuItem item = new JMenuItem("Cut"); item.addActionListener(listener); popup.add(item);彈出菜單調用show方法才能顯示出來: popup.show(panel,x,y);
彈出式觸發器(pop-up trigger):用戶點擊鼠標某個鍵時彈出菜單。在Windows或者Linux中,彈出式觸發器是鼠標右鍵。要想在用戶點擊某一個組件的時候彈出菜單,該組件就要調用如下方法設置彈出式觸發器:component.setComponentPopupMenu(popup);
快捷鍵:能夠爲菜單項設置快捷鍵。在當前菜單打開的狀況下,能夠按下某菜單項的快捷鍵,至關於鼠標單擊了該菜單項。JMenuItem CutItem=new JMenuItem(" Index "); CutItem.setMnemonic(" I ");此快捷鍵就會自動顯示在菜單項中,快捷鍵下面有一條下劃線。
加速器:加速器能夠在不打開菜單的狀況下選中菜單項的快捷鍵。 例如,不少應用程序把CTRL + O和CTRL + S關 聯到菜單中的Open和Save項。使用SetAccelerator方法能夠將加速器關聯到一個菜單項。該方法使用KeyStroke類型的對象做爲參數。例如: openItem.setAccelerator(KeyStroke.getKeyStroke("ctrl o" ));當用戶按下加速器組合鍵時,就自動選擇了相應的菜單項,同時激活一個動做事件。加速器只能關聯在菜單項,而不能關聯菜單;加速器實際上並不打開菜單,而是直接激活菜單關聯 的動做事件。
啓用和禁用菜單項:在程序運行過程當中,常常須要屏蔽某些暫時不適用的命令,待到條件容許時再使之從新可用。屏蔽 /啓用菜單項的方法: aMenuItem.setEnabled(boolean):當參數值爲false時,屏蔽該菜單項; 當參數值爲true時,啓用該菜單項; 若是須要動態啓用 /屏蔽某菜單項,則須要爲 「menu selected 」事件註冊監聽器。 javax.swing.event包定義了MenuListener接口,它有三個方法: void menuSelected(MenuEvent event) ; void menuDeselected(MenuEvent event) ; void menuCanceled(MenuEvent event) ;
工具欄(JToolBar):工具欄在程序中提供快速訪問經常使用命令的按鈕欄。工具欄的優勢在於能夠移動,脫離工具欄或拖拽到框架其餘地方。關閉包含工具欄的框架後,工具欄回到原始的框架中。
工具提示:工具提示(tooltips)提示用戶小按鈕的含義。當光標停留在某個按鈕上片刻是,工具提示就會激活。工具提示文本顯示在一個有顏色的矩形裏。當用戶移開鼠標是,工具提示就會自動地消失;在Swing中,能夠調用setToolTest方法將工具提示添加到JComponent上;exitButton.setToolTipText(" Exit ");另一種方法是,若是使用Action對象,就能夠用 SHORT-DESCRIPTION關聯工具提示: exitButton.putValue(Action.SHORT-DESCRIPTION, " Exit ");
網格組佈局 (GridBagLayout):GridBagLayout與GridLayout有點類似,它也是將組件排在格子裏,可是GridBagLayout在網格的基礎上提供更復雜的佈局。GridBagLayout容許單個組件在一個單元中不填滿整個單元,而只是佔用最佳大小,也容許單個組件擴展成不止一個單元,而且能夠用任意順序加入組件。
GridBagLayout 的API:使用GridBagLayout,必須構造一個GridBagConstraints對象。GridBagConstraints 用於指定如何用GridBagLayout放置組件。 GridBagConstraints對象包含一些重要的約束,以指定組件的放置方式,這些約束的含義以下:
1.gridx 、gridy 、gridwidth 和gridheight參數。這四個參數用於指定組件在網格中的位置。gridx 和 gridy值用於指定組件左上角的座標;gridwidth 和gridheight決定組件將佔用多少行和列.
2.增量域(weightx和weighty)。 GridBagLayout內的每一個區域都必須設置它的增量域,即weightx和weighty。若是將權值設置爲0,那麼這個區域就不會在那個方向上擴張或收縮,超出它的初始大小。 增量參數屬於行和列的屬性,而不屬於某個單獨的單元格。但卻需在單元格上指定它們,這是由於 網格組佈局並不暴露行和列。
3.fill 和anchor參數。fill參數用於指定組件在單元格 內進行伸縮時的填充方式,該參數能夠有四種有效 值:GridBagConstraints.NONE(不伸縮 ) 、 GridBagConstraints.HORIZONTAL(水平伸縮 ) 、 GridBagConstraints.VERTICAL(垂直伸縮 ) 和 GridBagConstraints.BOTH 。 若是組件沒有填充整個區域,能夠經過設置 anchor域指定其對齊位置。有效值爲 GridBagConstraints.CENTER, GridBagConstraints.NORTH, GridBagConstraints.NORTHEAST, GridBagConstraints.EAST 等
4 . 填 塞 : 填 充 參 數 insets , ipadx 和 ipady 。 insets參數用於設置沿單元格邊界的外部填充空白區域。ipadx和ipady則用於指定在環繞組件四周的單元格內部填充空白區域。
對話框(JDialog):對話框是一種大小不能變化、不能有菜單的容器窗口;對話框不能做爲一個應用程序的主框架,而必須包含在其餘的容器中。Java提供多種對話框類來支持多種形式的對話框。JOptionPane類支持簡單、標準的對話框;JDialog類支持定製用戶本身的對話框; JFileChooser類支持文件打開、保存對話框;ProgressMonitor類支持操做進度條控制對話框等。
對話框依賴於框架。當框架撤銷時,依賴該框架的對話框也撤銷。當框架圖標化時,依賴它的對話框也從屏幕上消失。當框架窗口恢復時,依賴框架的對話框又返回屏幕。對話框分爲無模式和有模式兩種。有模式的對話框處於激活狀態時,程序只能響應對話框內部的事件,不能再激活它所依賴的窗口或組件,並且它將堵塞當前線程的執行,即堵塞使得對話框處於激活狀態的線程,直到該對話框消失不可見。無模式對話框處於激活狀態時,程序仍能激活它所依賴的窗口或組件,它也不堵塞線程的執行。
選項對話框(JOptionPane):JOptionPane提供的對話框是模式對話框。當模式對話框顯示時,它不容許用戶輸入到程序的其餘的窗口。使用JOptionPane,能夠建立和自定義問題、信息、警告和錯誤等幾種類型的對話框。
Swing提供了用於顯示選項對話框(JOptionPane )的JOptionPane 類,定義了多個showXxxDialog形式的靜態方法 :showMessageDialog —— 信息對話框,顯示信息,告知用戶發生了什麼狀況 。showConfirmDialog —— 確認對話框,顯示問題,要求用戶進行 確認(yes/no/cancel )。showOptionDialog —— 選項對話框,顯示選項,要求用戶進行選 擇 。 showInputDialog —— 輸入對話框,提示用戶進行輸入
建立對話框(JDialog):對話框的構造方法:JDialog(Frame owner) ——構造一個沒有標題的非模式對話框。JDialog(Frame owner, boolean modal) ——構造一個沒有標題的對話框,boolean型參數modal指定對話框是否爲模式窗口。 JDialog(Frame owner, String title) ——構造一個有標題的非模式對話框. JDialog(Frame owner, String title, boolean modal) ——構造一個有標題的對話框。
showXxxDialog方法的參數:Component parentComponent對話框的父窗口對象,其屏幕座標將決定對話框的顯示位置;此參數也能夠爲null,表示採用缺省的Frame 做爲父窗口,此時對話框將設置在屏幕的正中 。 String title 對話框的標題 。 Object message 顯示在對話框中的描述信息。該參數一般是一個String對象,但也能夠是一個圖標、一個組件或者一個對象數組。int messageType – 對話框所傳遞的信息類型。int optionType對話框上按鈕的類型,能夠爲如下常量:DEFAULT_OPTION YES_NO_OPTION YES_NO_CANCEL_OPTION OK_CANCEL_OPTION 。Object[] options:對話框上的選項。在輸入對話框中,一般以組合框形式顯示,在選項對話框中,則指按鈕的選項類型。該參數一般是一個String數組,但也能夠是圖標或組件數組。Icon icon 對話框上顯示的裝飾性圖標,若是沒有指定,則根據 messageType 參數顯示缺省圖標。 Object initialValue 初始選項或輸入值
showXxxDialog()返回類型:showMessageDialog()沒有返回值 。 showConfirmDialog() 和showOptionDialog()方法返 回int型數值,表明用戶選擇按鈕的序號 。(JOptionPane中定義了YES_OPTION、 NO_OPTION、CANCEL_OPTION、OK_OPTION和 CLOSED_OPTION等常量,分別表明用戶選擇了 YES、NO、CANCEL、OK按鈕以及未選擇而直接關 閉了對話框)。 showInputDialog()方法的返回值爲String或 Object,表明用戶的輸入或選項
數據交換:輸入對話框含有供用戶輸入文本的文本框、一個確認和取消按鈕,是有模式對話框。當輸入對話框可見時,要求用戶輸入一個字符串。javax.swing包中的JOptionPane類的靜態方法:public static String showInputDialog(Component parentComponent, Object message,String title,int messageType)。建立一個輸入對話框,其中參數parentComponent指定消息對話框所依賴的組件,確認對話框會在該組件的正前方顯示出來,參數message指定對話框上的提示信息,參數 title指定對話框上的標題,參數messageType可取的有效值是JoptionPane中的類常量
文件對話框(JFileChooser):專門用於對文件(或目錄)進行瀏覽和選擇的對話框,經常使用的構造方法: JFileChooser():根據用戶的缺省目錄建立文件對話框。JFileChooser(File currentDirectory):根據File型參數currentDirectory指定的目錄建立文件對話框。JFileChooser(String currentDirectoryPath):根據 String型參數currentDirectoryPath指定的目錄建立文件對話框。
2、實驗部分
1、實驗目的與要求
(1) 掌握GUI佈局管理器用法;
(2) 掌握各種Java Swing組件用途及經常使用API;
2、實驗內容和步驟
實驗1: 導入第12章示例程序,測試程序並進行組內討論。
測試程序1
l 在elipse IDE中運行教材479頁程序12-1,結合運行結果理解程序;
l 掌握各類佈局管理器的用法;
l 理解GUI界面中事件處理技術的用途。
l 在佈局管理應用代碼處添加註釋;
package calculator; import java.awt.*; import javax.swing.*; /** * @version 1.34 2015-06-12 * @author Cay Horstmann */ public class Calculator { public static void main(String[] args) { EventQueue.invokeLater(() -> { CalculatorFrame frame = new CalculatorFrame(); frame.setTitle("Calculator");// 設置窗口標題 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } }
package calculator; import javax.swing.*; /** * A frame with a calculator panel. */ public class CalculatorFrame extends JFrame { public CalculatorFrame() { add(new CalculatorPanel()); pack(); } }
package calculator; import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * A panel with calculator buttons and a result display. */ public class CalculatorPanel extends JPanel { private JButton display; private JPanel panel; private double result; private String lastCommand; private boolean start; public CalculatorPanel() { setLayout(new BorderLayout());// 構造一個邊框佈局管理器 result = 0; lastCommand = "="; start = true; // add the display display = new JButton("0");// 用來顯示計算的計算結果 display.setEnabled(false);// 禁止使用按鈕 add(display, BorderLayout.NORTH); ActionListener insert = new InsertAction(); ActionListener command = new CommandAction();// 設置兩個監聽器對象 // add the buttons in a 4 x 4 grid panel = new JPanel(); panel.setLayout(new GridLayout(4, 4));// 設置4行4列的網格佈局 addButton("7", insert); addButton("8", insert); addButton("9", insert); addButton("/", command); addButton("4", insert); addButton("5", insert); addButton("6", insert); addButton("*", command); addButton("1", insert); addButton("2", insert); addButton("3", insert); addButton("-", command); addButton("0", insert); addButton(".", insert); addButton("=", command); addButton("+", command); add(panel, BorderLayout.CENTER);// 添加按鈕到指定方位 } /** * Adds a button to the center panel. * * @param label the button label * @param listener the button listener */ private void addButton(String label, ActionListener listener) { JButton button = new JButton(label); button.addActionListener(listener); panel.add(button); } /** * This action inserts the button action string to the end of the display text. */ private class InsertAction implements ActionListener { public void actionPerformed(ActionEvent event) { String input = event.getActionCommand(); if (start) { display.setText(""); start = false; } display.setText(display.getText() + input); } } /** * This action executes the command that the button action string denotes. */ private class CommandAction implements ActionListener { public void actionPerformed(ActionEvent event) { String command = event.getActionCommand(); if (start) { if (command.equals("-")) { display.setText(command); start = false; } else lastCommand = command; } else { calculate(Double.parseDouble(display.getText())); lastCommand = command; start = true; } } } /** * Carries out the pending calculation. * * @param x the value to be accumulated with the prior result. */ public void calculate(double x) { if (lastCommand.equals("+")) result += x; else if (lastCommand.equals("-")) result -= x; else if (lastCommand.equals("*")) result *= x; else if (lastCommand.equals("/")) result /= x; else if (lastCommand.equals("=")) result = x; display.setText("" + result); } }
測試程序2
l 在elipse IDE中調試運行教材486頁程序12-2,結合運行結果理解程序;
l 掌握各類文本組件的用法;
l 記錄示例代碼閱讀理解中存在的問題與疑惑。
package text; import java.awt.*; import javax.swing.*; /** * @version 1.41 2015-06-12 * @author Cay Horstmann */ public class TextComponentTest { public static void main(String[] args) { EventQueue.invokeLater(() -> { JFrame frame = new TextComponentFrame(); frame.setTitle("TextComponentTest"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } }
package text; import java.awt.BorderLayout; import java.awt.GridLayout; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JPasswordField; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.SwingConstants; /** * A frame with sample text components. */ public class TextComponentFrame extends JFrame { public static final int TEXTAREA_ROWS = 8; public static final int TEXTAREA_COLUMNS = 20; public TextComponentFrame() { JTextField textField = new JTextField(); JPasswordField passwordField = new JPasswordField(); JPanel northPanel = new JPanel(); northPanel.setLayout(new GridLayout(2, 2)); northPanel.add(new JLabel("User name: ", SwingConstants.RIGHT)); northPanel.add(textField); northPanel.add(new JLabel("Password: ", SwingConstants.RIGHT)); northPanel.add(passwordField);// 建立了兩個個label,並指定label的對齊方式爲右對齊 add(northPanel, BorderLayout.NORTH);// 北區域的邊框佈局約束(容器頂部)。 JTextArea textArea = new JTextArea(TEXTAREA_ROWS, TEXTAREA_COLUMNS);// 構造具備指定行數和列數的新的空 TextArea JScrollPane scrollPane = new JScrollPane(textArea);// 建立一個顯示指定組件內容的 JScrollPane,只要組件的內容超過視圖大小就會顯示水平和垂直滾動條。 add(scrollPane, BorderLayout.CENTER); // add button to append text into the text area JPanel southPanel = new JPanel(); JButton insertButton = new JButton("Insert"); southPanel.add(insertButton); insertButton.addActionListener(event -> textArea.append( "User name: " + textField.getText() + " Password: " + new String(passwordField.getPassword()) + "\n")); add(southPanel, BorderLayout.SOUTH); pack(); } }
測試程序3
l 在elipse IDE中調試運行教材489頁程序12-3,結合運行結果理解程序;
l 掌握複選框組件的用法;
l 記錄示例代碼閱讀理解中存在的問題與疑惑。
package checkBox; import java.awt.*; import javax.swing.*; /** * @version 1.34 2015-06-12 * @author Cay Horstmann */ public class CheckBoxTest { public static void main(String[] args) { EventQueue.invokeLater(() -> { JFrame frame = new CheckBoxFrame(); frame.setTitle("CheckBoxTest"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } }
package checkBox; import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * A frame with a sample text label and check boxes for selecting font * attributes. */ public class CheckBoxFrame extends JFrame { private JLabel label; private JCheckBox bold; private JCheckBox italic; private static final int FONTSIZE = 24; public CheckBoxFrame() { // add the sample text label label = new JLabel("The quick brown fox jumps over the lazy dog."); label.setFont(new Font("Serif", Font.BOLD, FONTSIZE));// 設置組件的字體。 add(label, BorderLayout.CENTER);// 中間區域的佈局約束(容器中央)。 // this listener sets the font attribute of // the label to the check box state ActionListener listener = event -> { int mode = 0; if (bold.isSelected()) mode += Font.BOLD; if (italic.isSelected()) mode += Font.ITALIC; label.setFont(new Font("Serif", mode, FONTSIZE)); }; // add the check boxes JPanel buttonPanel = new JPanel(); bold = new JCheckBox("Bold");// 複選框自動地帶有表示標籤。 bold.addActionListener(listener); bold.setSelected(true);// 使用setSelected方法來選定或取消選定複選框 buttonPanel.add(bold); italic = new JCheckBox("Italic"); italic.addActionListener(listener); buttonPanel.add(italic); add(buttonPanel, BorderLayout.SOUTH); pack(); } }
測試程序4
l 在elipse IDE中調試運行教材491頁程序12-4,運行結果理解程序;
l 掌握單選按鈕組件的用法;
l 記錄示例代碼閱讀理解中存在的問題與疑惑。
package radioButton; import java.awt.*; import javax.swing.*; /** * @version 1.34 2015-06-12 * @author Cay Horstmann */ public class RadioButtonTest { public static void main(String[] args) { EventQueue.invokeLater(() -> { JFrame frame = new RadioButtonFrame(); frame.setTitle("RadioButtonTest"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } }
package radioButton; import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * A frame with a sample text label and radio buttons for selecting font sizes. */ public class RadioButtonFrame extends JFrame { private JPanel buttonPanel; private ButtonGroup group; private JLabel label; private static final int DEFAULT_SIZE = 36; public RadioButtonFrame() { // add the sample text label label = new JLabel("The quick brown fox jumps over the lazy dog."); label.setFont(new Font("Serif", Font.PLAIN, DEFAULT_SIZE));//設置組件的字體 add(label, BorderLayout.CENTER);//中間區域的佈局約束(容器中央) // add the radio buttons buttonPanel = new JPanel(); group = new ButtonGroup(); addRadioButton("Small", 8); addRadioButton("Medium", 12); addRadioButton("Large", 18); addRadioButton("Extra large", 36); add(buttonPanel, BorderLayout.SOUTH);//添加按鈕到指定方位 pack(); } /** * Adds a radio button that sets the font size of the sample text. * * @param name the string to appear on the button * @param size the font size that this button sets */ public void addRadioButton(String name, int size) { boolean selected = size == DEFAULT_SIZE; JRadioButton button = new JRadioButton(name, selected); group.add(button); buttonPanel.add(button); // this listener sets the label font size ActionListener listener = event -> label.setFont(new Font("Serif", Font.PLAIN, size)); button.addActionListener(listener); } }
測試程序5
l 在elipse IDE中調試運行教材494頁程序12-5,結合運行結果理解程序;
l 掌握邊框的用法;
l 記錄示例代碼閱讀理解中存在的問題與疑惑。
package border; import java.awt.*; import javax.swing.*; /** * @version 1.34 2015-06-13 * @author Cay Horstmann */ public class BorderTest { public static void main(String[] args) { EventQueue.invokeLater(() -> { JFrame frame = new BorderFrame(); frame.setTitle("BorderTest"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } }
package border; import java.awt.*; import javax.swing.*; import javax.swing.border.*; /** * A frame with radio buttons to pick a border style. */ public class BorderFrame extends JFrame { private JPanel demoPanel; private JPanel buttonPanel; private ButtonGroup group; public BorderFrame() { demoPanel = new JPanel(); buttonPanel = new JPanel(); group = new ButtonGroup(); addRadioButton("Lowered bevel", BorderFactory.createLoweredBevelBorder());//建立一個具備凹入斜面邊緣的邊框,將組件當前背景色的較亮的色度用於高亮顯示,較暗的色度用於陰影。(在凹入邊框中,陰影位於頂部,高亮顯示位於其下。) addRadioButton("Raised bevel", BorderFactory.createRaisedBevelBorder()); //建立一個具備凸出斜面邊緣的邊框,將組件當前背景色的較亮的色度用於高亮顯示,較暗的色度用於陰影。(在凸出邊框中,高亮顯示位於頂部,陰影位於其下。) addRadioButton("Etched", BorderFactory.createEtchedBorder());//建立一個具備「浮雕化」外觀效果的邊框,將組件的當前背景色用於高亮顯示和陰影顯示。 addRadioButton("Line", BorderFactory.createLineBorder(Color.BLUE));//建立一個具備指定顏色的線邊框。 addRadioButton("Matte", BorderFactory.createMatteBorder(10, 10, 10, 10, Color.BLUE));//使用純色建立一個相似襯邊的邊框 addRadioButton("Empty", BorderFactory.createEmptyBorder());//建立一個不佔用空間的空邊框 Border etched = BorderFactory.createEtchedBorder(); Border titled = BorderFactory.createTitledBorder(etched, "Border types"); buttonPanel.setBorder(titled); setLayout(new GridLayout(2, 1));//建立2行1列的網格佈局 add(buttonPanel); add(demoPanel); pack(); } //單選按鈕組件監聽器 public void addRadioButton(String buttonName, Border b) { JRadioButton button = new JRadioButton(buttonName); button.addActionListener(event -> demoPanel.setBorder(b)); group.add(button); buttonPanel.add(button); } }
測試程序6
l 在elipse IDE中調試運行教材498頁程序12-6,結合運行結果理解程序;
l 掌握組合框組件的用法;
l 記錄示例代碼閱讀理解中存在的問題與疑惑。
package comboBox; import java.awt.*; import javax.swing.*; /** * @version 1.35 2015-06-12 * @author Cay Horstmann */ public class ComboBoxTest { public static void main(String[] args) { EventQueue.invokeLater(() -> { JFrame frame = new ComboBoxFrame(); frame.setTitle("ComboBoxTest"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } }
package comboBox; import java.awt.BorderLayout; import java.awt.Font; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; /** * A frame with a sample text label and a combo box for selecting font faces. */ public class ComboBoxFrame extends JFrame { private JComboBox<String> faceCombo; private JLabel label; private static final int DEFAULT_SIZE = 24; public ComboBoxFrame() { // add the sample text label label = new JLabel("The quick brown fox jumps over the lazy dog."); label.setFont(new Font("Serif", Font.PLAIN, DEFAULT_SIZE));//設置組件的字體 add(label, BorderLayout.CENTER); // make a combo box and add face names faceCombo = new JComboBox<>(); faceCombo.addItem("Serif"); faceCombo.addItem("SansSerif"); faceCombo.addItem("Monospaced"); faceCombo.addItem("Dialog"); faceCombo.addItem("DialogInput"); // the combo box listener changes the label font to the selected face name faceCombo.addActionListener(event -> label .setFont(new Font(faceCombo.getItemAt(faceCombo.getSelectedIndex()), Font.PLAIN, DEFAULT_SIZE))); // add combo box to a panel at the frame's southern border JPanel comboPanel = new JPanel(); comboPanel.add(faceCombo); add(comboPanel, BorderLayout.SOUTH); pack(); } }
測試程序7
l 在elipse IDE中調試運行教材501頁程序12-7,結合運行結果理解程序;
l 掌握滑動條組件的用法;
l 記錄示例代碼閱讀理解中存在的問題與疑惑。
package slider; import java.awt.*; import javax.swing.*; /** * @version 1.15 2015-06-12 * @author Cay Horstmann */ public class SliderTest { public static void main(String[] args) { EventQueue.invokeLater(() -> { SliderFrame frame = new SliderFrame(); frame.setTitle("SliderTest"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } }
package slider; import java.awt.*; import java.util.*; import javax.swing.*; import javax.swing.event.*; /** * A frame with many sliders and a text field to show slider values. */ public class SliderFrame extends JFrame { private JPanel sliderPanel; private JTextField textField; private ChangeListener listener; public SliderFrame() { sliderPanel = new JPanel(); sliderPanel.setLayout(new GridBagLayout()); // common listener for all sliders listener = event -> { // update text field when the slider value changes JSlider source = (JSlider) event.getSource(); textField.setText("" + source.getValue()); }; // add a plain slider JSlider slider = new JSlider(); addSlider(slider, "Plain"); // add a slider with major and minor ticks slider = new JSlider(); slider.setPaintTicks(true); slider.setMajorTickSpacing(20); slider.setMinorTickSpacing(5); addSlider(slider, "Ticks"); // add a slider that snaps to ticks slider = new JSlider(); slider.setPaintTicks(true); slider.setSnapToTicks(true); slider.setMajorTickSpacing(20); slider.setMinorTickSpacing(5); addSlider(slider, "Snap to ticks"); // add a slider with no track slider = new JSlider(); slider.setPaintTicks(true); slider.setMajorTickSpacing(20); slider.setMinorTickSpacing(5); slider.setPaintTrack(false); addSlider(slider, "No track"); // add an inverted slider slider = new JSlider(); slider.setPaintTicks(true); slider.setMajorTickSpacing(20); slider.setMinorTickSpacing(5); slider.setInverted(true); addSlider(slider, "Inverted"); // add a slider with numeric labels slider = new JSlider(); slider.setPaintTicks(true); slider.setPaintLabels(true); slider.setMajorTickSpacing(20); slider.setMinorTickSpacing(5); addSlider(slider, "Labels"); // add a slider with alphabetic labels slider = new JSlider(); slider.setPaintLabels(true); slider.setPaintTicks(true); slider.setMajorTickSpacing(20); slider.setMinorTickSpacing(5); Dictionary<Integer, Component> labelTable = new Hashtable<>(); labelTable.put(0, new JLabel("A")); labelTable.put(20, new JLabel("B")); labelTable.put(40, new JLabel("C")); labelTable.put(60, new JLabel("D")); labelTable.put(80, new JLabel("E")); labelTable.put(100, new JLabel("F")); slider.setLabelTable(labelTable); addSlider(slider, "Custom labels"); // add a slider with icon labels slider = new JSlider(); slider.setPaintTicks(true);// 顯示標記 slider.setPaintLabels(true);// 肯定是否在滑塊上繪製標籤 slider.setSnapToTicks(true);// 最靠近用戶放置滑塊處的刻度標記的值 slider.setMajorTickSpacing(20);// 大標尺標記 slider.setMinorTickSpacing(20);// 小標尺標記 labelTable = new Hashtable<Integer, Component>(); // add card images labelTable.put(0, new JLabel(new ImageIcon("nine.gif"))); labelTable.put(20, new JLabel(new ImageIcon("ten.gif"))); labelTable.put(40, new JLabel(new ImageIcon("jack.gif"))); labelTable.put(60, new JLabel(new ImageIcon("queen.gif"))); labelTable.put(80, new JLabel(new ImageIcon("king.gif"))); labelTable.put(100, new JLabel(new ImageIcon("ace.gif"))); slider.setLabelTable(labelTable); addSlider(slider, "Icon labels"); // add the text field that displays the slider value textField = new JTextField(); add(sliderPanel, BorderLayout.CENTER); add(textField, BorderLayout.SOUTH); pack(); } /** * Adds a slider to the slider panel and hooks up the listener * * @param s the slider * @param description the slider description */ public void addSlider(JSlider s, String description) { s.addChangeListener(listener); JPanel panel = new JPanel(); panel.add(s); panel.add(new JLabel(description)); panel.setAlignmentX(Component.LEFT_ALIGNMENT); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridy = sliderPanel.getComponentCount(); gbc.anchor = GridBagConstraints.WEST; sliderPanel.add(panel, gbc); } }
測試程序8
l 在elipse IDE中調試運行教材512頁程序12-8,結合運行結果理解程序;
l 掌握菜單的建立、菜單事件監聽器、複選框和單選按鈕菜單項、彈出菜單以及快捷鍵和加速器的用法。
l 記錄示例代碼閱讀理解中存在的問題與疑惑。
package menu; import java.awt.*; import javax.swing.*; /** * @version 1.24 2012-06-12 * @author Cay Horstmann */ public class MenuTest { public static void main(String[] args) { EventQueue.invokeLater(() -> { JFrame frame = new MenuFrame(); frame.setTitle("MenuTest"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } }
package menu; import java.awt.event.*; import javax.swing.*; /** * A frame with a sample menu bar. */ public class MenuFrame extends JFrame { private static final int DEFAULT_WIDTH = 300; private static final int DEFAULT_HEIGHT = 200; private Action saveAction; private Action saveAsAction; private JCheckBoxMenuItem readonlyItem; private JPopupMenu popup; /** * A sample action that prints the action name to System.out */ class TestAction extends AbstractAction { public TestAction(String name) { super(name); } public void actionPerformed(ActionEvent event) { System.out.println(getValue(Action.NAME) + " selected."); } } public MenuFrame() { setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); JMenu fileMenu = new JMenu("File"); fileMenu.add(new TestAction("New")); // demonstrate accelerators JMenuItem openItem = fileMenu.add(new TestAction("Open")); openItem.setAccelerator(KeyStroke.getKeyStroke("ctrl O")); fileMenu.addSeparator(); saveAction = new TestAction("Save"); JMenuItem saveItem = fileMenu.add(saveAction); saveItem.setAccelerator(KeyStroke.getKeyStroke("ctrl S")); saveAsAction = new TestAction("Save As"); fileMenu.add(saveAsAction); fileMenu.addSeparator(); fileMenu.add(new AbstractAction("Exit") { public void actionPerformed(ActionEvent event) { System.exit(0); } }); // demonstrate checkbox and radio button menus readonlyItem = new JCheckBoxMenuItem("Read-only"); readonlyItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { boolean saveOk = !readonlyItem.isSelected(); saveAction.setEnabled(saveOk); saveAsAction.setEnabled(saveOk); } }); ButtonGroup group = new ButtonGroup(); JRadioButtonMenuItem insertItem = new JRadioButtonMenuItem("Insert"); insertItem.setSelected(true); JRadioButtonMenuItem overtypeItem = new JRadioButtonMenuItem("Overtype"); group.add(insertItem); group.add(overtypeItem); // demonstrate icons Action cutAction = new TestAction("Cut"); cutAction.putValue(Action.SMALL_ICON, new ImageIcon("cut.gif")); Action copyAction = new TestAction("Copy"); copyAction.putValue(Action.SMALL_ICON, new ImageIcon("copy.gif")); Action pasteAction = new TestAction("Paste"); pasteAction.putValue(Action.SMALL_ICON, new ImageIcon("paste.gif")); JMenu editMenu = new JMenu("Edit"); editMenu.add(cutAction); editMenu.add(copyAction); editMenu.add(pasteAction); // demonstrate nested menus JMenu optionMenu = new JMenu("Options"); optionMenu.add(readonlyItem); optionMenu.addSeparator(); optionMenu.add(insertItem); optionMenu.add(overtypeItem); editMenu.addSeparator(); editMenu.add(optionMenu); // demonstrate mnemonics JMenu helpMenu = new JMenu("Help"); helpMenu.setMnemonic('H'); JMenuItem indexItem = new JMenuItem("Index"); indexItem.setMnemonic('I'); helpMenu.add(indexItem); // you can also add the mnemonic key to an action Action aboutAction = new TestAction("About"); aboutAction.putValue(Action.MNEMONIC_KEY, new Integer('A')); helpMenu.add(aboutAction); // add all top-level menus to menu bar JMenuBar menuBar = new JMenuBar(); setJMenuBar(menuBar); menuBar.add(fileMenu); menuBar.add(editMenu); menuBar.add(helpMenu); // demonstrate pop-ups popup = new JPopupMenu(); popup.add(cutAction); popup.add(copyAction); popup.add(pasteAction); JPanel panel = new JPanel(); panel.setComponentPopupMenu(popup); add(panel); } }
測試程序9
l 在elipse IDE中調試運行教材517頁程序12-9,結合運行結果理解程序;
l 掌握工具欄和工具提示的用法;
l 記錄示例代碼閱讀理解中存在的問題與疑惑。
package toolBar; import java.awt.*; import javax.swing.*; /** * @version 1.14 2015-06-12 * @author Cay Horstmann */ public class ToolBarsTet { public static void main(String[] args) { EventQueue.invokeLater(() -> { ToolBarFrame frame = new ToolBarFrame(); frame.setTitle("ToolBarTest"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } }
package toolBar; import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * A frame with a toolbar and menu for color changes. */ public class ToolBarFrame extends JFrame { private static final int DEFAULT_WIDTH = 300; private static final int DEFAULT_HEIGHT = 200; private JPanel panel; public ToolBarFrame() { setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); // add a panel for color change panel = new JPanel(); add(panel, BorderLayout.CENTER); // set up actions Action blueAction = new ColorAction("Blue", new ImageIcon("blue-ball.gif"), Color.BLUE); Action yellowAction = new ColorAction("Yellow", new ImageIcon("yellow-ball.gif"), Color.YELLOW); Action redAction = new ColorAction("Red", new ImageIcon("red-ball.gif"), Color.RED); Action exitAction = new AbstractAction("Exit", new ImageIcon("exit.gif")) { public void actionPerformed(ActionEvent event) { System.exit(0); } }; exitAction.putValue(Action.SHORT_DESCRIPTION, "Exit"); // populate toolbar JToolBar bar = new JToolBar(); bar.add(blueAction); bar.add(yellowAction); bar.add(redAction); bar.addSeparator(); bar.add(exitAction); add(bar, BorderLayout.NORTH); // populate menu JMenu menu = new JMenu("Color"); menu.add(yellowAction); menu.add(blueAction); menu.add(redAction); menu.add(exitAction); JMenuBar menuBar = new JMenuBar(); menuBar.add(menu); setJMenuBar(menuBar); } /** * The color action sets the background of the frame to a given color. */ class ColorAction extends AbstractAction { public ColorAction(String name, Icon icon, Color c) { putValue(Action.NAME, name); putValue(Action.SMALL_ICON, icon); putValue(Action.SHORT_DESCRIPTION, name + " background"); putValue("Color", c); } public void actionPerformed(ActionEvent event) { Color c = (Color) getValue("Color"); panel.setBackground(c); } } }
測試程序10
l 在elipse IDE中調試運行教材524頁程序12-十、12-11,結合運行結果理解程序,瞭解GridbagLayout的用法。
l 在elipse IDE中調試運行教材533頁程序12-12,結合程序運行結果理解程序,瞭解GroupLayout的用法。
l 記錄示例代碼閱讀理解中存在的問題與疑惑。
package gridbag; import java.awt.EventQueue; import javax.swing.JFrame; /** * @version 1.35 2015-06-12 * @author Cay Horstmann */ public class GridBagLayoutTest { public static void main(String[] args) { EventQueue.invokeLater(() -> { JFrame frame = new FontFrame(); frame.setTitle("GridBagLayoutTest"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } }
package gridbag; import java.awt.*; /** * This class simplifies the use of the GridBagConstraints class. * * @version 1.01 2004-05-06 * @author Cay Horstmann */ public class GBC extends GridBagConstraints { /** * Constructs a GBC with a given gridx and gridy position and all other grid bag * constraint values set to the default. * * @param gridx the gridx position * @param gridy the gridy position */ public GBC(int gridx, int gridy) { this.gridx = gridx; this.gridy = gridy; } /** * Constructs a GBC with given gridx, gridy, gridwidth, gridheight and all other * grid bag constraint values set to the default. * * @param gridx the gridx position * @param gridy the gridy position * @param gridwidth the cell span in x-direction * @param gridheight the cell span in y-direction */ public GBC(int gridx, int gridy, int gridwidth, int gridheight) { this.gridx = gridx; this.gridy = gridy; this.gridwidth = gridwidth; this.gridheight = gridheight; } /** * Sets the anchor. * * @param anchor the anchor value * @return this object for further modification */ public GBC setAnchor(int anchor) { this.anchor = anchor; return this; } /** * Sets the fill direction. * * @param fill the fill direction * @return this object for further modification */ public GBC setFill(int fill) { this.fill = fill; return this; } /** * Sets the cell weights. * * @param weightx the cell weight in x-direction * @param weighty the cell weight in y-direction * @return this object for further modification */ public GBC setWeight(double weightx, double weighty) { this.weightx = weightx; this.weighty = weighty; return this; } /** * Sets the insets of this cell. * * @param distance the spacing to use in all directions * @return this object for further modification */ public GBC setInsets(int distance) { this.insets = new Insets(distance, distance, distance, distance); return this; } /** * Sets the insets of this cell. * * @param top the spacing to use on top * @param left the spacing to use to the left * @param bottom the spacing to use on the bottom * @param right the spacing to use to the right * @return this object for further modification */ public GBC setInsets(int top, int left, int bottom, int right) { this.insets = new Insets(top, left, bottom, right); return this; } /** * Sets the internal padding * * @param ipadx the internal padding in x-direction * @param ipady the internal padding in y-direction * @return this object for further modification */ public GBC setIpad(int ipadx, int ipady) { this.ipadx = ipadx; this.ipady = ipady; return this; } }
package gridbag; import java.awt.Font; import java.awt.GridBagLayout; import java.awt.event.ActionListener; import javax.swing.BorderFactory; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JTextArea; /** * A frame that uses a grid bag layout to arrange font selection components. */ public class FontFrame extends JFrame { public static final int TEXT_ROWS = 10; public static final int TEXT_COLUMNS = 20; private JComboBox<String> face; private JComboBox<Integer> size; private JCheckBox bold; private JCheckBox italic; private JTextArea sample; public FontFrame() { GridBagLayout layout = new GridBagLayout(); setLayout(layout); ActionListener listener = event -> updateSample(); // construct components JLabel faceLabel = new JLabel("Face: "); face = new JComboBox<>(new String[] { "Serif", "SansSerif", "Monospaced", "Dialog", "DialogInput" }); face.addActionListener(listener); JLabel sizeLabel = new JLabel("Size: "); size = new JComboBox<>(new Integer[] { 8, 10, 12, 15, 18, 24, 36, 48 }); size.addActionListener(listener); bold = new JCheckBox("Bold"); bold.addActionListener(listener); italic = new JCheckBox("Italic"); italic.addActionListener(listener); sample = new JTextArea(TEXT_ROWS, TEXT_COLUMNS); sample.setText("The quick brown fox jumps over the lazy dog"); sample.setEditable(false); sample.setLineWrap(true); sample.setBorder(BorderFactory.createEtchedBorder()); // add components to grid, using GBC convenience class add(faceLabel, new GBC(0, 0).setAnchor(GBC.EAST)); add(face, new GBC(1, 0).setFill(GBC.HORIZONTAL).setWeight(100, 0).setInsets(1)); add(sizeLabel, new GBC(0, 1).setAnchor(GBC.EAST)); add(size, new GBC(1, 1).setFill(GBC.HORIZONTAL).setWeight(100, 0).setInsets(1)); add(bold, new GBC(0, 2, 2, 1).setAnchor(GBC.CENTER).setWeight(100, 100)); add(italic, new GBC(0, 3, 2, 1).setAnchor(GBC.CENTER).setWeight(100, 100)); add(sample, new GBC(2, 0, 1, 4).setFill(GBC.BOTH).setWeight(100, 100)); pack(); updateSample(); } public void updateSample() { String fontFace = (String) face.getSelectedItem(); int fontStyle = (bold.isSelected() ? Font.BOLD : 0) + (italic.isSelected() ? Font.ITALIC : 0); int fontSize = size.getItemAt(size.getSelectedIndex()); Font font = new Font(fontFace, fontStyle, fontSize); sample.setFont(font); sample.repaint(); } }
package groupLayout; import java.awt.EventQueue; import javax.swing.JFrame; /** * @version 1.01 2015-06-12 * @author Cay Horstmann */ public class GroupLayoutTest { public static void main(String[] args) { EventQueue.invokeLater(() -> { JFrame frame = new FontFrame(); frame.setTitle("GroupLayoutTest"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } }
package groupLayout; import java.awt.Font; import java.awt.event.ActionListener; import javax.swing.BorderFactory; import javax.swing.GroupLayout; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.LayoutStyle; import javax.swing.SwingConstants; /** * A frame that uses a group layout to arrange font selection components. */ public class FontFrame extends JFrame { public static final int TEXT_ROWS = 10; public static final int TEXT_COLUMNS = 20; private JComboBox<String> face; private JComboBox<Integer> size; private JCheckBox bold; private JCheckBox italic; private JScrollPane pane; private JTextArea sample; public FontFrame() { ActionListener listener = event -> updateSample(); // construct components JLabel faceLabel = new JLabel("Face: "); face = new JComboBox<>(new String[] { "Serif", "SansSerif", "Monospaced", "Dialog", "DialogInput" }); face.addActionListener(listener); JLabel sizeLabel = new JLabel("Size: "); size = new JComboBox<>(new Integer[] { 8, 10, 12, 15, 18, 24, 36, 48 }); size.addActionListener(listener); bold = new JCheckBox("Bold"); bold.addActionListener(listener); italic = new JCheckBox("Italic"); italic.addActionListener(listener); sample = new JTextArea(TEXT_ROWS, TEXT_COLUMNS); sample.setText("The quick brown fox jumps over the lazy dog"); sample.setEditable(false); sample.setLineWrap(true); sample.setBorder(BorderFactory.createEtchedBorder()); pane = new JScrollPane(sample); GroupLayout layout = new GroupLayout(getContentPane()); setLayout(layout); layout.setHorizontalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup().addContainerGap() .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) .addGroup(GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGroup(layout.createParallelGroup(GroupLayout.Alignment.TRAILING) .addComponent(faceLabel).addComponent(sizeLabel)) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING, false) .addComponent(size).addComponent(face))) .addComponent(italic).addComponent(bold)) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED).addComponent(pane).addContainerGap())); layout.linkSize(SwingConstants.HORIZONTAL, new java.awt.Component[] { face, size }); layout.setVerticalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup().addContainerGap() .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) .addComponent(pane, GroupLayout.Alignment.TRAILING) .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) .addComponent(face).addComponent(faceLabel)) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) .addComponent(size).addComponent(sizeLabel)) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) .addComponent(italic, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED).addComponent(bold, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) .addContainerGap())); pack(); } public void updateSample() { String fontFace = (String) face.getSelectedItem(); int fontStyle = (bold.isSelected() ? Font.BOLD : 0) + (italic.isSelected() ? Font.ITALIC : 0); int fontSize = size.getItemAt(size.getSelectedIndex()); Font font = new Font(fontFace, fontStyle, fontSize); sample.setFont(font); sample.repaint(); } }
測試程序11
l 在elipse IDE中調試運行教材539頁程序12-1三、12-14,結合運行結果理解程序;
l 掌握定製佈局管理器的用法。
l 記錄示例代碼閱讀理解中存在的問題與疑惑。
package circleLayout; import java.awt.*; import javax.swing.*; /** * @version 1.33 2015-06-12 * @author Cay Horstmann */ public class CircleLayoutTest { public static void main(String[] args) { EventQueue.invokeLater(() -> { JFrame frame = new CircleLayoutFrame(); frame.setTitle("CircleLayoutTest"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } }
package circleLayout; import javax.swing.*; /** * A frame that shows buttons arranged along a circle. */ public class CircleLayoutFrame extends JFrame { public CircleLayoutFrame() { setLayout(new CircleLayout()); add(new JButton("Yellow")); add(new JButton("Blue")); add(new JButton("Red")); add(new JButton("Green")); add(new JButton("Orange")); add(new JButton("Fuchsia")); add(new JButton("Indigo")); pack(); } }
package circleLayout; import java.awt.*; /** * A layout manager that lays out components along a circle. */ public class CircleLayout implements LayoutManager { private int minWidth = 0; private int minHeight = 0; private int preferredWidth = 0; private int preferredHeight = 0; private boolean sizesSet = false; private int maxComponentWidth = 0; private int maxComponentHeight = 0; public void addLayoutComponent(String name, Component comp) { } public void removeLayoutComponent(Component comp) { } public void setSizes(Container parent) { if (sizesSet) return; int n = parent.getComponentCount(); preferredWidth = 0; preferredHeight = 0; minWidth = 0; minHeight = 0; maxComponentWidth = 0; maxComponentHeight = 0; // compute the maximum component widths and heights // and set the preferred size to the sum of the component sizes. for (int i = 0; i < n; i++) { Component c = parent.getComponent(i); if (c.isVisible()) { Dimension d = c.getPreferredSize(); maxComponentWidth = Math.max(maxComponentWidth, d.width); maxComponentHeight = Math.max(maxComponentHeight, d.height); preferredWidth += d.width; preferredHeight += d.height; } } minWidth = preferredWidth / 2; minHeight = preferredHeight / 2; sizesSet = true; } public Dimension preferredLayoutSize(Container parent) { setSizes(parent); Insets insets = parent.getInsets(); int width = preferredWidth + insets.left + insets.right; int height = preferredHeight + insets.top + insets.bottom; return new Dimension(width, height); } public Dimension minimumLayoutSize(Container parent) { setSizes(parent); Insets insets = parent.getInsets(); int width = minWidth + insets.left + insets.right; int height = minHeight + insets.top + insets.bottom; return new Dimension(width, height); } public void layoutContainer(Container parent) { setSizes(parent); // compute center of the circle Insets insets = parent.getInsets(); int containerWidth = parent.getSize().width - insets.left - insets.right; int containerHeight = parent.getSize().height - insets.top - insets.bottom; int xcenter = insets.left + containerWidth / 2; int ycenter = insets.top + containerHeight / 2; // compute radius of the circle int xradius = (containerWidth - maxComponentWidth) / 2; int yradius = (containerHeight - maxComponentHeight) / 2; int radius = Math.min(xradius, yradius); // lay out components along the circle int n = parent.getComponentCount(); for (int i = 0; i < n; i++) { Component c = parent.getComponent(i); if (c.isVisible()) { double angle = 2 * Math.PI * i / n; // center point of component int x = xcenter + (int) (Math.cos(angle) * radius); int y = ycenter + (int) (Math.sin(angle) * radius); // move component so that its center is (x, y) // and its size is its preferred size Dimension d = c.getPreferredSize(); c.setBounds(x - d.width / 2, y - d.height / 2, d.width, d.height); } } } }
測試程序12
l 在elipse IDE中調試運行教材544頁程序12-1五、12-16,結合運行結果理解程序;
l 掌握選項對話框的用法。
l 記錄示例代碼閱讀理解中存在的問題與疑惑。
package optionDialog; import java.awt.*; import javax.swing.*; /** * @version 1.34 2015-06-12 * @author Cay Horstmann */ public class OptionDialogTest { public static void main(String[] args) { EventQueue.invokeLater(() -> { JFrame frame = new OptionDialogFrame(); frame.setTitle("OptionDialogTest");//設置窗體標題 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//設置用戶在窗體上發起 "close" 時默認執行的操做 frame.setVisible(true);//設置窗口可見 }); } }
package optionDialog; import java.awt.*; import java.awt.event.*; import java.awt.geom.*; import java.util.*; import javax.swing.*; /** * A frame that contains settings for selecting various option dialogs. */ public class OptionDialogFrame extends JFrame { private ButtonPanel typePanel; private ButtonPanel messagePanel; private ButtonPanel messageTypePanel; private ButtonPanel optionTypePanel; private ButtonPanel optionsPanel; private ButtonPanel inputPanel; private String messageString = "Message"; private Icon messageIcon = new ImageIcon("blue-ball.gif"); private Object messageObject = new Date(); private Component messageComponent = new SampleComponent(); public OptionDialogFrame() { JPanel gridPanel = new JPanel(); gridPanel.setLayout(new GridLayout(2, 3));//建立2行3列的網格佈局 typePanel = new ButtonPanel("Type", "Message", "Confirm", "Option", "Input"); messageTypePanel = new ButtonPanel("Message Type", "ERROR_MESSAGE", "INFORMATION_MESSAGE", "WARNING_MESSAGE", "QUESTION_MESSAGE", "PLAIN_MESSAGE"); messagePanel = new ButtonPanel("Message", "String", "Icon", "Component", "Other", "Object[]"); optionTypePanel = new ButtonPanel("Confirm", "DEFAULT_OPTION", "YES_NO_OPTION", "YES_NO_CANCEL_OPTION", "OK_CANCEL_OPTION"); optionsPanel = new ButtonPanel("Option", "String[]", "Icon[]", "Object[]"); inputPanel = new ButtonPanel("Input", "Text field", "Combo box"); gridPanel.add(typePanel); gridPanel.add(messageTypePanel); gridPanel.add(messagePanel); gridPanel.add(optionTypePanel); gridPanel.add(optionsPanel); gridPanel.add(inputPanel);//添加按鈕 // add a panel with a Show button JPanel showPanel = new JPanel(); JButton showButton = new JButton("Show");//建立一個帶"Show"的按鈕。 showButton.addActionListener(new ShowAction()); showPanel.add(showButton); add(gridPanel, BorderLayout.CENTER);//中間區域的佈局約束(容器中央)。 add(showPanel, BorderLayout.SOUTH);//南區域的佈局約束(容器底部)。 pack(); } /** * Gets the currently selected message. * * @return a string, icon, component, or object array, depending on the Message * panel selection */ public Object getMessage() { String s = messagePanel.getSelection(); if (s.equals("String"))//將此字符串與指定的對象比較 return messageString; else if (s.equals("Icon")) return messageIcon; else if (s.equals("Component")) return messageComponent; else if (s.equals("Object[]")) return new Object[] { messageString, messageIcon, messageComponent, messageObject }; else if (s.equals("Other")) return messageObject; else return null; } /** * Gets the currently selected options. * * @return an array of strings, icons, or objects, depending on the Option panel * selection */ public Object[] getOptions() { String s = optionsPanel.getSelection(); if (s.equals("String[]")) return new String[] { "Yellow", "Blue", "Red" }; else if (s.equals("Icon[]")) return new Icon[] { new ImageIcon("yellow-ball.gif"), new ImageIcon("blue-ball.gif"), new ImageIcon("red-ball.gif") }; else if (s.equals("Object[]")) return new Object[] { messageString, messageIcon, messageComponent, messageObject }; else return null; } /** * Gets the selected message or option type * * @param panel the Message Type or Confirm panel * @return the selected XXX_MESSAGE or XXX_OPTION constant from the JOptionPane * class */ public int getType(ButtonPanel panel) { String s = panel.getSelection(); try { return JOptionPane.class.getField(s).getInt(null); } catch (Exception e) { return -1; } } /** * The action listener for the Show button shows a Confirm, Input, Message, or * Option dialog depending on the Type panel selection. */ private class ShowAction implements ActionListener { public void actionPerformed(ActionEvent event) { if (typePanel.getSelection().equals("Confirm")) JOptionPane.showConfirmDialog(OptionDialogFrame.this, getMessage(), "Title", getType(optionTypePanel), getType(messageTypePanel)); else if (typePanel.getSelection().equals("Input")) { if (inputPanel.getSelection().equals("Text field")) JOptionPane.showInputDialog(OptionDialogFrame.this, getMessage(), "Title", getType(messageTypePanel)); else JOptionPane.showInputDialog(OptionDialogFrame.this, getMessage(), "Title", getType(messageTypePanel), null, new String[] { "Yellow", "Blue", "Red" }, "Blue"); } else if (typePanel.getSelection().equals("Message")) JOptionPane.showMessageDialog(OptionDialogFrame.this, getMessage(), "Title", getType(messageTypePanel)); else if (typePanel.getSelection().equals("Option")) JOptionPane.showOptionDialog(OptionDialogFrame.this, getMessage(), "Title", getType(optionTypePanel), getType(messageTypePanel), null, getOptions(), getOptions()[0]); } } } /** * A component with a painted surface */ class SampleComponent extends JComponent { public void paintComponent(Graphics g) { Graphics2D g2 = (Graphics2D) g; Rectangle2D rect = new Rectangle2D.Double(0, 0, getWidth() - 1, getHeight() - 1);//根據指定的 double 座標構造和初始化 Rectangle2D g2.setPaint(Color.YELLOW); g2.fill(rect); g2.setPaint(Color.BLUE); g2.draw(rect); } public Dimension getPreferredSize() { return new Dimension(10, 10);//構造一個 Dimension,並將其初始化爲指定寬度和高度。 } }
package optionDialog; import javax.swing.*; /** * A panel with radio buttons inside a titled border. */ public class ButtonPanel extends JPanel { private ButtonGroup group; /** * Constructs a button panel. * * @param title the title shown in the border * @param options an array of radio button labels */ public ButtonPanel(String title, String... options) { setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), title));//設置組件的邊框,向現有邊框添加一個標題 setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));//從上到下垂直佈置組件 group = new ButtonGroup(); // make one radio button for each option for (String option : options) { JRadioButton b = new JRadioButton(option);//建立一個具備指定文本的狀態爲未選擇的單選按鈕 b.setActionCommand(option);//設置此按鈕的動做命令 add(b); group.add(b);//將按鈕添加到組中 b.setSelected(option == options[0]);//設置按鈕的狀態 } } /** * Gets the currently selected option. * * @return the label of the currently selected radio button. */ public String getSelection() { return group.getSelection().getActionCommand();//返回該按鈕的動做命令字符串 } }
測試程序13
l 在elipse IDE中調試運行教材552頁程序12-1七、12-18,結合運行結果理解程序;
l 掌握對話框的建立方法;
l 記錄示例代碼閱讀理解中存在的問題與疑惑。
package dialog; import java.awt.*; import javax.swing.*; /** * @version 1.34 2012-06-12 * @author Cay Horstmann */ public class DialogTest { public static void main(String[] args) { EventQueue.invokeLater(() -> { JFrame frame = new DialogFrame(); frame.setTitle("DialogTest"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } }
package dialog; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; /** * A frame with a menu whose File->About action shows a dialog. */ public class DialogFrame extends JFrame { private static final int DEFAULT_WIDTH = 300; private static final int DEFAULT_HEIGHT = 200; private AboutDialog dialog; public DialogFrame() { setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); // Construct a File menu. JMenuBar menuBar = new JMenuBar(); setJMenuBar(menuBar); JMenu fileMenu = new JMenu("File"); menuBar.add(fileMenu); // Add About and Exit menu items. // The About item shows the About dialog. JMenuItem aboutItem = new JMenuItem("About"); aboutItem.addActionListener(event -> { if (dialog == null) // first time dialog = new AboutDialog(DialogFrame.this); dialog.setVisible(true); // pop up dialog }); fileMenu.add(aboutItem); // The Exit item exits the program. JMenuItem exitItem = new JMenuItem("Exit"); exitItem.addActionListener(event -> System.exit(0)); fileMenu.add(exitItem); } }
package dialog; import java.awt.BorderLayout; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; /** * A sample modal dialog that displays a message and waits for the user to click * the OK button. */ public class AboutDialog extends JDialog { public AboutDialog(JFrame owner) { super(owner, "About DialogTest", true); // add HTML label to center add(new JLabel("<html><h1><i>Core Java</i></h1><hr>By Cay Horstmann</html>"), BorderLayout.CENTER); // OK button closes the dialog JButton ok = new JButton("OK"); ok.addActionListener(event -> setVisible(false)); // add OK button to southern border JPanel panel = new JPanel(); panel.add(ok); add(panel, BorderLayout.SOUTH); pack(); } }
測試程序14
l 在elipse IDE中調試運行教材556頁程序12-1九、12-20,結合運行結果理解程序;
l 掌握對話框的數據交換用法;
l 記錄示例代碼閱讀理解中存在的問題與疑惑。
package dataExchange; import java.awt.*; import javax.swing.*; /** * @version 1.34 2015-06-12 * @author Cay Horstmann */ public class DataExchangeTest { public static void main(String[] args) { EventQueue.invokeLater(() -> { JFrame frame = new DataExchangeFrame(); frame.setTitle("DataExchangeTest"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } }
package dataExchange; /** * A user has a name and password. For security reasons, the password is stored * as a char[], not a String. */ public class User { private String name; private char[] password; public User(String aName, char[] aPassword) { name = aName; password = aPassword; } public String getName() { return name; } public char[] getPassword() { return password; } public void setName(String aName) { name = aName; } public void setPassword(char[] aPassword) { password = aPassword; } }
package dataExchange; import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * A frame with a menu whose File->Connect action shows a password dialog. */ public class DataExchangeFrame extends JFrame { public static final int TEXT_ROWS = 20; public static final int TEXT_COLUMNS = 40; private PasswordChooser dialog = null; private JTextArea textArea; public DataExchangeFrame() { // construct a File menu JMenuBar mbar = new JMenuBar(); setJMenuBar(mbar); JMenu fileMenu = new JMenu("File"); mbar.add(fileMenu); // add Connect and Exit menu items JMenuItem connectItem = new JMenuItem("Connect"); connectItem.addActionListener(new ConnectAction()); fileMenu.add(connectItem); // The Exit item exits the program JMenuItem exitItem = new JMenuItem("Exit"); exitItem.addActionListener(event -> System.exit(0)); fileMenu.add(exitItem); textArea = new JTextArea(TEXT_ROWS, TEXT_COLUMNS); add(new JScrollPane(textArea), BorderLayout.CENTER); pack(); } /** * The Connect action pops up the password dialog. */ private class ConnectAction implements ActionListener { public void actionPerformed(ActionEvent event) { // if first time, construct dialog if (dialog == null) dialog = new PasswordChooser(); // set default values dialog.setUser(new User("yourname", null)); // pop up dialog if (dialog.showDialog(DataExchangeFrame.this, "Connect")) { // if accepted, retrieve user input User u = dialog.getUser(); textArea.append("user name = " + u.getName() + ", password = " + (new String(u.getPassword())) + "\n"); } } } }
package dataExchange; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Frame; import java.awt.GridLayout; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JPasswordField; import javax.swing.JTextField; import javax.swing.SwingUtilities; /** * A password chooser that is shown inside a dialog */ public class PasswordChooser extends JPanel { private JTextField username; private JPasswordField password; private JButton okButton; private boolean ok; private JDialog dialog; public PasswordChooser() { setLayout(new BorderLayout()); // construct a panel with user name and password fields JPanel panel = new JPanel(); panel.setLayout(new GridLayout(2, 2)); panel.add(new JLabel("User name:")); panel.add(username = new JTextField("")); panel.add(new JLabel("Password:")); panel.add(password = new JPasswordField("")); add(panel, BorderLayout.CENTER); // create Ok and Cancel buttons that terminate the dialog okButton = new JButton("Ok"); okButton.addActionListener(event -> { ok = true; dialog.setVisible(false); }); JButton cancelButton = new JButton("Cancel"); cancelButton.addActionListener(event -> dialog.setVisible(false)); // add buttons to southern border JPanel buttonPanel = new JPanel(); buttonPanel.add(okButton); buttonPanel.add(cancelButton); add(buttonPanel, BorderLayout.SOUTH); } /** * Sets the dialog defaults. * * @param u the default user information */ public void setUser(User u) { username.setText(u.getName()); } /** * Gets the dialog entries. * * @return a User object whose state represents the dialog entries */ public User getUser() { return new User(username.getText(), password.getPassword()); } /** * Show the chooser panel in a dialog * * @param parent a component in the owner frame or null * @param title the dialog window title */ public boolean showDialog(Component parent, String title) { ok = false; // locate the owner frame Frame owner = null; if (parent instanceof Frame) owner = (Frame) parent; else owner = (Frame) SwingUtilities.getAncestorOfClass(Frame.class, parent); // if first time, or if owner has changed, make new dialog if (dialog == null || dialog.getOwner() != owner) { dialog = new JDialog(owner, true); dialog.add(this); dialog.getRootPane().setDefaultButton(okButton); dialog.pack(); } // set title and show dialog dialog.setTitle(title); dialog.setVisible(true); return ok; } }
測試程序15
l 在elipse IDE中調試運行教材556頁程序12-2一、12-2212-23,結合程序運行結果理解程序;
l 掌握文件對話框的用法;
l 記錄示例代碼閱讀理解中存在的問題與疑惑。
package fileChooser; import java.awt.*; import javax.swing.*; /** * @version 1.25 2015-06-12 * @author Cay Horstmann */ public class FileChooserTest { public static void main(String[] args) { EventQueue.invokeLater(() -> { JFrame frame = new ImageViewerFrame(); frame.setTitle("FileChooserTest"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } }
package fileChooser; import java.io.*; import javax.swing.*; import javax.swing.filechooser.*; import javax.swing.filechooser.FileFilter; /** * A file view that displays an icon for all files that match a file filter. */ public class FileIconView extends FileView { private FileFilter filter; private Icon icon; /** * Constructs a FileIconView. * * @param aFilter a file filter--all files that this filter accepts will be * shown with the icon. * @param anIcon--the icon shown with all accepted files. */ public FileIconView(FileFilter aFilter, Icon anIcon) { filter = aFilter; icon = anIcon; } public Icon getIcon(File f) { if (!f.isDirectory() && filter.accept(f)) return icon; else return null; } }
package fileChooser; import java.awt.*; import java.io.*; import javax.swing.*; /** * A file chooser accessory that previews images. */ public class ImagePreviewer extends JLabel { /** * Constructs an ImagePreviewer. * * @param chooser the file chooser whose property changes trigger an image * change in this previewer */ public ImagePreviewer(JFileChooser chooser) { setPreferredSize(new Dimension(100, 100)); setBorder(BorderFactory.createEtchedBorder()); chooser.addPropertyChangeListener(event -> { if (event.getPropertyName() == JFileChooser.SELECTED_FILE_CHANGED_PROPERTY) { // the user has selected a new file File f = (File) event.getNewValue(); if (f == null) { setIcon(null); return; } // read the image into an icon ImageIcon icon = new ImageIcon(f.getPath()); // if the icon is too large to fit, scale it if (icon.getIconWidth() > getWidth()) icon = new ImageIcon(icon.getImage().getScaledInstance(getWidth(), -1, Image.SCALE_DEFAULT)); setIcon(icon); } }); } }
package fileChooser; import java.io.*; import javax.swing.*; import javax.swing.filechooser.*; import javax.swing.filechooser.FileFilter; /** * A frame that has a menu for loading an image and a display area for the * loaded image. */ public class ImageViewerFrame extends JFrame { private static final int DEFAULT_WIDTH = 300; private static final int DEFAULT_HEIGHT = 400; private JLabel label; private JFileChooser chooser; public ImageViewerFrame() { setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); // set up menu bar JMenuBar menuBar = new JMenuBar(); setJMenuBar(menuBar); JMenu menu = new JMenu("File"); menuBar.add(menu); JMenuItem openItem = new JMenuItem("Open"); menu.add(openItem); openItem.addActionListener(event -> { chooser.setCurrentDirectory(new File(".")); // show file chooser dialog int result = chooser.showOpenDialog(ImageViewerFrame.this); // if image file accepted, set it as icon of the label if (result == JFileChooser.APPROVE_OPTION) { String name = chooser.getSelectedFile().getPath(); label.setIcon(new ImageIcon(name)); pack(); } }); JMenuItem exitItem = new JMenuItem("Exit"); menu.add(exitItem); exitItem.addActionListener(event -> System.exit(0)); // use a label to display the images label = new JLabel(); add(label); // set up file chooser chooser = new JFileChooser(); // accept all image files ending with .jpg, .jpeg, .gif FileFilter filter = new FileNameExtensionFilter("Image files", "jpg", "jpeg", "gif"); chooser.setFileFilter(filter); chooser.setAccessory(new ImagePreviewer(chooser)); chooser.setFileView(new FileIconView(filter, new ImageIcon("palette.gif"))); } }
測試程序16
l 在elipse IDE中調試運行教材570頁程序12-24,結合運行結果理解程序;
l 瞭解顏色選擇器的用法。
l 記錄示例代碼閱讀理解中存在的問題與疑惑。
package colorChooser; import java.awt.*; import javax.swing.*; /** * @version 1.04 2015-06-12 * @author Cay Horstmann */ public class ColorChooserTest { public static void main(String[] args) { EventQueue.invokeLater(() -> { JFrame frame = new ColorChooserFrame(); frame.setTitle("ColorChooserTest"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } }
package colorChooser; import javax.swing.*; /** * A frame with a color chooser panel */ public class ColorChooserFrame extends JFrame { private static final int DEFAULT_WIDTH = 300; private static final int DEFAULT_HEIGHT = 200; public ColorChooserFrame() { setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); // add color chooser panel to frame ColorChooserPanel panel = new ColorChooserPanel(); add(panel); } }
package colorChooser; import java.awt.Color; import java.awt.Frame; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JColorChooser; import javax.swing.JDialog; import javax.swing.JPanel; /** * A panel with buttons to pop up three types of color choosers */ public class ColorChooserPanel extends JPanel { public ColorChooserPanel() { JButton modalButton = new JButton("Modal"); modalButton.addActionListener(new ModalListener()); add(modalButton); JButton modelessButton = new JButton("Modeless"); modelessButton.addActionListener(new ModelessListener()); add(modelessButton); JButton immediateButton = new JButton("Immediate"); immediateButton.addActionListener(new ImmediateListener()); add(immediateButton); } /** * This listener pops up a modal color chooser */ private class ModalListener implements ActionListener { public void actionPerformed(ActionEvent event) { Color defaultColor = getBackground(); Color selected = JColorChooser.showDialog(ColorChooserPanel.this, "Set background", defaultColor); if (selected != null) setBackground(selected); } } /** * This listener pops up a modeless color chooser. The panel color is changed * when the user clicks the OK button. */ private class ModelessListener implements ActionListener { private JDialog dialog; private JColorChooser chooser; public ModelessListener() { chooser = new JColorChooser(); dialog = JColorChooser.createDialog(ColorChooserPanel.this, "Background Color", false /* not modal */, chooser, event -> setBackground(chooser.getColor()), null /* no Cancel button listener */); } public void actionPerformed(ActionEvent event) { chooser.setColor(getBackground()); dialog.setVisible(true); } } /** * This listener pops up a modeless color chooser. The panel color is changed * immediately when the user picks a new color. */ private class ImmediateListener implements ActionListener { private JDialog dialog; private JColorChooser chooser; public ImmediateListener() { chooser = new JColorChooser(); chooser.getSelectionModel().addChangeListener(event -> setBackground(chooser.getColor())); dialog = new JDialog((Frame) null, false /* not modal */); dialog.add(chooser); dialog.pack(); } public void actionPerformed(ActionEvent event) { chooser.setColor(getBackground()); dialog.setVisible(true); } } }
實驗2:組內討論反思本組負責程序,理解程序整體結構,梳理程序GUI設計中應用的相關組件,整理相關組件的API,對程序中組件應用的相關代碼添加註釋。
實驗3:組間協同窗習:在本班課程QQ羣內,各位同窗對實驗1中存在的問題進行提問,提問時註明實驗1中的測試程序編號,負責對應程序的小組需及時對羣內提問進行回答。
三:實驗總結:
此次實驗量比較多,知識點較多,學起來比較費勁,經過小組討論,更好的解讀代碼,分工合做自主學習,小組討論分享本身所瞭解的知識,對學習有很大的幫助,但對有些知識理解還不夠透徹。