柚子快報邀請碼778899分享:Java——Swing詳解
柚子快報邀請碼778899分享:Java——Swing詳解
目錄
Swing1、Swing和MVC設計模式2、布局管理2.1、布局管理器2.2、邊框布局2.3、網(wǎng)格布局
3、文本輸入3.1、文本域3.2、標簽和標簽組件3.3、密碼域3.4、文本區(qū)3.5、滾動窗格
4、選擇組件4.1、復選框4.2、單選按鈕4.3、邊框4.4、組合框4.5、滑動條
5、菜單5.1、菜單構建5.2、菜單項中的圖標5.3、復選框和單選按鈕菜單項5.4、彈出菜單5.5、鍵盤助記符和加速器5.6、啟用和禁用菜單項5.7、工具條5.8、工具提示
6、復雜的布局管理6.1、網(wǎng)格包布局1)、gridx、gridy、gridwidth和gridheight參數(shù)2)、增量字段3)、fill和anchor參數(shù)4)、填充5)、指定gridx、gridy、gridwidth和gridheight參數(shù)的備用方法6)、網(wǎng)格包布局技巧7)、使用幫助類管理網(wǎng)格包約束8)、完整示例9)、API
6.2、定制布局管理器
7、對話框7.1、選項對話框7.2、創(chuàng)建對話框7.3、數(shù)據(jù)交互7.4、文件對話框
Swing
1、Swing和MVC設計模式
構成用戶界面組件的各個組成部分,如按鈕、復選框、文本域或復雜的樹控件,每個組件都有三個特征:
內容,如按鈕的狀態(tài)(是否按下),或者文本域中的文本外觀(顏色、大小等)行為(對事件的反應)
這三個特征之間存在相當復雜的交互,即使是最簡單的組件(如按鈕)也能體現(xiàn)出這一點。很明顯,按鈕的外觀顯示取決于它的觀感。Metal按鈕的外觀與Windows按鈕或者 Moif按鈕的外觀就不一樣。另外,外觀顯示還要取決于按鈕的狀態(tài):當按鈕被按下時,按鈕需要重新繪制,使它看起來不一樣。而狀態(tài)取決于按鈕接收到的事件。當用戶在按鈕上點擊鼠標時,按鈕就被按下。
Swing設計者采用了MVC模式,這種設計模式要求我們提供三個不同的對象:
模型(model):存儲內容視圖(view):顯示內容控制器(controller):處理用戶輸入
這種模式明確地規(guī)定了三個對象如何交互。模型存儲內容,它沒有用戶界面。按鈕的內容非常簡單,只有很少的一組標志,用來表示當前按鈕是否按下,是否處于活動狀態(tài),等等。文本域的內容更有意思,它與內容的視圖不同:如果內容的長度大于文本域的大小,用戶就只能看到文本域可以顯示的那一部分。
對大多數(shù)Swing組件來說,模型類將實現(xiàn)一個名字以Model結尾的接口,在這里,接口就名為ButtonModel接口。實現(xiàn)了此接口的類可以定義各種按鈕的狀態(tài)。實際上,按鈕并不復雜,另外Swing庫中有一個名為DefaultButtonModel的類實現(xiàn)了這個接口。
可以通過查看ButtonModel接口的屬性來了解按鈕模型維護著什么類型的數(shù)據(jù):
actionCommand:與按鈕關聯(lián)的動作命令字符串mnemonic:按鈕的助記快捷鍵armed:如果按鈕按下且鼠標仍在按鈕上則為trueenabled:如果按鈕是可選擇的則為truepressed:如果按鈕按下且鼠標按鍵沒有釋放則為truerollover:如果鼠標在按鈕上則為trueselected:如果按鈕已經(jīng)被選擇(用于復選框和單選按鈕)則為true
每個JButton對象都存儲著一個按鈕模型對象,可以如下訪問:
var button = new JButton("Blue");
ButtonModel model = button.getModel();
實際上,不必關心按鈕狀態(tài)的詳細信息,只有繪制它的視圖才對此感興趣。所有重要的信息(如按鈕是否啟用)可以通過JButton類得到(當然,JButton類會向它的模型獲取這些信息)。
下面查看ButtonModel接口中不包含的信息。模型不存儲按鈕標簽或者圖標。對于一個按鈕來說,僅憑模型無法知道它的外觀。
另外還需要注意,同樣的模型(即DefaultButtonModel)可用于下壓按鈕、單選按鈕、復選框,甚至菜單項。當然,這些按鈕都有各自不同的視圖和控制器。當使用Metal觀感時,JButton類用BasicButtonUI類作為其視圖;用ButtonUIListener類作為其控制器。通常,每個Swing組件都有一個相關的后綴為UI的視圖對象,但并不是所有的Swing組件都有專門的控制器對象。
JButton就是一個繼承自JComponent的包裝器類,其中包含DefaultButtonModel對象,一些視圖數(shù)據(jù)(例如按鈕標簽和圖標)以及一個負責按鈕視圖的BasicButtonUI對象。
2、布局管理
2.1、布局管理器
通常,組件放置在容器中,布局管理器決定容器中組件的位置和大小。按鈕、文本域和其他的用戶界面元素都會擴展Component類,組件可以放置在容器(如面板)中。由于Container類擴展自Component類,所以容器本身也可以放置在另一個容器中。
每個容器都有一個默認的布局管理器,但可以重新進行設置:
panel.setLayout(new GridLayout(4, 4));
會使用GridLayout類按4行4列擺放組件。往容器中添加組件時,容器的add方法將把組件和所有位置要求傳遞給布局管理器。
java.awt.Container:
void setLayout(LayoutManager m):為容器設置布局管理器Component add(Component c)Component add(Component c, Object constraints):將組件添加到容器中,并返回組件引用
java.awt.FlowLayout
FlowLayout()FlowLayout(int align)FlowLayout(int align, int hgap, int vgap):構造一個新的FlowLayout對象。align參數(shù)可以是LEFT、CENTER或者RIGHT
2.2、邊框布局
邊框布局管理器(border layout manager)是每個JFrame的內容窗格的默認布局管理器。流布局管理器會完全控制每個組件的位置,邊框布局管理器則不然,它允許為每個組件選擇一個位置??梢赃x擇把組件放在內容窗格的中央、北部、南部、東部或者西部。
例如:
frame.add(component, BorderLayout.SOUTH);
先放置邊緣組件,剩余的可用空間由中間組件占據(jù)。當容器調整大小時,邊緣組件的尺寸不會改變,而中間組件的大小會發(fā)生變化。添加組件時可以指定BorderLayout類的CENTER、NORTH、SOUTH、EAST和WEST常量。不是所有的位置都會被占用,如果沒有提供任何值,系統(tǒng)默認為CENTER。
與流布局不同,邊框布局會擴展所有組件的尺寸以便填滿可用空間(流布局將維持每個組件的最佳尺寸)。
添加一個按鈕時,這會有問題:
frame.add(yellowButton, BorderLayout.SOUTH);
按鈕會擴展至填滿窗體的整個南部區(qū)域。而且,如果再將另外一個按鈕添加到南部區(qū)域,就會取代第一個按鈕。
public class BorderFrameDemo {
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
JFrame frame = new BorderFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
});
}
}
class BorderFrame extends JFrame {
private static final int DEFAULT_WIDTH = 300;
private static final int DEFAULT_HEIGHT = 200;
public BorderFrame() throws HeadlessException {
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
JButton button = new JButton("Button");
add(button, BorderLayout.SOUTH);
}
}
解決這個問題的常見方法是使用另外的面板(panel),因為Panel的默認布局管理器是FlowLayout(流式布局)。
public BorderFrame() throws HeadlessException {
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
JButton button1 = new JButton("Button1");
JButton button2 = new JButton("Button2");
JButton button3 = new JButton("Button3");
JPanel panel = new JPanel();
panel.add(button1);
panel.add(button2);
panel.add(button3);
add(panel, BorderLayout.SOUTH);
}
java.awt.BorderLayout:
BorderLayout()BorderLayout(int hgap, int vgap):構造一個新的BorderLayout對象
2.3、網(wǎng)格布局
網(wǎng)格布局像電子數(shù)據(jù)表一樣,按行列排列所有的組件。不過,所有組件的大小都是一樣的。
public class GridFrame extends JFrame {
private static final int DEFAULT_WIDTH = 300;
private static final int DEFAULT_HEIGHT = 200;
public GridFrame() throws HeadlessException {
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
JButton b1 = new JButton("1");
JButton b2 = new JButton("2");
JButton b3 = new JButton("3");
JButton b4 = new JButton("4");
JButton b5 = new JButton("5");
JButton b6 = new JButton("6");
JButton b7 = new JButton("7");
JButton b8 = new JButton("8");
JButton b9 = new JButton("9");
setLayout(new GridLayout(3, 3));
add(b1);
add(b2);
add(b3);
add(b4);
add(b5);
add(b6);
add(b7);
add(b8);
add(b9);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
JFrame frame = new GridFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
});
}
}
java.awt.GridLayout:
GridLayout(int rows, int colums)GridLayout(int rows, int columns, int hgap, int vgap):構造一個新的GridLayout對象。rows或者columns可以為零,但不能同時為零,指示每行或每列任意的組件數(shù)
3、文本輸入
文本域(JTextField):只能接收單行文本文本區(qū)(JTextArea):可以接收多行文本密碼域(JPasswordField):只能接收單行文本,但不會將輸入的內容顯示出來
這三個類都繼承自JTextComponent類:
String getText()void setText(String text):獲取或設置文本組件的文本內容boolean isEditable()void setEditable(boolean b):獲取或設置editable特性,這個特性決定了用戶是否可以編輯這個文本組件的內容
3.1、文本域
把文本域添加到窗口的常用辦法是將它添加到一個面板或者其他容器中,這與添加按鈕完全一樣:
JPanel panel = new JPanel();
JTextField textField = new JTextField("Default input", 20);
panel.add(textField);
這段代碼將添加一個文本域,初始化時在其中放入字符串"Default input"。構造器的第二個參數(shù)設置了文本域的寬度。在這個示例中,寬度值為20“列”。但是,這里所說的列不是一個精確的測量單位。一列就是指當前使用的字體一個字符的寬度。
如果希望文本域最多能夠輸入n個字符,就應該把寬度設置為n列。在實際中,這樣做效果并不理想,應該將最大輸人長度再多加1~2個字符。另外要記住,列數(shù)只是給AWT設定首選(preferred)大小的一個提示。
如果布局管理器需要縮放這個文本域,它會調整文本域的大小。在JTextField的構造器中設定的寬度并不是用戶能輸入的字符個數(shù)的上限。用戶仍然可以輸入一個更長的字符串,但是當文本長度超過文本域長度時輸入就會滾動。用戶通常不喜歡滾動文本域,因此應該盡量把文本域設置得寬一些。如果需要在運行時重新設置列數(shù),可以使用setColumns方法。
可以在任何時候調用setText方法來改變文本域中的內容。
textField.setText("Hello!");
可以調用getText方法來獲取用戶鍵入的文本。這個方法原樣返回用戶輸入的文本。如果想要將文本域中內容的前后空格去掉,可以對getText的返回值應用trim方法:
String text = textField.getText().trim();
如果想改變顯示文本的字體,可以使用setFont方法。
javax.swing.JTextField:
JTextField(int cols):構造一個有給定列數(shù)的空JTextField對象JTextField(String text, int cols):構造一個有給定列數(shù)和初始字符串的JTextField對象int getColumns()void setColumns(int cols):獲取或設置文本域使用的列數(shù)
javax.swing.JComponent:
void revalidate():重新計算組件的位置和大小void setFont(Font f):設置這個組件的字體
java.awt.Component:
void validate():重新計算組件的位置和大小。如果組件是容器,容器中包含的所有組件的位置和大小也會重新計算Font getFont():獲取組件的字體
3.2、標簽和標簽組件
標簽是容納文本的組件,它們沒有任何的修飾(例如沒有邊緣),也不能響應用戶輸入。
可以利用標簽標識組件。例如,與按鈕不同,文本域沒有標識它們的標簽。要想用標識符標識這種本身不帶標簽的組件:
用正確的文本構造一個JLabel組件。將它放置在距離需要標識的組件足夠近的地方,以便用戶看出這個標簽所標識的組件。
JLabel的構造器允許指定初始文本和圖標,也可以選擇內容的排列方式??梢杂肧wingConstants接口中的常量來指定排列方式。在這個接口中定義了幾個很有用的常量,如 LEFT、RIGHT、CENTER、NORTH、EAST等。
JLabel類是實現(xiàn)這個接口的眾多Swing類之一。因此, 可以指定右對齊標簽:
JLabel label = new JLabel("User name:", SwingConstants.RIGHT);
//或者
JLabel label = new JLabel("User name:", JLabel.RIGHT);
利用setText和setIcon方法可以在運行期間設置標簽的文本和圖標。
javax.swing.JLabel:
JLabel(String text)JLabel(Icon icon)JLabel(String text, int align)JLabel(String text, Icon icon, int align):構造一個標簽。align參數(shù)是一個SwingConstants常量String getText()void setText(String text):獲取或設置標簽的文本Icon getIcon()void setIcon(Icon icon):獲取或設置標簽的圖標
3.3、密碼域
密碼域是一種特殊類型的文本域。為了避免有不良企圖的人站在一旁看到密碼,用戶輸入的字符不真正顯示出來。每個輸入的字符都用回顯字符(echo character)表示,典型的回顯字符是星號(*)。
Swing提供了JPasswordField類來實現(xiàn)這樣的文本域。 密碼域采用與常規(guī)文本域相同的模型來存儲數(shù)據(jù),但是,它的視圖卻改為顯示回顯字符,而不是實際的字符。
javax.swing.JPasswordField:
JPasswordField(String text, int columns):構造一個新的密碼域void setEchoChar(char echo):為密碼域設置回顯字符。這只是一個建議;特定的觀感可能堅持使用自己的回顯字符。值0會重新設置為默認的回顯字符char[] getPassword():返回密碼域中包含的文本。為了得到更好的安全性,在使用之后應該覆寫所返回數(shù)組 的內容(密碼并不是以String返回,這是因為字符串在被垃圾回收之前會一直駐留在虛擬機中)
3.4、文本區(qū)
在JTextArea組件的構造器中,可以指定文本區(qū)的行數(shù) 和列數(shù)。例如:
textArea = new JTextArea(8, 40);
這里參數(shù)columns與之前的做法相同,而且出于穩(wěn)妥的考 慮,應該再增加幾列。另外,用戶并不受限于輸入指定的行數(shù)和列數(shù)。當輸入過長時,文本會滾動。還可以用setColumns方法改變列數(shù),用setRows方法改變行數(shù)。這些值只是指示首選大小—布局管理器可能會對文本區(qū)進行縮放。
如果文本區(qū)的文本超出顯示的范圍,那么剩下的文本就會被剪裁掉??梢酝ㄟ^開啟換行特性來避免裁剪過長的行:
textArea.setLineWrap(true);
換行只是視覺效果,文檔中的文本沒有改變,并沒有在文本中自動插入'\n'字符。
3.5、滾動窗格
在Swing中,文本區(qū)沒有滾動條。如果需要滾動條,可以將文本區(qū)放在滾動窗格(scroll pane)中。
textArea = new JTextArea(8, 40);
JScrollPane scrollPane = new JScrollPane(textArea);
現(xiàn)在滾動窗格管理文本區(qū)的視圖。如果文本超出了文本區(qū)可以顯示的范圍,滾動條就會自動地出現(xiàn),刪除部分文本后,如果文本能夠顯示在文本區(qū)范圍內,滾動條會再次自動地消失。滾動是由滾動窗格內部處理的,編寫程序時無須處理滾動事件。
這是一種適用于所有組件的通用機制,而不是文本區(qū)特有的。也就是說,要想為組件添加滾動條,只需將它們放入一個滾動窗格中即可。
public class TextComponentFrame extends JFrame {
private static final int TEXTAREA_ROWS = 8;
private static final int TEXTAREA_COLUMNS = 20;
private static final int DEFAULT_WIDTH = 300;
private static final int DEFAULT_HEIGHT = 600;
public TextComponentFrame() throws HeadlessException {
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
//North
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);
add(northPanel, BorderLayout.NORTH);
//Center
JTextArea textArea = new JTextArea(TEXTAREA_ROWS, TEXTAREA_COLUMNS);
JScrollPane scrollPane = new JScrollPane(textArea);
add(scrollPane, BorderLayout.CENTER);
//South
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();
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
JFrame frame = new TextComponentFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
});
}
}
javax.swing.JTextArea:
JTextArea()JTextArea(int rows, int cols)JTextArea(String text, int rows, int cols):構造一個新的文本區(qū)void setColumns(int cols):設置文本區(qū)應該使用的首選列數(shù)void setRows(int rows):設置文本區(qū)應該使用的首選行數(shù)void append(String newText):將給定的文本追加到文本區(qū)中已有文本的末尾void setLineWrap(boolean wrap):打開或關閉換行void setWrapStyleWord(boolean word):如果word是true,超長的行會在單詞邊界換行。如果為false,超長的行會被截斷而不考慮單詞邊界void setTabSize(int c):將制表符(tab stop)設置為c列。注意,制表符不會被轉化為空格,但可以讓文本對 齊到下一個制表符處。
javax.swing.JScrollPane:
JScrollPane(Component c):創(chuàng)建一個滾動窗格,用來顯示指定組件的內容。當組件內容超過顯示范圍時,滾動條會自動出現(xiàn)
4、選擇組件
4.1、復選框
如果想要接收的輸入只是“是”或“否”,就可以使用復選框組件。復選框自動帶有標識標簽。用戶通過點擊一個復選框將它選中,再點擊則取消選中。當復選框獲得焦點時,用戶也可以通過按空格鍵來切換選擇。
復選框需要一個緊鄰的標簽來說明其用途。在構造器中指定標簽文本。
bold = new JCheckBOx("Bold");
可以使用setSelected方法來選中或取消選中復選框:
bold.setSelected(true);
isSelected方法將獲取每個復選框的當前狀態(tài)。如果沒有選中則為false,如果選中這個復選框則為true。
當用戶點擊復選框時將觸發(fā)一個動作事件。與以往一樣,可以為復選框關聯(lián)一個動作監(jiān)聽器。
public class CheckBoxFrame extends JFrame {
private JLabel label;
private JCheckBox bold;
private JCheckBox italic;
private static final int FONTSIZE = 24;
public CheckBoxFrame() throws HeadlessException {
label = new JLabel("The quick brown fox jumps over the lazy dog.");
label.setFont(new Font("Serif", Font.BOLD, FONTSIZE));
add(label, BorderLayout.CENTER);
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));
};
JPanel buttonPanel = new JPanel();
bold = new JCheckBox("Bold");
bold.addActionListener(listener);
bold.setSelected(true);
buttonPanel.add(bold);
italic = new JCheckBox("Italic");
italic.addActionListener(listener);
buttonPanel.add(italic);
add(buttonPanel, BorderLayout.SOUTH);
pack();
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
JFrame frame = new CheckBoxFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
});
}
}
javax.swing.JCheckBox:
JCheckBox(String label)JCheckBox(String label, Icon icon):構造一個復選框,初始沒有被選中JCheckBox(String label, boolean stete):用給定的標簽和初始化狀態(tài)構造一個復選框boolean isSelected()void setSelected(boolean state):獲取或設置復選框的選擇狀態(tài)
4.2、單選按鈕
在很多情況下,我們需要用戶只選擇幾個選項當中的一個。當用戶選擇另一項的時候,前一項就自動地取消選中。這樣一組選項通常稱為單選按鈕組(Radio Button Group)。
在Swing中實現(xiàn)單選按鈕組非常簡單。為單選按鈕組構造一個ButtonGroup類型的對象。然后,再將JRadioButton類型的對象添加到按鈕組中。按鈕組對象負責在新按鈕被按下時取消前一個選中按鈕的選擇狀態(tài)。
注意,按鈕組僅僅控制按鈕的行為,如果想把這些按鈕擺放在一起,需要把它們添加到容器中,和JPanel一樣。
public class RadioButtonFrame extends JFrame {
private JPanel buttonPanel;
private ButtonGroup group;
private JLabel label;
private static final int DEFAULT_SIZE = 36;
public RadioButtonFrame() {
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);
//添加按鈕組
buttonPanel = new JPanel();
group = new ButtonGroup();
addRadioButton("Small", 8);
addRadioButton("Medium", 12);
addRadioButton("Large", 18);
addRadioButton("Extra", 36);
add(buttonPanel, BorderLayout.SOUTH);
pack();
}
public void addRadioButton(String name, int size) {
boolean selected = size == DEFAULT_SIZE;
JRadioButton button = new JRadioButton(name, selected);
group.add(button);
buttonPanel.add(button);
button.addActionListener(event -> {
label.setFont(new Font("Serif", Font.PLAIN, size));
});
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
JFrame frame = new RadioButtonFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
});
}
}
javax.swing.JRadioButton:
JRadioButton(String label, Icon icon):構造一個初始沒有選中的單選按鈕JRadioButton(String label, boolean state):用給定的標簽和初始狀態(tài)構造一個單選按鈕
javax.swing.ButtonGroup:
void add(AbstractButton b):將按鈕添加到組中ButtonModel getSelection():返回被選中的按鈕的按鈕模型
javax.swing.ButtonModel:
String getActionCommand():返回按鈕模型的動作命令
javax.swing.AbstractButton:
void setActionCommand(String s):設置按鈕及其模型的動作命令
4.3、邊框
如果在一個窗口中有多組單選按鈕,就需要用可見的方式來指明哪些按鈕屬于同一組。Swing提供了一組很有用的邊框(border)來解決這個問題??梢栽谌魏卫^承了JComponent的組件上應用邊框。最常用的用法是在面板周圍放置一個邊框,然后用其他用戶界面元素(如單選按鈕)填充面板。
有幾種不同的邊框可供選擇,但是使用它們的步驟完全一樣:
調用BorderFactory的靜態(tài)方法創(chuàng)建邊框,如下是幾種可選的風格
凹斜面凸斜面蝕刻直線蒙版空(在組件外圍創(chuàng)建一些空白空間) 如果愿意的話,可以給邊框添加標題,具體的實現(xiàn)方法是將邊框傳遞給BroderFactory.createTitleBorder如果確實想全力地使用邊框,可以調用以下方法將幾種邊框組合起來:BorderFactory.createCompoundBorder調用JComponent類的setBorder方法將得到的邊框添加到組件
把一個帶有標題的蝕刻邊框添加到一個面板:
Border etched = BorderFactory.createEtchedBorder();
Border titled = BorderFactory.createTitledBorder(etched, "A Title");
panel.setBorder(titled);
java.swing.BorderFactory:
static Border createLineBorder(Color color)static Border createLineBorder(Color color, int thickness):創(chuàng)建一個簡單的直線邊框static MatteBorder createMatteBorder(int top, int left, int bottom, int right, Color color)static MatteBorder createMatteBorder(int top, int left, int bottom, int right, Icon tileIcon):創(chuàng)建一個用顏色或重復圖標填充的粗邊框static Border createEmptyBOrder()static Border createEmptyBorder(int top, int left, int bottom, int right):創(chuàng)建一個空邊框static Border createEtchedBorder()static Border createEtchedBorder(Color highlight, Color shadow)static Border createEtchedBorder(int type)static Border createEtchedBorder(int type, Color highlight, Color shadow):創(chuàng)建一個具有3D效果的直線邊框。type參數(shù)是常量EtchedBorder.RAISED和EtchedBorder.LOWERED之一static Border createBevelBorder(int type)static Border createBevelBorder(int type, Color highlight, Color shadow)static Border createLOweredBevelBorder()static Border createRaisedBevelBorder():創(chuàng)建一個具有凹面或凸面效果的邊框static TitleBorder createTitleBorder(String title)static TitleBorder createTitleBorder(Border border)static TitleBorder createTitleBorder(Border border, String title)static TitleBorder createTitleBorder(Border border, String title, int justification, int position)static TitleBorder createTitleBorder(Border border, String title, int justification, int position, Font font)static TitleBorder createTitleBorder(Border border, String title, int justification, int position, Font font, Color color):創(chuàng)建一個有指定屬性的帶標題的邊框。justification參數(shù)是TitledBorder常量LEFT、 CENTER、RIGHT、LEADING、TRAILING或DEFAULT_JUSTIFICATION(左X對齊)之一,position是ABOVE_TOP、TOP、BELOW_TOP、ABOVE_BOTTOM、BOTTOM、BELOW_BOTTOM或DEFAULT_POSITION(上)之一。static CompoundBorder createCompoundBorder(Border outsideBorder, Border insideBOrder):將兩個邊框組合成一個新的邊框
javax.swing.border.SoftBevelBorder:
SoftBevelBorder(int type)SoftBevelBorder(int type, Color highlight, Color shadow):創(chuàng)建一個帶有柔和邊角的斜面邊框。type參數(shù)是BevelBorder.LOWERED和BevelBorder.RAISED之一
javax.swing.border.LineBorder:
public LineBorder(Color color, int thickness, boolean rounded roundedCorners):用指定的顏色和粗細創(chuàng)建一個直線邊框。如果roundedCorners為true,則邊框有圓角
javax.swing.JComponent:
void setBorder(Border border):設置這個組件的邊框
4.4、組合框
如果有多個選擇項,使用單選按鈕就不太適宜了,原因是會占據(jù)太多屏幕空間。這時就可以選擇組合框。當用戶點擊這個組件時,會下拉一個選擇列表,用戶可以從中選擇一項。
如果下拉列表框被設置成可編輯(editable),就可以像這 是一個文本域一樣編輯當前的選項內容。鑒于這個原因,這種組件被稱為組合框(combo box),它將文本域的靈活性與一組預定義的選項組合起來。JComboBox類提供了組合框組件。
在Java7中,JComboBox類是一個泛型類。例如,JComboBox
調用setEditable方法可以讓組合框可編輯。注意,編輯 只會影響選擇的項,而不會改變選擇列表的內容。
可以調用getSelectedItem方法獲取當前的選項,如果組合框是可編輯的,當前選項可能已經(jīng)編輯過。不過,對于可編輯組合框,其中的選項可以是任何類型,這取決于編輯器(即由編輯器獲取用戶輸入并將結果轉換為一個對象)。如果組合框不是可編輯的,最好調用:
combo.getItemAt(combo.getSelectedIndex());
public class ComboBoxFrame extends JFrame {
private JComboBox
private JLabel label;
private static final int DEFAULT_SIZE = 24;
public ComboBoxFrame() {
//添加一個標簽
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);
//添加組合框
faceCombo = new JComboBox<>();
faceCombo.addItem("Serif");
faceCombo.addItem("SansSerif");
faceCombo.addItem("Monospaced");
faceCombo.addItem("Dialog");
faceCombo.addItem("DialogInput");
faceCombo.addActionListener(event -> {
label.setFont(new Font(faceCombo.getItemAt(faceCombo.getSelectedIndex()),
Font.PLAIN,
DEFAULT_SIZE));
});
JPanel comboPanel = new JPanel();
comboPanel.add(faceCombo);
add(comboPanel, BorderLayout.SOUTH);
pack();
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
JFrame frame = new ComboBoxFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
});
}
}
javax.swing.JComboBox:
boolean isEditable()void setEditable(boolean b):獲取或設置組合框的editable特性void addItem(Object item):把一個選項添加到選項列表中void insertItemAt(Object item, int index):將一個選項插入到選項列表的指定索引位置void removeItem(Object item):從選項列表中刪除一個選項void removeItemAt(int index):刪除指定索引位置的選項void removeAllItems():從選項列表中刪除所有選項Object getSelectedItem():返回當前選擇的選項
4.5、滑動條
滑動條允許用戶從連續(xù)值中進行選擇。
JSlider slider = new JSlider(min, max, initialValue);
如果省略最小值、最大值和初始值,其默認值分別為0、100和50?;蛘呷绻枰怪被瑒訔l,可以按照以下方式調用構造器:
JSlider slider = new JSlider(SwingConstants.VERICAL, min, max, initialValue);
當用戶滑動滑動條時,滑動條的值就會在最小值和最大值之間變化。當值發(fā)生變化時,ChangeEvent就會發(fā)送給所有變更監(jiān)聽器。為了得到這些變更的通知,需要調用addChangeListener方法并且安裝一個實現(xiàn)了 ChangeListener接口的對象。在這個回調中,可以獲取滑 動條的值:
ChangeListener listener = event -> {
JSlider slider = (JSlider)event.getSource();
int value = slider.getValue();
...
};
可以通過顯示刻度(tick)對滑動條進行修飾:
slider.setMajorTickSpacing(20);
slider.setMinorTickSpacing(5);
上述滑動條在每20個單位的位置顯示一個大刻度標記,每5個單位的位置顯示一個小刻度標記。所謂單位是指滑動條值,而不是像素。這些指令只設置了刻度標記的單位數(shù),要想將它們真正顯示出來,還需要調用:
slider.setPaintTicks(true);
大刻度和小刻度標記是相互獨立的。例如,可以每20個單位設置一個大刻度標記,同時每7個單位設置一個小刻度尺標記,但是這樣設置滑動條看起來會顯得非常凌亂。
可以強制滑動條對齊刻度(snap to tick)。這樣一來,只要用戶采用對齊模式完成拖放滑動條的操作,它就會立即自動地移到最接近的刻度。激活這種模式需要調用:
slider.setPaintLabels(true);
public class SliderFrame extends JFrame {
private JPanel sliderPanel;
private JTextField textField;
private ChangeListener listener;
public SliderFrame() {
sliderPanel = new JPanel();
sliderPanel.setLayout(new GridBagLayout());
//滑動條的通用監(jiān)聽器
listener = event -> {
JSlider source = (JSlider)event.getSource();
textField.setText("" + source.getValue());
};
//滑動條1
JSlider slider = new JSlider();
addSlider(slider, "Plain");
//滑動條2
slider = new JSlider();
slider.setPaintTicks(true);
slider.setMajorTickSpacing(20);
slider.setMinorTickSpacing(5);
addSlider(slider, "Ticks");
//滑動條3
slider = new JSlider();
slider.setPaintTicks(true);
slider.setSnapToTicks(true);
slider.setMajorTickSpacing(20);
slider.setMinorTickSpacing(5);
addSlider(slider, "Snap to ticks");
//滑動條4
slider = new JSlider();
slider.setPaintTicks(true);
slider.setMajorTickSpacing(20);
slider.setMinorTickSpacing(5);
slider.setPaintTrack(false);
addSlider(slider, "No track");
//滑動條5
slider = new JSlider();
slider.setPaintTrack(true);
slider.setMajorTickSpacing(20);
slider.setMinorTickSpacing(5);
slider.setInverted(true);
addSlider(slider, "Inverted");
//滑動條6
slider = new JSlider();
slider.setPaintTicks(true);
slider.setPaintLabels(true);
slider.setMajorTickSpacing(20);
slider.setMinorTickSpacing(5);
addSlider(slider, "Labels");
//滑動條7
slider = new JSlider();
slider.setPaintLabels(true);
slider.setPaintTicks(true);
slider.setMajorTickSpacing(20);
slider.setMinorTickSpacing(5);
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");
//滑動條8
slider = new JSlider();
slider.setPaintTicks(true);
slider.setPaintLabels(true);
slider.setSnapToTicks(true);
slider.setMajorTickSpacing(20);
slider.setMinorTickSpacing(20);
labelTable = new Hashtable<>();
labelTable.put(0, new JLabel(new ImageIcon("icon.png")));
labelTable.put(20, new JLabel(new ImageIcon("icon.png")));
labelTable.put(40, new JLabel(new ImageIcon("icon.png")));
labelTable.put(60, new JLabel(new ImageIcon("icon.png")));
labelTable.put(80, new JLabel(new ImageIcon("icon.png")));
labelTable.put(100, new JLabel(new ImageIcon("icon.png")));
slider.setLabelTable(labelTable);
addSlider(slider, "Icon labels");
textField = new JTextField();
add(sliderPanel, BorderLayout.CENTER);
add(textField, BorderLayout.SOUTH);
pack();
}
public void addSlider(JSlider slider, String description) {
slider.addChangeListener(listener);
JPanel panel = new JPanel();
panel.add(slider);
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);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
JFrame frame = new SliderFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
});
}
}
javax.swing.JSlider:
JSlider()JSlider(int direction)JSlider(int min, int max)JSlider(int min, int max, int initialValue)JSlider(int direction, int min, int max, int initialValue):用給定的方向、最大值、最小值和初始值構造一個水平滑動條。direction參數(shù)是SwingConstants.HORIZONTAL或SwingConstants.VERTICAL之一。默認為水平?;瑒訔l的最小值、初始值和最大值默認為0、50和100void setPaintTicks(boolean b):如果b為true,顯示刻度void setMajorTickSpacing(int units)void setMinorTickSpacing(int nuits):用給定的滑動條單位的倍數(shù)設置最大刻度和最小刻度void setPaintLabels(boolean b):設置用做刻度標簽的組件void setSnapToTicks(boolean b):如果b是true,每一次調整后滑塊都要對齊到最接近的刻度void setPaintTrack(boolean b):如果b是true,顯示滑動條滑動的軌跡
5、菜單
位于窗口頂部的萊單欄(menu bar)包括了下拉菜單的名 字。點擊一個名字就可以打開包含菜單項(menu item)和子菜單(submenu)的菜單。當用戶點擊菜單項時,所有的菜單都會被關閉并且將一條消息發(fā)送給程序。
5.1、菜單構建
構建菜單是一件非常容易的事情。首先要創(chuàng)建一個菜單欄:
var menuBar = new JMenuBar();
菜單欄是一個可以添加到任何位置的組件。正常情況下會放置在窗體的頂部??梢哉{用setJMenuBar方法將菜單欄添加到這里:
frame.setJMenuBar(menuBar);
需要為每個菜單創(chuàng)建一個菜單對象:
var editMenu = new JMenu("Edit");
然后將頂層菜單添加到菜單欄中:
menuBar.add(editMenu);
向菜單對象中添加菜單項、分隔符和子菜單:
var pasteItem new JMenuItem("Paste");
editMenu.add(pasteItem);
editMenu.addSeparator();
JMenu optionsMenu =...;//a submenu
editMenu.add(optionsMenu);
當用戶選擇菜單時,將觸發(fā)一個動作事件。需要為每個菜單項安裝一個動作監(jiān)聽器:
ActionListener listener =...
pasteItem.addActionListener(listener);
JMenu.add(String s)方法可以很方便地將菜單項增加到菜單的尾部,例如:
editMenu.add("Paste");
add方法返回創(chuàng)建的菜單項。可以獲取這個菜單項,并添加監(jiān)聽器,如下所示:
JMenuItem pasteItem = editMenu.add("Paste");
pasteItem.addActionListener(listener);
在通常情況下,菜單項觸發(fā)的命令也可以通過其他用戶界面元素(如工具條按鈕)激活。要定義一個實現(xiàn)Action接 口的類,為此通常會擴展便利的AbstractAction類,在AbstractAction對象的構造器中指定菜單項標簽,并且覆蓋actionPerformed方法來獲得菜單動作處理器。例如:
var exitAction new AbstractAction("Exit") {
//menu item text goes here
public void actionPerformed(ActionEvent event){
//action code goes here
System.exit(0);
}
};
然后將動作添加到菜單中:
JMenuItem exitItem = fileMenu.add(exitAction);
這個命令利用動作名將一個菜單項添加到菜單中。這個動作對象將作為它的監(jiān)聽器。上面這條語句是下面兩條語句的快捷形式:
var exitItem = new JMenuItem(exitAction);
fileMenu.add(exitItem)
javax.swing.JMenu:
JMenu(String label):用給定標簽構造一個菜單JMenuItem add(JMenuItem item):添加一個菜單項(或一個菜單)JMenuItem add(String label):將一個有給定標簽的菜單項添加到菜單中,并返回這個菜單項JMenuItem add(Action a):將一個有給定動作的菜單項添加到菜單中,并返回這個菜單項void addSeparator():將一個分隔行添加到菜單中JMenuItem insert(JMenuItem menu, int index):將一個新菜單項(或子菜單)添加到菜單的指定索引位置JMunuItem insert(Action a, int index):將有指定動作的新菜單項增加到菜單的指定索引位置void insertSeparator(int index):將一個分隔符添加到菜單中void remove(int index)void remove(JMenuItem item):從菜單中刪除指定的菜單項
javax.swing.JMenuItem:
JmenuItem(String label):用給定標簽構造一個菜單項JMenuItem(Action a):為給定動作構造一個菜單項
javax.swing.AbstractButton:
void setAction(Action a):為了這個按鈕或菜單項設置動作
javax.swing.JFrame:
void setJMenuBar(JMenuBar memubar)**:為這個窗體設置菜單欄
5.2、菜單項中的圖標
菜單項與按鈕很相似。實際上,JMenuItem類擴展了AbstractButton類。與按鈕一樣,菜單可以只包含文本標簽、只包含圖標,或者兩者都包含??梢允褂肑MenuItem(String,Icon)或者JMenuItem(Icon)構造器為菜單指定一個圖標,也可以使用JMenuItem類從AbstractButton類繼承的setIcon方法指定一個圖標。例如:
var cutItem = new JMenuItem("Cut",new ImageIcon("cut.gif"));
在默認情況下,菜單項文本放在圖標的右側。如果喜歡將文本放置在左側,可以調用JMenuItem類從AbstractButton類繼承的setHorizontalTextPosition方法。例如:
cutItem.setHorizontalTextPosition(SwingConstants.LEFT);
這個調用把菜單項文本移動到圖標的左側。也可以為動作增加一個圖標:
cutAction.putValue(Action.SMALL ICON,new ImageIcon("cut.gif"));
當使用動作構造菜單項時,Action.NAME值將會作為菜單項的文本,而Action.SMALL ICON將會作為圖標。 或者,可以在AbstractAction構造器中設置圖標:
cutAction = new AbstractAction("Cut",new ImageIcon("cut.gif")) {
public void actionPerformed(ActionEvent event){
...
}
};
javax.swing.JMenuItem:
JMenuItem(String label, Icon icon):用給定的標簽和圖標構造一個菜單項
javax.swing.AbstractButton:
void setHorizontalTextPosition(int pos):設置文本相對于圖標的水平位置。pos參數(shù)是SwingConstants.RIGHT(文本在圖標的右側)或SwingConstants.LEFT
javax.swing.AbstractAction:
AbstractAction(String name, Icon smallIcon):用給定的名字和圖標構造一個抽象動作
5.3、復選框和單選按鈕菜單項
復選框和單選按鈕菜單項會在菜單名旁邊顯示了一個復選框或一個單選按鈕。當用戶選擇一個菜單項時,菜單項就會自動地在選擇和未選擇間進行切換。
除了按鈕裝飾外,復選框和單選按鈕菜單項同其他菜單項的處理一樣。例如,可以如下創(chuàng)建復選框菜單項:
var readonlyItem = new JCheckBoxMenuItem("Read-only");
optionsMenu.add(readonlyItem);
單選按鈕菜單項與普通單選按鈕的工作方式一樣,必須將它們加入到按鈕組中。當按鈕組中的一個按鈕被選中時,其他按鈕都自動地變?yōu)槲催x中。
var group = new ButtonGroup();
var insertItem = new JRadioButtonMenuItem("Insert");
insertItem.setSelected(true);
var overtypeItem = new JRadioButtonMenuItem("Overtype");
group.add(insertItem);
group.add(overtypeItem);
optionsMenu.add(insertItem)
optionsMenu.add(overtypeItem);
使用這些菜單項,不需要立刻得到用戶選擇菜單項的通知。實際上,可以使用isSelected方法來測試菜單項的當前狀態(tài)(當然,這意味著應該保留這個菜單項的一個引用,保存在一個實例字段中)。可以使用setSelected方法設置狀態(tài)。
javax.swing.JCheckBoxMenuItem:
JCheckBoxMenuItem(String label):用給定的標簽構造一個復選框菜單項JCheckBoxMenuItem(String label, boolean state):用給定的標簽和給定的初始狀態(tài)(true為選定)構造一個復選框菜單
javax.swing.JRadioButtonMenuItem:
JRadioButtonMenuItem(String label):用給定的標簽構造一個單選按鈕菜單項JRadioButtonMenuItem(String label, boolean state):用給定的標簽和給定的初始狀態(tài)(true為選定)構造一個單選按鈕菜單項
javax.swing.AbstractButton:
boolean isSelected()void setSelected(boolean state):獲取或設置這個菜單項的選擇狀態(tài)(true為選中)
5.4、彈出菜單
彈出菜單(pop-up menu)是不固定在菜單欄中隨處浮動的菜單。
創(chuàng)建一個彈出菜單與創(chuàng)建一個常規(guī)菜單的方法類似,但 是彈出菜單沒有標題。
var popup = new JPopupMenu();
然后用常規(guī)的方法添加菜單項:
var item = new JMenultem("Cut");
item.addActionListener(listener);
popup.add(item);
彈出菜單并不像常規(guī)菜單欄那樣總是顯示在窗體的頂部,必須調用show方法顯式地顯示彈出菜單。需要指定父組件,并使用父組件的坐標系統(tǒng)指定彈出菜單的位置。例如:
popup.show(panel,x,y);
通常,你可能希望當用戶點擊某個鼠標鍵時彈出菜單,這就是所謂的彈出式觸發(fā)器(pop-up trigger)。在Windows或者Linux中,彈出式觸發(fā)器是鼠標次鍵(通常是右鍵)。要想在用戶點擊一個組件時彈出菜單,只需要調用方法:
component.setComponentPopupMenu(popup);
偶爾也可能需要把一個組件放在另一個帶彈出菜單的組件中。通過調用以下方法,這個子組件可以繼承父組件的彈出菜單:
child.setInheritsPopupMenu(true);
javax.swing.JPopuMenu:
void show(Component c, int x, int y):在組件c上顯示彈出菜單,組件c的左上角坐標為(x,y)(c的坐標空間內)boolean isPopupTrigger(MouseEvent event):如果鼠標事件是彈出菜單觸發(fā)器,則返回true
java.awt.event.MouseEvent:
boolean isPopupTrigger():如果鼠標事件是彈出菜單觸發(fā)器,則返回true
javax.swing.JComponent:
JPopupMenu getComponentPopupMenu()void setComponentPopupMenu(JPopupMenu popup):獲取或設置用于這個組件的彈出菜單boolean getInheritsPopupMenu()void setInheritsPopupMenu(boolean b):獲取或設置inheritsPopupMenu特性。如果這個特性已設置或這個組件的彈出菜單為null,就使用其父組件的彈出菜單
5.5、鍵盤助記符和加速器
對于有經(jīng)驗的用戶來說,通過鍵盤助記符選擇菜單項確實非常便捷。可以通過在菜單項的構造器中指定一個助記字母來為菜單項設置鍵盤助記符:
var aboutItem = new JMenuItem("About",'A');
鍵盤助記符會在菜單中自動顯示,助記字母下面有一條下劃線。例如,在上面的例子中,菜單項中的標簽顯示為“About”,字母A帶有一個下劃線。菜單顯示時,用戶只需要按下“A”鍵就可以選擇這個菜單項(如果助記字母不在菜單字符串中,同樣可以按下這個字母選擇菜單項,不過助記符不會在菜單中,同樣可以按下這個字母選擇菜單項,不過助記符不會在菜單中顯示。
javax.swing.JMenuItem:
JMenuItem(String label,int mnemonic):用給定的標簽和助記符構造一個菜單項。void setAccelerator(KeyStroke k):將k鍵設置為這個菜單項的加速器。加速器鍵顯示在標簽旁邊。
javax.swing.AbstractButton:
void setMnemonic(int mnemonic):設置按鈕的助記字符。該字符會在標簽中加下劃線顯示。void setDisplayedMnemonicIndex(int index):設置按鈕文本中加下劃線字符的索引。如果不希望第一個出現(xiàn)的助記字符帶下劃線,就可以使用這個方法。
5.6、啟用和禁用菜單項
有些時候,某個特定的菜單項可能只在某種特定的環(huán)境下才能選擇。例如,當文檔以只讀方式打開時,Save菜單項就沒有意義。當然,可以使用JMenu.remove方法將這個菜單項從菜單中刪掉,但用戶會對內容不斷變化的菜單感到奇怪。實際上,最好禁用這個菜單項,以免觸發(fā)暫時不適用的命令。被禁用的菜單項顯示為灰色,不允許選擇。
啟用或禁用菜單項需要調用setEnabled方法:
saveItem.setEnabled(false);
啟用和禁用菜單項有兩種策略。每次環(huán)境發(fā)生變化時,就可以對相關的菜單項或動作調用setEnabled。例如:一旦文檔以只讀方式打開,可以找到并禁用Save和Save As菜單項。另一種方法是在顯示菜單之前禁用這些菜單項。為此,必須為“菜單選中”事件注冊一個監(jiān)聽器。javax.swing.event包定義了一個MenuListener接口,它包含三個方法:
void menuSelected(MenuEvent event)void menuDeselected(MenuEvent event)void menuCanceled(MenuEvent event)
menuSelected方法在菜單顯示之前調用,所以可以用這個方法禁用或啟用菜單項。下面的代碼顯示了選中只讀復選框菜單項時如何禁用Save和Save As動作。
public void menuSelected(MenuEvent event) {
saveAction.setEnabled(!readonlyItem.isSelected());
saveAsAction.setEnabled(!readonlyItem.isSelected());
}
javax.swing.JMenuItem:
void setEnabled(boolean b):啟用或禁用菜單項。
javax.swing.event.MenuListener:
void menuSelected(MenuEvent e):在菜單被選擇但尚未打開時調用void menuDeselected(MenuEvent e):在菜單被取消選擇并且已經(jīng)關閉之后調用void menuCanceled(MenuEvent e):當菜單被取消時調用。例如,用戶點擊菜單以外的區(qū)域
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;
class TestAction extends AbstractAction {
public TestAction(String name) {
super(name);
}
@Override
public void actionPerformed(ActionEvent e) {
System.out.println(getValue(Action.NAME) + " selected.");
}
}
public MenuFrame() {
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
JMenu fileMenu = new JMenu("File");
fileMenu.add(new TestAction("New"));
JMenuItem openItem = fileMenu.add(new TestAction("Open"));
openItem.setAccelerator(KeyStroke.getKeyStroke("ctrl 0"));
fileMenu.addSeparator();
saveAction = new TestAction("Save");
JMenuItem saveItem = fileMenu.add(saveAction);
saveItem.setAccelerator(KeyStroke.getKeyStroke("ctrl S"));
saveAsAction = new TestAction("Save As");
fileMenu.add(saveAction);
fileMenu.addSeparator();
fileMenu.add(new AbstractAction("Exit") {
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
readonlyItem = new JCheckBoxMenuItem("Read-only");
readonlyItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
boolean saveOk = !readonlyItem.isSelected();
saveAction.setEnabled(saveOk);
saveAction.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);
TestAction cutAction = new TestAction("Cut");
cutAction.putValue(Action.SMALL_ICON, new ImageIcon("icon.png"));
TestAction copyAction = new TestAction("Copy");
copyAction.putValue(Action.SMALL_ICON, new ImageIcon("icon.png"));
TestAction pasteAction = new TestAction("Paste");
pasteAction.putValue(Action.SMALL_ICON, new ImageIcon("icon.png"));
JMenu editMenu = new JMenu("Edit");
editMenu.add(cutAction);
editMenu.add(copyAction);
editMenu.add(pasteAction);
JMenu optionMenu = new JMenu("Options");
optionMenu.add(readonlyItem);
optionMenu.addSeparator();
optionMenu.add(insertItem);
optionMenu.add(overtypeItem);
editMenu.addSeparator();
editMenu.add(optionMenu);
JMenu helpMenu = new JMenu("Help");
helpMenu.setMnemonic('H');
JMenuItem indexItem = new JMenuItem("Index");
indexItem.setMnemonic('I');
helpMenu.add(indexItem);
TestAction aboutAction = new TestAction("About");
aboutAction.putValue(Action.MNEMONIC_KEY, new Integer('A'));
helpMenu.add(aboutAction);
JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);
menuBar.add(fileMenu);
menuBar.add(editMenu);
menuBar.add(helpMenu);
popup = new JPopupMenu();
popup.add(cutAction);
popup.add(copyAction);
popup.add(pasteAction);
JPanel panel = new JPanel();
panel.setComponentPopupMenu(popup);
add(panel);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
JFrame frame = new MenuFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
});
}
}
5.7、工具條
工具條是一個按鈕條,通過它可以快速訪問程序中最常用的命令,工具條的特殊之處在于可以將它隨處移動??梢詫⑺弦返酱绑w的四個邊框上。釋放鼠標按鈕后,工具條將會落在新的位置上。
工具條甚至可以完全脫離窗體。這種分離的工具條包含在自己的窗體中,關閉包含分離式工具條的窗體時,工具條會回到原窗體中。
可以將組件添加到工具條:
JToolBar toolbar = new JToolBar();
toolbar.add(blueButton);
JToolBar類還有一個添加Action對象的方法,可以用Action對象填充工具條,如下所示:
toolbar.add(blueAction);
這個動作的小圖標將會出現(xiàn)在工具條中。可以用分隔符將按鈕分組:
toolbar.addSeparator();
還可以指定工具條的標題,當工具條未鎖定時就會顯示這個標題:
toolbar new JToolBar(titleString);
在默認情況下,工具條初始為水平的。如果希望工具條初始是垂直的,可以使用以下代碼:
toolbar new JToolBar(SwingConstants.VERTICAL)
或者
toolbar = new JToolBar(titleString,SwingConstants.VERTICAL)
按鈕是工具條中最常用的組件。不過對于工具條中可以增加哪些組件并沒有任何限制。例如,可以在工具條中加入組合框。
5.8、工具提示
工具條有一個缺點,這就是用戶常常需要猜測工具條中小圖標的含義。為了解決這個問題,用戶界面設計者發(fā)明了工具提示(tooltip)。當光標在一個按鈕上停留片刻時,工具提示就會被激活。工具提示文本顯示在一個有顏色的矩形里。當用戶移開鼠標時,工具提示就會消失。
在Swing中,可以調用setToolTipText方法將工具提示添 加到任何JComponent上:
exitButton.setToolTipText("Exit");
或者,如果使用Action對象,可以用SHORT_DESCRIPTION關聯(lián)工具提示:
exitAction.putValue(Action.SHORT DESCRIPTION,"Exit");
javax.swing.JToolBar:
JToolBar()JToolBar(String titleString)JToolBar(int orientation)JToolBar(String titleString,int orientation):用給定的標題字符串和方向構造一個工具條。orientation可以是SwingConstants.HORIZONTAL(默認)或SwingConstants.VERTICALJButton add(Action a):在工具條中用給定動作的名稱、圖標、簡要說明和動作回調構造一個新按鈕,并把這 個按鈕增加到工具條末尾void addSeparator():將一個分隔符添加到工具條的末尾
javax.swing.JComponent:
void setToolTipText(String text):設置當鼠標停留在組件上時要作為工具提示顯示的文本
6、復雜的布局管理
自從Java 1.0以來,AWT就含有網(wǎng)格包布局(grid bag layout),這種布局將組件按行和列排列。行和列的大小可以靈活改變,而且組件可以跨多行多列。這種布局管理器非常靈活,但也非常復雜。僅僅提到“網(wǎng)格包布局”一詞就會讓一些Java程序員膽戰(zhàn)心驚。
Swig設計者有一個失敗的嘗試:為了設計一個布局管理器,能夠將程序員從使用網(wǎng)格包布局的麻煩中解脫出來,他們提出了一種箱式布局(box layout)。根據(jù)BoxLayout類的JDK文檔所述:“采用水平和垂直[sic]的不同組合嵌套多個面板可以獲得與GridBagLayout類似的效果,而且降低了復雜度。”不過,由于每個箱子是獨立放置的,所以不能使用箱式布局排列水平和垂直方向都相鄰的組件。
Java 1.4還做了一個嘗試:設計網(wǎng)格包布局的一種替代布局一彈性布局(spring layout)。這種布局使用假想的彈簧連接一個容器中的組件。當容器改變大小時,彈簧會伸展 或收縮,從而調整組件的位置。這聽起來似乎很枯燥而且讓人很困惑,其實也確實如此。彈性布局很快就變得含糊不清。
NetBeans IDE結合了一個布局工具(名為“Matisse”)和一個布局管理器。用戶界面設計者可以使用工具將組件拖放到一個容器中,并指出組件的排列方式。工具再將設計者的意圖轉換成組布局管理器可以理解的指令。與手動編寫布局管理代碼相比,這樣要便捷得多。
6.1、網(wǎng)格包布局
網(wǎng)格包布局是所有布局管理器之母??梢詫⒕W(wǎng)格包布局看成是沒有任何限制的網(wǎng)格布局。在網(wǎng)格包布局中,行和列的大小可以改變??梢詫⑾噜彽膯卧喜⒁赃m應較大的組件(很多字處理器以及HTML為表格提供了類似的功能:可以先建立一個表格,然后根據(jù)需要合并相鄰的單元格)。組件不需要填充整個單元格區(qū)域,而且可以指定它們在單元格內的對齊方式。
考慮上圖所示的字體選擇器,其中包含下面的組件:
兩個用于指定字體和字體大小的組合框兩個組合框的標簽兩個用于選擇粗體和斜體的復選框一個用于顯示示例字符串的文本區(qū)
現(xiàn)在將容器分解為由單元格組成的網(wǎng)格,(行和列的大小不必相同)。每個復選框橫跨兩列,文本區(qū)跨四行:
為了向網(wǎng)格包管理器描述這個布局,需要完成以下過程:
創(chuàng)建一個GridBagLayout類型的對象。不需要指定底層網(wǎng)格的行數(shù)和列數(shù)。實際上,布局管理器會根據(jù)后面所給的信息猜測行數(shù)和列數(shù)。將這個GridBagLayout對象設置為組件的布局管理器。對于每個組件,創(chuàng)建一個GridBagConstraints類型的對象。設置GridBagConstraints對象的字段值來指定組件在網(wǎng)格包中如何布局。最后,通過下面的調用為各個組件增加約束:
add(component,constraints);
下面給出所需的示例代碼:
var layout = new GridBagLayout();
panel.setLayout(layout);
var constraints = new GridBagConstraints();
constraints.weightx 100;
constraints.weighty 100;
constraints.gridx 0;
constraints.gridy 2;
constraints.gridwidth 2;
constraints.gridheight 1;
panel.add(component,constraints);
1)、gridx、gridy、gridwidth和gridheight參數(shù)
gridx、gridy、gridwidth和gridheight約束定義了組件在網(wǎng)格中的位置:
gridx和gridy值指定了所添加組件左上角的行、列位置。gridwidth和gridheight值確定組件占據(jù)的行數(shù)和列數(shù)。
網(wǎng)格的坐標從0開始。具體地,gridx=0和gridy=0指示最左上角。例如,示例程序中,文本區(qū)的gridx=2,gridy=0。這是因為這個文本區(qū)起始于0行2列(即第3列),它的girdwidth=1, gridheight=4,因為它占據(jù)4行1列。
2)、增量字段
總是需要為網(wǎng)格包布局中的每個區(qū)域設置增量字段(weightx和weighty)。如果將增量設置為0,那么這個區(qū)域在該方向上永遠為初始大小,不會擴大或收縮。
另一方面,如果將所有區(qū)域的增量都設置為0,容器就會擠在所分配區(qū)域的中間,而不會拉伸來填充空間。
從概念上講,增量參數(shù)的問題在于增量是行和列的屬性,而不是各個單元格的屬性。但你卻需要為單元格指定增量,因為網(wǎng)格包布局并不對外提供行和列。行和列的增量等于每行或每列中單元格增量的最大值。因此,如果想讓一行或一列的大小保持不變,就需要將其中所有組件的增量都設置為0。
注意,增量并不實際給出列的相對大小。當容器超過首選大小時,增量會指出“閑散”空間按什么比例分配給各個區(qū)域。這么說不太直觀。我們建議將所有的增量設置為10,然后運行程序,查看布局情況。調整這個對話框的大小,再來看行和列是如何調整的。如果發(fā)現(xiàn)某行或某列不應該擴大,就將那一行或那一列中的所有組件的增量設置為0。也可以調整為其他增量值,但是那么做的意義并不大。
3)、fill和anchor參數(shù)
如果不希望組件拉伸至填滿整個區(qū)域,就需要設置fill約束。這個參數(shù)有4個可能的取值:
GridBag Constraints.NONEGridBagConstraints.HORIZONTALGridBagConstraints.VERTICALGridBagConstraints.BOTH
如果組件沒有填充整個區(qū)域,可以通過設置anchor字段指定它在這個區(qū)域中的位置。有效值為:
GridBagConstraints.CENTER(默認值)GridBagConstraints.NORTHGridBagConstraints.NORTHEASTGridBagConstraints.EAST
4)、填充
可以通過設置GridBagConstraints的insets字段在組件周圍增加額外的空白區(qū)域。通過設置Insets對象的left、top、right和bottom值指定組件周圍的空間大小。這被稱作外部填充(external padding)。
ipadx和ipady值可以指定內部填充(internal padding)。這兩個值會加到組件的最小寬度和最小高度上,這樣可以保證組件不會收縮至其最小尺寸以下。
5)、指定gridx、gridy、gridwidth和gridheight參數(shù)的備用方法
AWT文檔建議不要將gridx和gridy設置為絕對位置,而應該將它們設置為常量GridBagConstraints.RELATIVE。然后,按照標準的順序將組件添加到網(wǎng)格包布局中,即首先在第一行從左向右增加,然后再轉到新的一行,依此類推。
還需要為gridheight和gridwidth字段提供適當?shù)闹祦碇付ńM件所跨的行數(shù)和列數(shù)。不過,如果組件擴展至最后一行或最后一列,則不需要指定具體的數(shù),而是可以使用常量 GridBagConstraints.REMAINDER,這樣會告訴布局管理器這個組件是該行上的最后一個組件。
這種方案看起來是可行的,但似乎有點笨拙。這是因為這樣做會對布局管理器隱藏具體的位置信息,并希望它能夠重新發(fā)現(xiàn)這些信息。
6)、網(wǎng)格包布局技巧
在實際中,利用下面的技巧,可以讓網(wǎng)格包布局的使用沒那么麻煩:
在紙上畫出組件布局草圖。找出一個網(wǎng)格,小組件分別包含在一個單元格內,更大的組件會跨越多個單元格。用0,1,2,3…標識網(wǎng)格的行和列?,F(xiàn)在可以得出gridx、gridy、gridwidth和gridheight的值。對于每個組件,需要考慮以下問題:是否需要水平或者垂直填充它所在的單元格?如果不需要,希望如何對齊?這些就是fill和anchor參數(shù)的設置。將所有的增量設置為100。不過,如果希望某行或某列始終保持默認的大小,就將這行或這列中所有組件的weightx和weighty設置為0。編寫代碼。仔細地檢查GridBagConstraints的設置。錯誤的約束可能會破壞整個布局。編譯并運行,你會看到滿意的布局。
7)、使用幫助類管理網(wǎng)格包約束
網(wǎng)格包布局最乏味的方面就是要編寫代碼設置約束。為此,大多數(shù)程序員會編寫幫助函數(shù)或者一個小幫助類。下面將在字體對話框示例的代碼后面給出一個幫助類。這個類有以下特性:
名字簡短:GBC而不是GridBagConstraints。它擴展了GridBagConstraints,因此常量可以使用更短的名字,如GBC.EAST。當添加組件時,使用GC對象,如:
add(component,new GBC(1,2))
有兩個構造器可以用來設置最常用的參數(shù):gridx和gridy,或者gridx、gridy、gridwidth和gridheight
add (component,new GBC(1,2,1,4))
對于以xy值對出現(xiàn)的字段,提供了便捷的設置方法:
add(component,new GBC(1,2).setweight(100,100));
設置器方法將返回this,所以可以串鏈這些方法調用:
add(component,new GBC(1,2).setAnchor(GBC.EAST).setWeight(100,100));
setInsets方法將構造Insets對象。要想獲取1個像素的insets,可以調用:
add(component,new GBC(1,2).setAnchor(GBC.EAST).setInsets(1));
8)、完整示例
public class GBC extends GridBagConstraints {
public GBC(int gridx, int gridy) {
this.gridx = gridx;
this.gridy = gridy;
}
public GBC(int gridx, int gridy, int gridwidth, int gridheight) {
this.gridx = gridx;
this.gridy = gridy;
this.gridwidth = gridwidth;
this.gridheight = gridheight;
}
public GBC setAnchor(int anchor) {
this.anchor = anchor;
return this;
}
public GBC setFill(int fill) {
this.fill = fill;
return this;
}
public GBC setWeight(double weightx, double weighty) {
this.weightx = weightx;
this.weighty = weighty;
return this;
}
public GBC setInsets(int distance) {
this.insets = new Insets(distance, distance, distance, distance);
return this;
}
public GBC setInsets(int top, int left, int bottom, int right) {
this.insets = new Insets(top, left, bottom, right);
return this;
}
public GBC setIpad(int ipadx, int ipady) {
this.ipadx = ipadx;
this.ipady = ipady;
return this;
}
}
public class FontFrame extends JFrame {
public static final int TEXT_ROWS = 10;
public static final int TEXT_COLUMS = 20;
private JComboBox
private JComboBox
private JCheckBox bold;
private JCheckBox italic;
private JTextArea sample;
public FontFrame() {
GridBagLayout layout = new GridBagLayout();
setLayout(layout);
ActionListener listener = event -> updateSample();
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_COLUMS);
sample.setText("The quick brown fox jumps over the lazy dog");
sample.setEditable(false);
sample.setLineWrap(true);
sample.setBorder(BorderFactory.createEtchedBorder());
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();
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
JFrame frame = new FontFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
});
}
}
9)、API
java.awt.GridBagConstraints:
int gridx,gridy:指定單元格的起始行和列。默認值為0int gridwidth,gridheight:指定單元格的行和列的范圍。默認值為1double weightx,weighty:指定單元格擴大的容量。默認值為0int anchor:表示組件在單元格內的對齊方式??梢赃x擇的絕對位置包括:
NORTHWESTNORTHNORTHEASTWESTCENTEREASTSOUTHWESTSOUTHSOUTHEAST或者各個方向上的相對位置:FIRST_LINE_STARTLINE_STARTFIRST_LINE_ENDPAGE_STARTCENTERPAGE_ENDLAST_LINE_STARTLINE_ENDLAST_LINE_END如果你的應用要本地化為從右向左或者從上向下排列文本,就應該使用后者。默認值為CENTER。 int fill:指定組件在單元格內的填充行為,取值為NONE、BOTH、HORIZONTAL或者VERTICAL。默認值 為NONEint ipadx,ipady:指定組件周圍的“內部”填充。默認值為0Insets insets:指定組件邊框周圍的“外部”填充。默認為不填充。GridBagConstraints(int gridx,int gridy,int gridwidth,int gridheight,double weightx, double weighty,int anchor,int fill,Insets insets,int ipadx,int ipady):用參數(shù)中給定的所有字段值構造GridBagConstraints。這個構造器只用于自動代碼生成器,因為它會讓你的源代碼很難閱讀
6.2、定制布局管理器
可以設計你自己的LayoutManager類以一種特殊的方式管理組件。作為一個有趣的例子,可以將容器中的組件排列成一個圓形。
定制布局管理器必須實現(xiàn)LayoutManager接口,并且需要覆蓋下面5個方法:
void addLayoutComponent(String s,Component c)
void removeLayoutComponent(Component c)
Dimension preferredLayoutSize(Container parent)
Dimension minimumLayoutSize(Container parent)
void layoutContainer(Container parent)
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;
@Override
public void addLayoutComponent(String name, Component comp) {
}
@Override
public void removeLayoutComponent(Component comp) {
}
@Override
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);
}
@Override
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);
}
@Override
public void layoutContainer(Container parent) {
setSizes(parent);
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;
int xradius = (containerWidth - maxComponentWidth) / 2;
int yradius = (containerHeight - maxComponentHeight) / 2;
int radius = Math.min(xradius, yradius);
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;
int x = xcenter + (int)(Math.cos(angle) * radius);
int y = ycenter + (int)(Math.sin(angle) * radius);
Dimension d = c.getPreferredSize();
c.setBounds(x - d.width / 2, y - d.height / 2, d.width, d.height);
}
}
}
public void setSizes(Container parent) {
if (sizesSet) {
return;
}
int n = parent.getComponentCount();
preferredWidth = 0;
preferredHeight = 0;
minWidth = 0;
minHeight = 0;
maxComponentWidth = 0;
maxComponentHeight = 0;
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 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();
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
JFrame frame = new CircleLayoutFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
});
}
}
java.awt.LayoutManager:
void addLayoutComponent(String name,Component comp):將組件添加到布局中void removeLayoutComponent(Component comp):從布局刪除一個組件Dimension preferredLayoutSize(Container cont):返回這個布局中容器的首選尺寸Dimension minimumLayoutSize(Container cont):返回這個布局中容器的最小尺寸void layoutContainer(Container cont):在容器中擺放的組件
7、對話框
到目前為止,所有的用戶界面組件都顯示在應用程序創(chuàng)建的窗體窗口中。如果編寫運行在Web瀏覽器中的applet,這是最常見的情況。但是,如果你要編寫應用程序,通常就需要有不同的對話框向用戶顯示信息或者獲取用戶提供的信息。
與大多數(shù)的窗口系統(tǒng)一樣,AWT也分為模式對話框和無模式對話框。所謂模式對話框是指在結束對它的處理之前,不允許用戶與應用程序的其余窗口進行交互。模式對話框主要用于在程序繼續(xù)運行之前獲取用戶提供的信息。例如,當用戶想要讀取一個文件時,就會彈出一個模式文件對話框。用戶必須給定一個文件名,然后程序才能夠開始讀操作。只有用戶關閉這個模式對話框之后,應用才能夠繼續(xù)執(zhí)行。
無模式對話框允許用戶同時在對話框和應用程序的其他部分輸入信息。使用無模式對話框的一個例子就是工具條。只要需要,工具條可以??吭谌魏蔚胤?,而且用戶可以根據(jù)需要同時與應用窗口和工具條進行交互。
7.1、選項對話框
Swing有一組現(xiàn)成的簡單對話框,足以讓用戶提供一些信息。JOptionPane有4個用于顯示這些對話框的靜態(tài)方法:
showMessageDialog:顯示一條消息并等待用戶點擊OK;showConfirmDialog:顯示一條消息并等待用戶確認(如OK/Cancel):showOptionDialog:顯示一條消息并獲得用戶在一組選項中的選擇;showInputDialog:顯示一條消息并獲得用戶輸人的一行文本。
對話框有以下組件:
一個圖標一條消息一個或多個選項按鈕
輸入對話框有一個用于接收用戶輸人的額外組件。這可能是一個文本域,用戶可以輸入任何的字符串,也可能是一個組合框,用戶可以從中選擇一項。
這些對話框的具體布局和為標準消息類型選擇的圖標都取決于可插接式觀感。左側的圖標取決于下面5種消息類型:
ERROR_MESSAGEINFORMATION_MESSAGEWARNING_MESSAGEQUESTION_MESSAGEPLAIN_MESSAGE
PLAIN_MESSAGE類型沒有圖標。每個對話框類型都有一個方法,可以用來提供自己的圖標,以替代原來的圖標??梢詾槊總€對話框類型指定一條消息。這里的消息既可以是字符串、圖標、用戶界面組件,也可以是其他類型的對象??梢匀缦嘛@示消息對象:
String:繪制字符串;Icon:顯示圖標;Component:顯示組件;Object[]:顯示數(shù)組中的所有對象,依次疊加任何其它對象:調用toString()方法來顯示結果字符串
當然,提供字符串消息是目前為止最常見的情況,而提供一個Component會帶來更大的靈活性,這是因為可以讓paintComponent方法繪制你想要的任何內容。位于底部的按鈕取決于對話框類型和選項類型。當調用showMessageDialog和showInputDialog時,只能看到一組標準按鈕(分別是OK和OK/Cancel)。當調用showConfirmDialog時,可以在下面四種選項類型中選擇:
DEFAULT_OPTIONYES_NO_OPTIONYES_NO_CANCEL_OPTIONOK_CANCEL_OPTION
使用showOptionDialog時,可以指定一組任意的選項。你要提供一個對象數(shù)組作為選項。 每個數(shù)組元素會如下顯示:
String:創(chuàng)建一個按鈕,使用字符串作為標簽;Icon:創(chuàng)建一個按鈕,使用圖標作為標簽;Component:顯示這個組件;其他類型的對象:應用toString方法,然后創(chuàng)建一個按鈕,用結果字符串作為標簽。
這些方法的返回值如下:
showMessageDialog:無;showConfirmDialog:表示所選項的一個整數(shù);show0 ptionDialog:表示所選項的一個整數(shù);showInputDialog:用戶提供或選擇的字符串;
showConfirmDialog和showOptionDialog返回一個整數(shù),表示用戶選擇了哪個按鈕。對于選項對話框來說,這個值就是所選選項的索引值,或者是CLOSED0_PTION(此時用戶沒有選擇選項,而是關閉了對話框)。對于確認對話框,返回值可以是以下值之一:
OK_OPTIONCANCEL_OPTIONYES_OPTIONNO_OPTIONCLOSED_OPTION
這些選項看上去讓人有些困惑,實際上非常簡單。步驟如下:
選擇對話框的類型(消息、確認、選項或者輸入)。選擇圖標(錯誤、信息、警告、問題、無或者自定義)。選擇消息(字符串、圖標、自定義組件或者它們的集合)。對于確認對話框,選擇選項類型(默認、Yes/No、Yes/No/Cancel或者OK/Cancel)。對于選項對話框,選擇選項(字符串、圖標或者自定義組件)和默認選項。對于輸入對話框,選擇文本域或者組合框。調用JOptionPane API中的相應方法。
例如,對話框顯示了一條消息,并請求用戶確認或者取消。這是一個確認對話框。圖標是一個問題圖標,消息是字符串,選項類型是OK_CANCEL_OPTION。調用如下:
int selection = JOptionPane.showConfirmDialog(parent,
"Message","Title",
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE);
if (selection =JOptionPane.OK OPTION){
...
}
javax.swing.JoptionPane:
static void showMessageDialog(Component parent,Object message,String title,int messageType, Icon icon)static void showMessageDialog(Component parent,Object message,String title,int messageType) static void showMessageDialog(Component parent,Object message)static void showInternalMessageDialog(Component parent,Object message,String title,int messageType,Icon icon)static void showInternalMessageDialog(Component parent,Object message,String title,int messageType)static void showInternalMessageDialog(Component parent,object message):顯示一個消息對話框或者一個內部消息對話框(內部對話框完全顯示在其父組件窗體內)。父組件可以為ul1。顯示在對話框中的消息可以是字符串、圖標、組件或者它們的一個數(shù)組。messageType參數(shù)取值為ERROR MESSAGE、INFORMATION MESSAGE、WARNING_MESSAGE、QUESTION MESSAGE和PLAIN MESSAGE之一static int showConfirmDialog(Component parent,Object message,String title,int optionType, int messageType,Icon icon)static int showConfirmDialog(Component parent,Object message,String title,int optionType, int messageType)static int showConfirmDialog(Component parent,Object message,String title,int optionType) static int showConfirmDialog(Component parent,Object message)static int showInternalConfirmDialog(Component parent,object message,String title,int optionType,int messageType,Icon icon)static int showInternalConfirmDialog(Component parent,Object message,String title,int optionType,int messageType)static int showInternalConfirmDialog(Component parent,Object message,String title,int optionType)static int showInternalConfirmDialog(Component parent,object message):顯示一個確認對話框或者內部確認對話框(內部對話框完全顯示在其父組件窗體內)。返回用戶選擇的選項(取值為OK OPTION、CANCEL OPTION、YES OPTION或NO OPTION);如果 用戶關閉對話框將返回CL0 SED OPTI0N。父組件可以為ulL。顯示在對話框中的消息可以是字符串、圖標、組件或者它們的一個數(shù)組。messageType參數(shù)取值為ERROR MESSAGE、INFORMATION MESSAGE、WARNING MESSAGE、QUESTION MESSAGE、PLAIN MESSAGE之一。optionType取值為DEFAULT OPTION、YES NO OPTION、YES NO CANCEL OPTION、OK CANCEL OPTION之一。static int showoptionDialog(Component parent,Object message,String title,int optionType, int messageType,Icon icon,Object[]options,Object default)static int showInternalOptionDialog(Component parent,Object message,String title,int optionType,int messageType,Icon icon,Object[]options,Object default):顯示一個選項對話框或者內部選項對話框(內部對話框完全顯示在其父組件窗體內)。返回用戶所選選項的索引;或者如果用戶取消了對話框則返回CL0SD0TION。父組件可以為null。顯示在對話框中的消息可以是字符串、圖標、組件或者它們的一個數(shù)組。messageType參數(shù)取值為ERROR_MESSAGE、INFORMATION_MESSAGE、WARNING_MESSAGE、QUESTION_MESSAGE、PLAIN_MESSAGE之一。optionType取值為DEFAULT_OPTION、YES_NO_OPTION、YES_NO_CANCEL_OPTION、OK_CANCEL_OPTION之一。options參數(shù)是字符串、圖標或者組件的一個數(shù)組。static Object showInputDialog(Component parent,Object message,String title,int messageType, Iconicon,Object[]values,Object default)static String showInputDialog(Component parent,Object message,String title,int messageType) static String showInputDialog(Component parent,Object message)static String showInputDialog(Object message) static String showInputDialog(Component parent,Object message,Object default)static String showInputDialog(Object message,Object default)static Object showInternalInputDialog(Component parent,Object message,String title,int messageType,Icon icon,Object[]values,Object default) static String showInternalInputDialog(Component parent,Object message,String title,int messagelype)static String showInternalInputDialog(Component parent,Object message):顯示一個輸入對話框或者內部輸入對話框(內部對話框完全顯示在其父組件窗體內)。返回用戶輸入的字符串;或者如果用戶取消了對話框則返回ul。父組件可以為ulL。顯示在對話框中的消息可以是字符串、圖標、組件或者它們的一個數(shù)組。messageType參數(shù)取值為ERROR_MESSAGE、INFORMATION_MESSAGE、WARNING_MESSAGE、QUESTION_MESSAGE、PLAIN_MESSAGE之一。
7.2、創(chuàng)建對話框
要想實現(xiàn)一個對話框,需要擴展JDialog類。這與應用程 序窗口擴展JFrame的過程完全一樣。具體過程如下:
在對話框構造器中,調用超類JDialog的構造器。添加對話框的用戶界面組件。添加事件處理器。設置對話框的大小。
調用超類構造器時,需要提供所有者窗體(owner frame) 對話框標題及模式特征。
所有者窗體控制對話框的顯示位置,如果提供null作為所有者,那么這個對話框將屬于一個隱藏窗體。模式特征將指定顯示這個對話框時阻塞應用程序的哪些其他窗口。無模式對話框不會阻塞其他窗口,而模式對話框將阻塞應用的所有其他窗口(除當前對話框的子窗口外)。用戶經(jīng)常使用的工具條要使用無模式對話框實現(xiàn)。另一方面,如果想強制用戶在繼續(xù)操作之前必須提供一些必要的信息,就應該使用模式對話框。
public class AboutDialog extends JDialog {
public AboutDialog(JFrame owner) {
super(owner, "About DialogTest", true);
add(new JLabel("
Core Java
By Cay Horstmann"), BorderLayout.CENTER);JButton ok = new JButton("OK");
ok.addActionListener(event -> setVisible(false));
JPanel panel = new JPanel();
panel.add(ok);
add(panel, BorderLayout.SOUTH);
pack();
}
}
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);
JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);
JMenu fileMenu = new JMenu("File");
menuBar.add(fileMenu);
JMenuItem aboutItem = new JMenuItem("About");
aboutItem.addActionListener(event -> {
if (dialog == null) {
dialog = new AboutDialog(DialogFrame.this);
}
dialog.setVisible(true);
});
fileMenu.add(aboutItem);
JMenuItem exitItem = new JMenuItem("Exit");
exitItem.addActionListener(event -> System.exit(0));
fileMenu.add(exitItem);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
JFrame frame = new DialogFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
});
}
}
javax.swing.JDialog:
public JDialog(Frame parent, String title, boolean modal):構造一個對話框。在顯式顯示對話框之前,這個對話框是不可見的。
7.3、數(shù)據(jù)交互
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private String username;
private char[] password;
}
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());
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);
okButton = new JButton("OK");
okButton.addActionListener(event -> {
ok = true;
dialog.setVisible(false);
});
JButton cancelButton = new JButton("Cancel");
cancelButton.addActionListener(event -> dialog.setVisible(false));
JPanel buttonPanel = new JPanel();
buttonPanel.add(okButton);
buttonPanel.add(cancelButton);
add(buttonPanel, BorderLayout.SOUTH);
}
public void setUser(User u) {
username.setText(u.getUsername());
}
public User getUser() {
return new User(username.getText(), password.getPassword());
}
public boolean showDialog(Component parent, String title) {
ok = false;
Frame owner = null;
if (parent instanceof Frame) {
owner = (Frame)parent;
} else {
owner = (Frame)SwingUtilities.getAncestorOfClass(Frame.class, parent);
}
if (dialog == null || dialog.getOwner() != owner) {
dialog = new JDialog(owner, true);
dialog.add(this);
dialog.getRootPane().setDefaultButton(okButton);
dialog.pack();
}
dialog.setTitle(title);
dialog.setVisible(true);
return ok;
}
}
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() {
JMenuBar mbar = new JMenuBar();
setJMenuBar(mbar);
JMenu fileMenu = new JMenu("File");
mbar.add(fileMenu);
JMenuItem connectItem = new JMenuItem("Connect");
connectItem.addActionListener(new ConnectAction());
fileMenu.add(connectItem);
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();
}
private class ConnectAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
if (dialog == null) {
dialog = new PasswordChooser();
}
dialog.setUser(new User("yourname", null));
if (dialog.showDialog(DataExchangeFrame.this, "Connect")) {
User u = dialog.getUser();
textArea.append("user name = " + u.getUsername() + ", password = " + (new String(u.getPassword())) + "\n");
}
}
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
JFrame frame = new DataExchangeFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
});
}
}
javax.swing.SwingUtilities:
Container getAncestorofClass(Class c,Component comp):返回屬于給定類或其某個子類的給定組件的最內層父容器。
javax.swing.JComponent:
JRootPane getRootPane():獲得包含這個組件的根窗格,如果這個組件沒有帶根窗格的祖先,則返回null。 javax.swing.JRootPane: void setDefaultButton(JButton button):設置根窗格的默認按鈕。要想禁用默認按鈕,可以提供null參數(shù)來調用這個方法。
javax.swing.JButton:
boolean isDefaultButton():如果這個按鈕是其根窗格的默認按鈕,返回true。
7.4、文件對話框
在一個應用中,通常希望可以打開和保存文件。一個好的文件對話框應該可以顯示文件和目錄,允許用戶瀏覽文件系統(tǒng),這樣一個文件對話框很難編寫,人們肯定不愿意從頭做起。很幸運,Swing中提供了JFileChooser類,它顯示的文件對話框類似于大多數(shù)原生應用所用的對話框。JFileChooser對話框總是模式對話框。注意,JFileChooser類并不是JDialog類的子類。需要調用show0 penDialog 顯示打開文件的對話框,或者調用showSaveDialog顯示保存文件的對話框,而不是調用setVisible(true)。接收文件的按鈕會自動地使用標簽Open或者Save。也可以調用showDialog方法為按鈕提供你自己的標簽。圖11-33是文件選擇器對話框的一個示例。
下面是建立文件對話框并獲取用戶選擇信息的步驟:
建立一個JFileChooser對象。與JDialog類的構造器不同,不需要指定父組件。這就允許你在多個窗體中重用一個文件選擇器。例如:
var chooser = new JFileChooser();
調用setCurrentDirectory方法設置目錄。例如,要使用當前的工作目錄:
chooser.setCurrentDirectory(new File("."));
需要提供一個File對象。File對象將在卷Ⅱ的第2章中詳細介紹。這里只需要知道構造器File(String fileName)能夠將一個文件或目錄名轉化為一個File對象。
如果有一個希望用戶選擇的默認文件名,可以使用setSelectedFile方法指定:
chooser.setSelectedFile(new File(filename));
如果允許用戶在對話框中選擇多個文件,需要調用setMultiSelectionEnabled方法。當然,這是可選的,而且并不常見。
chooser.setMultiSelectionEnabled(true);
如果想讓對話框只顯示某種特定類型的文件(如,所有擴展名為.gif的文件),需要設置文件過濾器,稍后將會討論文件過濾器。在默認情況下,用戶只能在文件選擇器中選擇文件。如果希望用戶選擇目錄,需要使用setFileSelectionMode方法。調用時可以提供以下參數(shù):JFileChooser.FILES ONLY(默認值),JFileChooser.DIRECTORIES_ONLY或者 JFileChooser.FILES_AND_DIRECTORIES調用showOpenDialog或者showSaveDialog方法顯示對話框。在這些調用中必須提供父組件:
int result = chooser.showOpenDialog(parent);
或者
int result = chooser.showSaveDialog(parent);
這些調用的唯一區(qū)別是“確認按鈕”的標簽不同?!按_認按鈕”就是用戶點擊來完成文件選擇的那個按鈕。也可以調用showDialog方法,并將一個顯式的文本傳遞給確認按鈕:
int result chooser.showDialog(parent,"Select");
僅當用戶確認、取消或者關閉對話框時這些調用才返回。返回值可以是JFileChooser. APPROVE_OPTION、JFileChooser.CANCEL_OPTION或者JFileChooser.ERROR_OPTION。 8.調用getSelectedFile()或者getSelectedFiles()方法獲取用戶選擇的一個或多個文件。這些方法將返回一個File對象或者一個File對象數(shù)組。如果需要知道文件對象名,可以調用 getPath方法。例如:
String filename chooser.getSelectedFile().getPath();
在大多數(shù)情況下,這些步驟都很簡單。使用文件對話框的主要困難在于指定一個要讓用戶從中選擇文件的文件子集。例如,假設用戶應該選擇GF圖像文件。那么,文件選擇器就應該只顯示擴展名為,9f的文件。另外,還應該為用戶提供反饋信息,來說明所顯示的文件屬于某個特定文件類別,如“GF圖像”。不過,情況有可能會更加復雜。如果用戶應該選擇JPFG圖像文件,擴展名就可以是.jpg或者.jpeg。文件選擇器的設計者沒有編寫代碼來實現(xiàn)這種復雜性,而是提供了一種更優(yōu)雅的機制:要想限制所顯示的文件,可以提供一個擴展了抽象類javax.swing…filechooser.FileFilter的對象。文件選擇器將各個文件傳遞給文件過濾器,只有文件過濾器接受的文件才會顯示。
有兩個子類:一個是可以接受所有文件的默認過濾器,另一個過濾器可以接受給定擴展名的所有文件。不過,很容易編寫專用文件過濾器,只需實現(xiàn)FileFilter超類中的兩個抽象方法:
public boolean accept(File f);public String getDescription();
第一個方法檢測是否應該接受一個文件,第二個方法返回可能在文件選擇對話框中顯示的文件類型的描述信息。
一旦有了文件過濾器對象,可以調用JFileChooser類的setFileFilter方法,將這個對象安裝到文件選擇器對象中:
chooser.setFileFilter(new FileNameExtensionFilter("Image files","gif","jpg"));
可以為一個文件選擇器安裝多個過濾器,如下:
chooser.addChoosableFileFilter(filterl);
chooser.addChoosableFileFilter(filter2);
用戶可以從文件對話框底部的組合框中選擇過濾器。在默認情況下,組合框中總是顯示“All files”過濾器。這是一個好主意,因為使用這個程序的用戶有可能需要選擇一個具有非標準擴展名的文件。不過,如果你想禁用All files過濾器,需要調用:
chooser.setAcceptAllFileFilterUsed(false)
最后,可以為文件選擇器顯示的每個文件提供特定的圖標和文件描述來定制文件選擇器。為此,需要提供-一個類對象,這個類要擴展javax.swing.filechooser包中的FileView類。
這顯然是一種高級技術。通常情況下,并不需要你來提供文件視圖一可插接式觀感會為你提供一個視圖。不過,如果想為特殊的文件類型顯示不同的圖標,也可以安裝你自己的文件視圖。需要擴展FileView類并實現(xiàn)下面5個方法:
Icon getIcon(File f)
String getName(File f)
String getDescription(File f)
String getTypeDescription(File f)
Boolean isTraversable(File f)
然后,使用setFileView方法將文件視圖安裝到文件選擇器中。
文件選擇器會為希望顯示的每個文件或目錄調用這些方法。如果方法返回的圖標、名字或描述信息為ul1,那么文件選擇器會使用當前觀感的默認文件視圖。這樣處理很好,因為這意味著只需要處理那些希望有不同顯示的文件類型。
文件選擇器調用isTraversable方法來決定用戶點擊一個目錄時是否打開這個目錄。請注意,這個方法返回一個Boolean對象,而不是boolean值??雌饋硭坪跤悬c怪,但實際上很方便一如果只需要使用默認文件視圖,則返回ull。文件選擇器就會使用默認的文件視圖。換句話說,這個方法返回的Boolean.對象能給出3種選擇:真(Boolean.TRUE)、假(Boolean.FALSE)和不關心(nuLL)。
示例程序中包含了一個簡單的文件視圖類。只要一個文件匹配文件過濾器,這個類將會顯示一個特定的圖標??梢岳眠@個類為所有圖像文件顯示一個調色板圖標。
class FileIconView extends FileView
{
private FileFilter filter;
private Icon icon;
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;
}
}
可以調用setFileView方法將這個文件視圖安裝到文件選擇器:
chooser.setFileView(new FileIconView(filter,
new ImageIcon("palette.gif")));
文件選擇器會在通過filter過濾的所有文件旁邊顯示調色板圖標,而使用默認的文件視圖顯示所有其他的文件。很自然地,我們使用了文件選擇器中設置的過濾器。
javax.swing.JFileChooser:
JFileChooser():創(chuàng)建一個可用于多個窗體的文件選擇器對話框。void setCurrentDirectory(File dir):設置文件對話框的初始目錄。void setSelectedFile(File file)void setSelectedFiles(File[]file):設置文件對話框的默認文件選擇。void setMultiSelectionEnabled(boolean b):設置或清除多選模式。void setFileSelectionMode(int mode):設置用戶選擇模式,只可以選擇文件(默認),只可以選擇目錄,或者文件和目錄均可以選擇。mode參數(shù)的取值可以是JFileChooser.FILES ONLY、JFileChooser.DIRECTORIES ONLY和JFileChooser.FILES AND DIRECTORIES之一。int showOpenDialog(Component parent)int showSaveDialog(Component parent)int showDialog(Component parent,String approveButtonText):顯示一個對話框,確認按鈕標簽為“Open”“Save”或者approveButtonText字符串,并返回APPROVE OPTION、CANCEL OPTION(如果用戶選擇取消按鈕或者關閉了對話框)或者ERROR OPTION(如果發(fā)生錯誤)。File getSelectedFile()File[]getSelectedFiles():獲取用戶選擇的一個文件或多個文件(如果用戶沒有選擇文件,返回null)。void setFileFilter(FileFilter filter):設置文件對話框的文件過濾器。所有讓filter.accept返回true的文件都會顯示,并且將這個過濾器添加到可選過濾器列表中。void addChoosableFileFilter(FileFilter filter):將文件過濾器添加到可選過濾器列表中。void setAcceptAllFileFilterUsed(boolean b):在過濾器組合框中包括或者取消“All files”過濾器。void resetChoosableFileFilters():清除可選過濾器列表。除非“A1fils”過濾器被顯式地清除,否則它仍然保留。void setFileview(Fileview view):設置一個文件視圖來提供文件選擇器顯示的有關文件的信息。void setAccessory(JComponent component):設置一個附件組件。
javax.swing.filechooser.FileFilter:
boolean accept(File f):如果文件選擇器顯示這個文件,返回true。String getDescription():返回這個文件過濾器的一個描述,例如,“Image files(.gif- ,.jpeg)”。
javax.swing.filechooser.FileNameExtensionFilter:
FileNameExtensionFilter(String description,String…extensions):利用給定的描述構造一個文件過濾器,它接受名字以特定方式結尾的所有目錄和文件,即有一個點號,后面緊跟給定的某個擴展名字符串。
javax.swing.filechooser.FileView:
String getName(File f):返回文件f的文件名,或者null。正常情況下這個方法簡單地返回f.getName()。String getDescription(File f):返回關于文件f的人類可讀的一個描述,或者ull。例如,如果f是HTML文檔,那么這個方法可能返回它的標題。String getTypeDescription(File f):返回關于文件f類型的人類可讀的一個描述,或者ull。例如,如果文件f是HTML文檔,那么這個方法可能返回字符串"Hypertext document’"。Icon getIcon(File f):返回文件f的圖標,或者ull。例如,如果f是PEG文件,那么這個方法可能返回縮略圖標。Boolean isTraversable(File f):如果f是用戶可以打開的目錄,返回Boolean.TUE。如果一個目錄在概念上是復合文檔,那么這個方法可能返回Boolean.false.。與所有的FileView方法一樣,這個方法有可能返回null,表示文件選擇器應該使用默認視圖。
柚子快報邀請碼778899分享:Java——Swing詳解
相關文章
本文內容根據(jù)網(wǎng)絡資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉載請注明,如有侵權,聯(lián)系刪除。