Java核心技術(卷I)讀書筆記 第七~九章
GUI
Chapter 7 圖形程序設計
- Swing概述:抽象窗口工具箱( Abstract Windoe Toolkit ) AWT. Swing已經是Java基礎類庫( Java Foundamental Class JFC) 的一部分了。Swing類位於 javax.swing包中,javax表示這是一個Java擴展包。所有的Swing組件都由事件分配線程(event dispatch thread)進行配置,線程將鼠標點擊和按鍵控制轉移到用戶接口組件。
- 框架Frame:在Java中頂層窗口被稱爲框架。默認情況下,框架的大小爲 0*0,框架起初是不可見的,調用 setVisible(true)。JFrame類繼承了許多用於處理框架大小和位置的方法:
- setLocation(int x, int y),setBounds(int x, int y, int width, int height):用於設置框架的位置。
- SetIconImage(Image image)用於告訴窗口系統在標題欄、任務切換窗口等位置顯示那個圖標。
- setTitle(String name):用於改變標題欄的文字。
- setResizable(boolean b):利用boolean
- 值確定框架的大小是否允許用戶改變。
確定合適的框架的大小:
Toolkit kit = Toolkit.getDefaultToolkit(); //調用Toolkit類的靜態方法返回一個Toolkit對象// Dimension screenSize = kit.getScreenSize(); //getScreenSize以Dimension對象的方式返回屏幕的大小 int screenWidth = screenSize.width; int screenHeight = screenSize.height;
組件:繪製一個組件,需要定義一個擴展JComponent的類,並覆蓋其中的paintComponent方法。其中有一個Graphics類型的參數,在Java中所有的繪製都必須使用Graphics對象,包含了繪製圖案、圖像和文本的方法。只要窗口需要重新繪圖,事件處理器就會通告組件,從而引發執行所有組件的paintComponent方法,所以一定不要自己調用paintComponent方法。
顯示文本是一種特殊的繪圖,在Graphics有一個drawString方法,g.drawString(text, x, y);
覆蓋getPreferredSize()方法,返回一個有首選項寬度和高度的Dimension類對象,告訴用戶組件有多大。
當框架中填入一個或多個組件時,如果只想使用它們的首選大小,就可以調用pack()方法。
使用frame.add(Component C):將給定的組件添加到給框架的內容窗格中。- 處理2D圖形:要想繪製圖形,首先要創建一個實現了Shape接口類的對象,然後調用Graphics2D類的draw方法。
使用顏色:可以使用Graphics2D類的setPaint(Paint p)方法可以爲圖形環境上的所有後續繪製操作選擇顏色。`g.setPaint(Color.RED);
只需要將draw替換爲fill(Shape S) 就可以用一種顏色填充一個封閉圖形。
Color類用於定義顏色,在java.awt.Color類中提供了13個預定義的常量,分別表示13中標準顏色。可以使用 0~255之間的紅綠藍三種顏色來創建一個Color對象。
可以使用Component的setBackground(Color c)設置背景顏色。
Java在 SystemColor 中預定義了很多顏色的名字,其中的常量封裝了用戶系統的各個元素的顏色。 - 特殊字體:人們可以通過字體名( font face name) 指定一種字體,字體名由字體家族名(font family name) 和 一個可選的 “Bold”後綴組成。
- 要想使用某種字體繪製字符,必須首先利用制定的字體名、字體風格和字體大小來創建一個Font類對象。
Font sansbold14 = new Font("SansSerif", Font.BOLD, 14);
其中字體的風格有Font.PLAIN, Font.BOLD, Font.ITALIC。
可以使用deriveFont(Float f)方法得到希望的字體大小。
有關包圍字符串的矩形:基線( baseline )是一條虛構的線,上坡度( ascent )是從基線到坡頂( ascenter )的距離,下坡度( decenter )是從基線到破敵( descenter )的距離。行間距( leading )
是某一行的坡底到其下一行的坡頂的距離,字體的高度是連續兩個基線的距離。 - 顯示圖像:可以是哦用ImageIcon類
Image image = new ImageIcon(filename).getImage();
Chapter 8 事件處理
- 事件過程 event procedure:程序員將相應的特定事件編寫代碼,並將這些代碼放置在過程中。事件源 event source,事件監聽器 event listener。監聽器對象是實現了特定監聽器接口的類的實例,監聽器必須有一個被稱爲actionPerformed的方法,接收一個actionEvent參數。事件源是一個能夠註冊監聽器對象併發送事件對象的對象。
- 動態改變觀感:調用靜態UIManager.setLookAndFeel方法,並提供所想要的觀感類名,然後再調用SwingUtilities.updateComponentTreeUI刷新全部的組件集。
- 適配器類:窗口佳寧器必須是實現WindowListener接口的類的一個對象。
- Action接口:用來封裝命令,將他們連接到多個事件源上。
- void actionPerformed(ActionListener event):Action擴展語ActionListener接口。
- void setEnabled(boolean b)
- boolean isEnabled(): 這兩個方法允許啓用或者禁用這個動作,並檢查這個動作時候當前可用。
- putValue, getValue:這兩個方法允許存儲和檢索動作對象中的任意值/名。其中Action.NAME 和 Action.SAMLL_ICON 將動作的名字和圖標存儲到一個動作對象中。如果將動作對象添加到菜單或者工具欄中,它的名稱和圖標就會自動被提取出來。
Aciton.putValue(Action.NAME, "Blue");
Action.putValue(Action.SAMLL_ICON, new ImageIcon("blue-ball.gif"));
- addPropertyChangeListener, removePropertyChangeListener:這兩個方法能讓其他對象在動作對象的屬性發生 變化時得到通知。
有一個類實現了除ActionListener外的所有接口,叫做AbstractAction。
- 將動作和擊鍵關聯起來要生成KeyStroke對象,可以條用KeyStroke類的靜態getKeyStroke方法。
KeyStroke ctrlBKey = keyStroke.getKeyStroke("ctrl B");
- KeyBoard Focus:當用戶敲擊鍵盤時,這個動作就會被髮送給擁有焦點的組件。通常具有焦點的組件就會明顯感受到。每個JComponent有三個輸入映射,每個映射的KeyStroke對象都與動作關聯。
- WHEN_FOCUSED:當這個組件擁有鍵盤焦點
- WHEN_ANCESTOR_OF_FOCUSED_COMPONENT:當這個組件包含了擁有焦點的組件。
- WHEN_IN_FOCUSED_WINDOW:當這個組件被包含在擁有焦點的窗口中。
按鍵處理將按照從上到下的順序進行,可以使用InputMap從組建中獲得輸入映射。InputMap imap = new InpurMap(Action.WHEN_FOCUSED);
InputMap先將KeyStroke對象映射到任意對象上,然後由ActionMap類實現將對象映射到動作的第二個映射。
imap.put(KeyStroke.getKeyStroke("ctrl Y"), "panel.yellow");
ActionMap amap = panel.getActionMap();
amap.put("panel.yellow", yellowAction);
習慣上使用字符串none表示空動作,用來去下一個按鍵動作。
imap.put(KeyStroke.getKeyStroke("ctrl Y"), "none");
接下來將這個動作和按鍵關聯起來,JButton有用Action作爲參數的構造器
JButton blueButton = new JButton(yellowButton);
- 鼠標事件:當用戶點擊鼠標時,就會調用三個監聽器參數:鼠標第一次被調用時調用mousePressed, 鼠標被釋放時調用mouseReleased, 最後調用mouseClicked。
當鼠標移動時,有兩個獨立接口MouseListener 用於接收組件上“感興趣”的鼠標事件(按下、釋放、單擊、進入或離開)的偵聽器接口 和 MouseMotionLIstener接收鼠標移動事件的抽象適配器類。
只有鼠標在一個組件內部停留時纔會調用mouseMoved方法,即使鼠標拖動到組件外面,mouseDragged
方法也會被調用。另外,mouseEntered和mouseExited這兩個方法是在鼠標進入或移出組件時被調用。 - AWT事件繼承層次:事件對象封裝了事件源和監聽器彼此通信的時間信息。AWT將事件分爲低級( low-level )和語義( semantic )事件。語義時間表示用戶動作的事件,低級事件是形成那些事件的事件。
常用的5個低級事件是:KeyEvent、MouseEvent、MouseWheelEvent、FocusEvent和WindowEvent。
Chapter 9 Swing用戶界面組件
- 模型-視圖-控制器:設計模式。
- 流佈局管理器(flow layout mananger):是面板默認的佈局管理器。
- SetLayout(Layout Manager):爲容器設置佈局管理器
- add(Component C):將組件添加到容器中並返回其引用。
- FlowLayout(int align, int hgap, int vgap):構建一個系的FlowLayout對象,設置對齊,水平和垂直間距。
- 邊框佈局管理器(border layout manager):是JFrame內容窗格的默認佈局管理器。當容器被縮放時,邊緣組件的尺寸不會改變,而中間組建的大小會變化。添加組件時可以指定BorderLayout類中的CENTER、NORTH、SOUTH、EAST和WEST常量,默認爲CENTER。
邊框佈局會拓展所偶有的尺寸以填滿可用空間。 - 網格佈局(GridLayout):在網格佈局對象的構造器中需要指定行數和列數
panel.setLayout(new GridLayout(4, 4));
- 文本輸入:文本域(JTextField)只能接收單行的文本輸入,文本區(JTextArea)能夠接收多行的文本輸入。JPassword也只能接收單行文本輸入,但不會將輸入內容顯示出來。
JTextField textField = new JTextFirld("Default Input", 20);
panel.add(textField);
不提供字符串參數文本域就是空白。在示例中寬度之爲20列,一列就是在當前使用的字體下一個字符的寬度。應將最大輸入長度設爲在多設置1~2個字符。可使用textField.setColumns(5); panel.revalidate();
在運行時重新設置列數。revalidate()方法重新計算容器內所有組件大小並對他們重新佈局。
textField.getText().trim();
將返回的文本域的前後空格去掉。
textArea.setLineWrap(true);
開啓換行特性避免裁剪過長的行。 - 標籤:標籤是容納文本框的組件,沒有任何修飾符,也不響應用戶輸入。可以利用標籤標示組件:
- 用相應的文本構造一個JLAbel組件。
- 將標籤組件放置在距離需要標識的組件的足夠近的地方。
構造器可以指定初始文本和圖標,也可以選擇內容排列方式——用SwingConstants接口中幾個常量。
JLabel label = new Label("User name: ", SwingConstants.RIGHT);
- 密碼域:每個輸入的字符都是用回顯字符(echo character)顯示出來,JPasswordField類實現了這樣的功能。
setEchoChar(char echo)爲密碼域設置回顯字符。 - 滾動窗格:在Swing中,文本區沒有滾動條,需要將文本區插入到滾動窗格(scroll pane)中。
JScrollPane scrollPane = new JScrollPane(textArea)
- 選擇組件:複選框:複選框需要緊鄰的標籤來說明其用途
JCheckBox bold = new JCheckBox("Bold");
使用setSelect方法來選定或取消複選框
bold.setSelect(true);
isSelected方法返回每個複選框當前的狀態。 - 單選按鈕(Radio Button Group):爲按鈕組構造ButtonGroup對象,然後再將JRadioButton類型的對象加入到按鈕組中。仍需要進行佈局。
JRadioButton smallButton = new JRadioButton("Small", true);
第二個參數表明這個按鈕初始狀態是否被選擇。 - 邊框(borders):可以在任何繼承了JComponent的組件上應用邊框,最常用的用途是在一個面板周圍防止一個邊框,然後用其他洪湖街面元素填充邊框。方法
- 調用BorderFactory靜態方法創建邊框:凹斜面、凸斜面、蝕刻、直線和蒙刻。
- 可以給邊框添加標題,將邊框傳遞給BorderFactory.createTitledBorder。
- 調用BorderFactory.createCompoundBorder將邊框組合起來使用。
- 調用JComponent類中的setBorder方法將結果添加到組建中。
Border etched = BorderFactory.createEcthedBorder();
Border titled = BorderFactory.createTitledBorder(etched, "A Title");
panel.setBorder(etched);
- 組合框( Combo Box ):JComboBox類提供了組合框的組件。調用setEditable方法讓組合框可編輯。在JAva SE 7中,這個類是泛型類。調用getSelectedItem方法獲取當前的選項,如果組合框是可編輯的,那麼當前選項也是可編輯的。
JComboBox<String> facoCombo = new JComboBox<>();
faceCombo.addItem("Serif");
這個方法將字符串添加到列表的尾部。
faceCombo.insertItemAt("Monospaced", 0);
faceCombo.removeItem("Serif")
faceCombo.removeItemAt(0)
faceCombo.removeAllItems()
用於移除選項。
如果需要向組合框中添加大量選項,構造一個DefaultComboBoxModel,並調用addElement進行加載。然後再調用setModel方法。
用戶從組合框中選擇一個選項時,組合框就產生一個動作事件,調用getSource方法得到發送事件的組合框引用,接着調用getSelectedItem方法獲取當前選項。 - 滑動條:允許進行連續值的選擇。
JSlider slider = new JSlider(min, max, InitialValue);
默認值爲0, 100, 50。
如果使用垂直滑動條:
JSlider slider = new JSlider(SwingConstants.VERTICAL, min, max, InitialValue);
當滑動條的值發生改變時,ChangeEvent就會發送給所有變化的監聽器,爲了得到這些改變的通知,就要調用addChangeListener方法並且安裝了一個實現了ChangeListener接口的對象。
public void stateChange(ChangeEvent event){
JSlider slider = (JSlider)event.getSource();
int value = slider.getValue();
}
可以使用標尺(tick)對滑動條進行修飾。
slider.setMajorTickSpacing(20)
每20單位顯示一個大標尺。
slider.setMinTickSpacing(5)
每5個單位顯示一個小標尺。
可以強制滑動條對其標尺slider.setSnapToTicks(true);
可以使用slider.setPaintLabels(true)
爲大標尺添加標尺標記標籤(tick mark labels).
要想要隱藏滑動條移動的軌跡可以調用slider.setPaintTrack(false);
逆向滑動條slider.setInverted(true);
- 菜單:菜單欄(menu bar), 菜單項(menu items)和子菜單(submenu)。
首先創建一個菜單欄,可以添加到任何位置,通常放在菜單頂部。
JMenuBar menuBar = new JMenuBar();
frame.setMenuBar(menuBar);
將菜單添加到框架上
爲每一個菜單建立一個菜單對象
JMenu editMenu = new JMenu("Edit");
將頂層菜單加到菜單欄中
menuBar.add(editMenu);
向菜單中添加菜單項、分隔符和子菜單
JMenuItem pasteItem = new JMenuItem("Paste");
editMenu.add(pasteItem);
editMenu.setSeparator();
JMenu optionMenu = new ...;
editMenu.add(optionMenu);
可以使用JMenu.add(String s)
方法將菜單插入到菜單尾部。
當用戶選擇菜單時,會觸發一個動作事件。需要爲每一個菜單安裝動作監聽器。
將動作處理器添加到菜單項
JMenuItem exitItem = fileMenu.add(exitAction);
可利用JMenuItem(String, Icon)
或setIcon方法指定圖標。
可以將一個圖標添加到一個動作上,或者利用AbstractAction構造器社遏制圖標。
爲菜單項創建複選框。當用戶選擇一個菜單項時,菜單項就會自動在選擇與未選擇之間進行切換。
JCheckBoxMenuItem readonlyItem = new JCheckBoxMenuItem("Read-only");
optionMenu.add(readonlyItem);
爲菜單項添加單選按鈕,必須把它們加入按鈕組中。
ButtonGroup group = new ButtonGroup();
JRadioButtonMenuItem insertItem = new JRadioButtonMenuItem("Insert");
insertItem.setSelected(true);
group.add(InsertItem);
optionsMenu.add(InsertItem);
彈出菜單(pop-up menu):
創建一個彈出菜單與一般菜單類似,但是沒有標題。
JPopupMenu popup = new JPopupMenu();
用常規方法添加菜單項。
要調用show方法才能顯示菜單,須給出父組件和相對父組件的顯示位置。
popup.show(panel, x, y);
當用戶點擊某個鼠標鍵時彈出菜單,這就是所謂彈出式觸發器(pop-up trigger )在Windows中,彈出式觸發器是鼠標右鍵。
component.setComponentPopyoMenu(popup);
快捷鍵和加速器
通過在菜單項的構造器中制定一個快捷字母來爲菜單項設置快捷鍵。快捷鍵會自動顯示在菜單項中,並帶有一條下劃線。
JMenuItem aboutItem = new JMenuItem("About", "A");
如果有Action對象,就可以把快捷鍵作爲Action.MNEMONIC_KEY的鍵值添加到對象中。
cutAction.putValue(Action.MNEMONIC_KEY, new Integer('A'));
如果想爲菜單設置快捷鍵,就要調用setMnemonic()方法。
helpMenu.setMnemonic('H');
加速器是在不打開菜單的情況下選擇菜單項的快捷鍵。使用setAccelerator()方法將一個加速器關聯到一個菜單項上。加速器只能關聯到菜單項上,將直接激活菜單關聯的動作事件。
openItem.setAccelerator(KeyStroke.getKeyStroke("ctrl O"));
啓用和禁用菜單項:
啓用或禁用菜單項需要調用setEnable(boolean b)方法
在顯示菜單前禁用這些菜單項,需要爲”menu selected”事件註冊監聽器,swing包中定義了MenuListener接口。 - 工具欄:是提供快捷訪問的按鈕欄。可以將其任意移動,可以完全脫離框架。
JToolBar bar = new JToolBar();
bar.add(blueButton);
添加按鈕
bar.add(blueAction);
以動作對象作爲參數
bar.setsetSeparator();
設置分隔符
bar = new JToolBar(titleString);
工具欄沒有停靠時,可設置標題
bar = new JToolBar(SwingConstants.VERTICAL);
將工具欄數值顯式
工具提示(tooltips)
在Swing中可以使用button.setToolTipsText("Exit");
或者使用Action對象button.putValue(Action.SHORT_DESCRIPTION, "Exit");
對話框:AWT分爲模式對話框(在結束對它的處理之前不允許與應用程序的其餘窗口進行交互)和無模式對話框(允許用戶在對話框的應用程序的其他窗口輸入信息)。
文件對話框
- 建立一個JFileChooser 對象,不需要制定父組件,允許在多個框架中重用一個文件選擇器。
JFileChooser chooser = new JFileChooser();
- 調用setCurrentDirectory方法設置當前目錄。
chooser.setCurrentDirectory(new File("."));
- 如果有一個想要用戶作爲的默認文件名,調用setSelectedFile()
chooser.setSelectedDirectory(new File(filename));
- 如果允許用戶在對話框選擇多個文件,需要調用setMultiSelectionEnabled()方法。
chooser.setMultiSelectionEnabled(true);
- 如果想讓對話框僅顯示一種類型的文件(.gif等),需要設置文件過濾器。
- 默認情況下,用戶在文件選擇器只能選擇文件,如果想要選擇目錄,需要調用
setSelectionMode
方法,參數值爲JFileChooser.Files_ONLY, JFileChooser.DIRECTORIES_ONLY, JFileChooser.FILES_AND_DIRECTORYIES - 調用showOpenDialog或者showDaveDialog方法顯示對話框。必須爲這些方法調用父組件。
int result = chooser.showOpenDialog(parent);
int result = chooser.showSaveDialog(parent);
這些調用的區別在於”確認按鈕不同”,點擊確認按鈕將完成文件選擇,調用showDialog方法,將一個顯示地文本傳遞給確認按鈕
int result = chooser.showDialog("Select");
只用當喲用戶確認、取消或者離開對話框的時才返回調用。 - 調用getSelectFile()或getSelectFiles()方法獲取用戶選擇的一個或者多個文件,調用getPath方法獲取文件名。
String filename = chooser.getSelectFile().getPath();
若想要限制顯示地文件,需要創建一個實現了抽象類javax.Swing.filechooser.FileFliter的對象,文件選擇器將文件傳遞給文件過濾器,只有文件過濾器接受的文件纔會被顯示出來。
chooser.setFileFliter(fliter1);
當然可以爲一個文件安裝多個過濾器。
chooser.resetFileFliters();
清除舊的文件過濾器。 - 爲每個文件選擇器顯示的沒個文件提供特定的圖標和文件,需要擴展於javax.Swing.filechooser包中的FileView類的對象。
然後調用chooser.setFileView();
將文件視圖安裝到文件選擇器中。
- 建立一個JFileChooser 對象,不需要制定父組件,允許在多個框架中重用一個文件選擇器。
顏色選擇器:JColorChooser, 是一個組件,而不是一個對話框。
Color selectedColor = JColorChooser.showDialog(parent, title, initialColor);
也可以設置一個無模式的顏色選擇器對話框,需要提供:父組件,對話框標題,選擇選擇模式,顏色選擇器,OK和Cancel按鈕對話框。