快顯視窗與選取器(五)

來源:互聯網
上載者:User
9.5 JFileChooser類

Swing組件集合約時提供了用於選擇檔案名稱字與目錄的選取器:JFileChooser類。這個選取器替換了原始AWT組件集合中使用FileDialog的需要。類似於其他的Swing選取器組件,JFileChooser並沒有自動被放入一個快顯視窗中,但是他可以放在我們程式中使用者介面的任何地方。圖9-25顯示了一個具有Metal觀感,Ocean主題的JFileChooser,他被自動放在一個模態JDialog中。

對JFileChooser提供支援的是javax.swing.filechooser包中的大量類。這些支援類包括用於限制列出在JFileChooser的FileView的檔案與目錄。FileView控制目錄與檔案如何列在JFileChooser中。FileSystemView是一個嘗試由選取器隱藏檔案系統相關的作業系統細節的一個抽象類別。Java 2平台提供者將會提供特定作業系統的版本,從而類似列出根分區這樣的任務可以實現(使用100%純Java代碼)。

注意,不要混淆javax.swing.filechooser.FileFilter抽象類別與java.io.FileFilter介面。儘管功能類似,但是他們是不同的。他們兩個共存是因為java.io.FileFilter介面並不存在於Java 1.1運行時中。因為原始的Swing JFileChooser需要同時運行在Java 1.1與Java 2一部 ,選取器需要定義一個替換。除非特別指定,本部分的所有FileFilter引用位於javax.swing.filechooser包中的類。

9.5.1 建立JFileChooser

JFileChooser有六個建構函式:

public JFileChooser()JFileChooser fileChooser = new JFileChooser();public JFileChooser(File currentDirectory)File currentDirectory = new File("."); // starting directory of programJFileChooser fileChooser = new JFileChooser(currentDirectory);public JFileChooser(File currentDirectory, FileSystemView fileSystemView)FileSystemView fileSystemView = new SomeFileSystemView(...);JFileChooser fileChooser = new JFileChooser(currentDirectory, fileSystemView);public JFileChooser(FileSystemView fileSystemView)JFileChooser fileChooser = new JFileChooser(fileSystemView);public JFileChooser(String currentDirectoryPath)String currentDirectoryPath = "."; // starting directory of programJFileChooser fileChooser = new JFileChooser(currentDirectoryPath);public JFileChooser(String currentDirectoryPath, FileSystemView fileSystemView)JFileChooser fileChooser = new JFileChooser(currentDirectoryPath, fileSystemView);

預設情況下,顯示的起始目錄是使用者主目錄(系統屬性user.home)。如果我們希望啟動JFileChooser指向其他的目錄,這個目錄可以使用String或是File對象進行指定。

我們也可以指定一個FileSystemView來指定作業系統頂層目錄結構的自訂表格示。當沒有指定FileSystemView參數時,JFileChooser使用適合於使用者作業系統的FileSystemView。

9.5.2 使用JFileChooser

在由建構函式建立JFileChooser之後,我們可以將其放在任何的Container中,因為他是一個JComponent。位於非快顯視窗對象中的JFileChooser對象看起來有一些奇怪,但是這可以使得我們完成一些無需建立新檔案選取器的任務。

列表9-13示範了帶有兩個標籤以及一個JFileChooser的簡單表單。注意,這個表單並沒有Open或是Cancel按鈕,但是位於FileSystemView地區的按鈕是可選擇的。

package swingstudy.ch09;import java.awt.BorderLayout;import java.awt.EventQueue;import java.awt.Font;import javax.swing.JFileChooser;import javax.swing.JFrame;import javax.swing.JLabel;public class FileSamplePanel {/** * @param args */public static void main(String[] args) {// TODO Auto-generated method stubRunnable runner = new Runnable() {public void run() {JFrame frame = new JFrame("JFileChooser Popup");frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);final JLabel directoryLabel = new JLabel("");directoryLabel.setFont(new Font("Serif", Font.BOLD | Font.ITALIC, 36));frame.add(directoryLabel, BorderLayout.NORTH);final JLabel filenameLabel = new JLabel("");filenameLabel.setFont(new Font("Serif", Font.BOLD | Font.ITALIC, 36));frame.add(filenameLabel, BorderLayout.SOUTH);JFileChooser fileChooser = new JFileChooser(".");fileChooser.setControlButtonsAreShown(false);frame.add(fileChooser, BorderLayout.CENTER);frame.pack();frame.setVisible(true);}};EventQueue.invokeLater(runner);}}

向JFileChooser添加ActionListener

JFileChooser允許我們添加ActionListener對象來監聽確認或是關閉動作的選擇。確認是雙擊一個檔案;關閉是按下Escape按鍵。要檢測激發了哪一個動作,我們可以檢測我們的ActionLister所接收到的ActionEvent的動作命令。其動作命令設定可以為用於檔案選擇的JFileChooser.APPROVE_SELECTION或是用於按下Escape按鍵的JFileChooser.CANCEL_SELECTION。

為了完成前面列表9-13中的樣本,添加一個ActionListener從而使得我們在使用者選擇檔案時設定兩個標籤的文本。一旦選擇,文本變為目前的目錄與檔案名稱。一旦按下Escape按鍵,文本會被清除。列表9-14顯示了新的ActionListener。

// create ActionListenerActionListener actionListener = new ActionListener() {public void actionPerformed(ActionEvent event) {JFileChooser theFileChooser = (JFileChooser)event.getSource();String command = event.getActionCommand();if(command.equals(JFileChooser.APPROVE_SELECTION)) {File selectedFile = theFileChooser.getSelectedFile();directoryLabel.setText(selectedFile.getParent());filenameLabel.setText(selectedFile.getName());}else if(command.equals(JFileChooser.CANCEL_SELECTION)) {directoryLabel.setText("");filenameLabel.setText("");}}};fileChooser.addActionListener(actionListener);

通過使用這個ActionListener,由選擇被啟用的角度來說程式是完整的了。圖9-26顯示了在選中了C:\jdb1.5.0目錄下的COPYRIGHT檔案之後視窗的樣子。

在快顯視窗中顯示JFileChooser

除了可以將JFileChooser放在我們自己的視窗以外,我們更為通常的是將其放在一個模態JDialog中。依據我們希望在確認按鈕上所顯示的文本,有三種方法可以實現:

  • public int showDialog(Component parentComponent, String approvalButtonText)
  • public int showOpenDialog(Component parentComponent)
  • public int showSaveDialog(Component parentComponent)

調用這些方法中的任何一個都可以將配置的JFileChooser放在一個模態JDialog中,並且在父組件的中間位置顯示對話方塊。提供一個null父組件參數會將快顯視窗放在螢幕中間。這個方法只有當使用者選擇確認或是關閉按鈕時才會返回。在選擇這兩個按鈕中的一個之後,調用會依據哪一個按鈕被選中而返回一個狀態值。這個狀態值可以是JFileChooser的三個常量之一:APPROVE_OPTION, CANCEL_OPTION或是ERROR_OPTION。

注意,如果使用者點擊了確認按鈕而沒有選擇任何檔案,則CANCEL_OPTION會返回。

為了執行與前面的例子相同的任務,其中是將一個ActionListener關聯到JFileChooser,我們可以顯示這個對話方塊並依據返回狀態修改標籤,而是不依賴於動作命令,如下所示:

JFileChooser fileChooser = new JFileChooser(".");int status = fileChooser.showOpenDialog(null);if (status == JFileChooser.APPROVE_OPTION) {  File selectedFile = fileChooser.getSelectedFile();  directoryLabel.setText(selectedFile.getParent());  filenameLabel.setText(selectedFile.getName());}  else if (status == JFileChooser.CANCEL_OPTION) {  directoryLabel.setText(" ");  filenameLabel.setText(" ");}

使用這一技術,檔案選取器將會在另一個視窗中顯示,而不是在具有兩個標籤的視窗中顯示。注意,這個版本是由檢測前面樣本中的String傳回值切換到檢測int傳回值:[if (command.equals(JFileChooser.APPROVE_SELECTION)) versus if (status == JFileChooser.APPROVE_OPTION)].

9.5.3 JFileChooser屬性

一旦我們理解了基本的JFileChooser的使用,我們可以通過修改其屬性來自訂群組件的行為與外觀。表9-10顯示了JFileChooser的26個屬性。

當使用不同的showDialog()方法時,dialogType屬性被自動化佈建為JOptionPane的三個常量之一:OPEN_DIALOG, SAVE_DIALOG, CUSTOM_DIALOG。如果我們沒有使用showDialog(),我們應該依據我們計劃使用的對話方塊類型來設定這個屬性。controlButtonsAreShown屬性可以使得我們隱藏Open, Save與Cancel按鈕。

9.5.4 使用檔案過濾器

JFileChooser支援三種過濾其檔案與目錄列表的方法。前兩個涉及到使用FileFilter類,而最後一個涉及到隱藏檔案。首先,我們來看一下FileFilter類。

FileFilter是一個抽象類別,其工作方式類似於AWT中的FilenameFilter。然而,這個並不使用目錄或是檔案名稱的字串,而是使用File對象。對於每一個要顯示的File對象(檔案與目錄),過濾器決定File是否要顯示在JFileChooser中。除了提供一個接受機制,當向使用者顯示描述時,過濾器同時提供了描述或名字。在下面的類定義的兩個方法反映了這種功能:

public abstract class FileFilter {  public FileFilter();  public abstract String getDescription();  public abstract boolean accept(File file);}

注意,由於這個類的抽象特性,他本應是一個介面,但事實上不是。

為了示範檔案過濾器,列表9-15建立了一個可以接受一個副檔名數組的過濾器。如果發送給accept()方法的檔案是一個目錄,則會被自動接受。否則,副檔名必須與所提供的數組中的副檔名匹配,而且副檔名前的字元必須是一個句點。對於這個特定的過濾器,比較是大小寫敏感的。

package swingstudy.ch09;import java.io.File;import javax.swing.filechooser.FileFilter;public class ExtensionFileFilter extends FileFilter {String description;String extensions[];public ExtensionFileFilter(String description, String extension) {this(description, new String[] {extension} );}public ExtensionFileFilter(String description, String extensions[]) {if(description == null) {// since no description, use first extension and # of extensions as descriptionthis.description = extensions[0]+"{ "+extensions.length+"} ";}else {this.description = description;}// convert array to lowercase// don't alter original entriesthis.extensions = (String[])extensions.clone();toLower(this.extensions);}private void toLower(String array[]) {for(int i=0, n=array.length; i<n; i++) {array[i] = array[i].toLowerCase();}}// ignore case, always accept directories// character before extension must be a period@Overridepublic boolean accept(File file) {// TODO Auto-generated method stubif(file.isDirectory()) {return true;}else {String path = file.getAbsolutePath().toLowerCase();for(int i=0, n=extensions.length; i<n; i++) {String extension = extensions[i];if(path.endsWith(extension) && (path.charAt(path.length()-extension.length()-1)=='.')) {return true;}}}return false;}@Overridepublic String getDescription() {// TODO Auto-generated method stubreturn description;}}

使用這個檔案過濾器可以使得我們建立並將其關聯到JFileChooser。如果我們只是想使得過濾器可以為使用者選擇,但是並不是預設的初始選擇,可以調用public void addChoosableFileFilter(FileFilter filter)。這可以使得預設的接受所有檔案的過濾器被選中。相反,如果我們希望過濾參選取器第一次出現時設定,調用public void setFileFilter(FileFilter filter)方法,而檔案選取器將會過濾所顯示的初始檔案集合。

例如,下面的源碼將會向檔案選取器添加兩個過濾器:

FileFilter jpegFilter =  new ExtensionFileFilter(null, new String[]{ "JPG", "JPEG"} );fileChooser.addChoosableFileFilter(jpegFilter);FileFilter gifFilter = new ExtensionFileFilter("gif", new String[]{ "gif"} );fileChooser.addChoosableFileFilter(gifFilter);

當沒有檔案過濾器與JFileChooser相關聯時,JFileChooser.getAcceptAllFileFilter()中的過濾器會被用來提供一個接受所有檔案的過濾器,而這也同樣適用於底層作業系統。

圖9-27顯示了Motif檔案選取器中的一個開啟的過濾器選擇組合框。

提示,在使用addChoosableFileFilter()方法添加過濾器之前使用setFileFilter()方法設定FileFilter會使得接受所有檔案的過濾器不可用。要恢複這個過濾器,調用setAcceptAllFileFilterUsed(true)方法。另外,我們可以使用resetChoosableFileFilters()方法重新設定過濾器列表。

內建的過濾器並不是FileFilter。他關注於隱藏檔案,例如Unix檔案系統上以句點(.)開始的檔案。預設情況下,隱藏檔案並不會顯示在JFileChooser中。要允許顯示隱藏檔案,我們必須將fileHidingEnabled屬性設定為false:

aFileChooser.setFileHidingEnabled(false);

提示,當建立javax.swing.filechooser.FileFilter子類時,我們也許會希望新類同時實現java.io.FileFilter介面。要實現這一目的,只需要簡單的將implements java.io.FileFilter添加到類定義。這樣做是因為javax.swing.filechooser類中的accept()方法的方法簽名與介面定義相匹配:public boolean accept(File file)。

選擇目錄而不選擇檔案

JFileChooser支援三種選擇模式:只選擇檔案,只選擇目錄,同時選擇檔案與目錄。fileSelectionMode屬性設定決定了選取器的模式。可用的設定是通過三個JFileChooser常量來指定的:FILES_ONLY, DIRECTORIES_ONLY以及FILES_AND_DIRECTORIES。初始時,檔案選取器位於JFileChooser.FILES_ONLY模式。要修改模式,只需要調用public void setFileSelectionMode(int newMode)。

除了fileSelectionMode屬性,我們可以使用唯讀fileSelectionEnabled與directorySelectionEnabled屬性來決定檔案選擇當前所支援的輸入類型。

添加附加面板

JFileChooser支援附加組件的添加。這個組件可以加強選取器的功能,包括預覽圖片或文檔,或是播放音頻檔案。要回應檔選擇變化,附加組件應將其自己作為PropertyChangeListener關聯到JFileChooser。當JFileChooser.SELECTED_FILE_CHANGED_PROPERTY屬性變化時,附加組件發生變化來反映檔案選擇。圖9-28顯示了一個圖片預覽附加組件的樣子。配置選取器的附加性就如同設定其他屬性一樣。

fileChooser.setAccessory(new LabelAccessory(fileChooser));

列表9-16顯示了顯示一個附加表徵圖的Image組件的源碼。被選中的影像檔變為JLabel組件的表徵圖。組件執行兩個縮放操作來保證映像的維度適合附加組件的尺寸。

package swingstudy.ch09;import java.awt.Dimension;import java.awt.Image;import java.beans.PropertyChangeEvent;import java.beans.PropertyChangeListener;import java.io.File;import javax.swing.ImageIcon;import javax.swing.JFileChooser;import javax.swing.JLabel;public class LabelAccessory extends JLabel implements PropertyChangeListener {private static final int PREFERRED_WIDTH = 125;private static final int PREFERRED_HEIGHT = 100;public LabelAccessory(JFileChooser chooser) {setVerticalAlignment(JLabel.CENTER);setHorizontalAlignment(JLabel.CENTER);chooser.addPropertyChangeListener(this);setPreferredSize(new Dimension(PREFERRED_WIDTH, PREFERRED_HEIGHT));}@Overridepublic void propertyChange(PropertyChangeEvent event) {String changeName = event.getPropertyName();if(changeName.equals(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY)){File file = (File)event.getNewValue();if(file != null) {ImageIcon icon = new ImageIcon(file.getPath());if(icon.getIconWidth() > PREFERRED_WIDTH) {icon = new ImageIcon(icon.getImage().getScaledInstance(PREFERRED_WIDTH, -1, Image.SCALE_DEFAULT));if(icon.getIconHeight() > PREFERRED_HEIGHT) {icon = new ImageIcon(icon.getImage().getScaledInstance(-1, PREFERRED_HEIGHT, Image.SCALE_DEFAULT));}}setIcon(icon);}}}}

使用FileSystemView類

FileSystemView類可以訪問平台相關的檔案系統資訊。java.io.File的JDK 1.1版本在這方面比較弱,FileSystemView的出現使得設計FileChooserUI對象更為容易。Swing的FileSystemView類以FileSystemView的包私人子類的方式提供了三個自訂的視圖。他們包括對Unix,Windows以及一個通用處理器的支援。

儘管並沒有必要來定義我們自己的FileSystemView,這個類提供了一些在JFileChooser環境之外十分有用的特性。要擷取特定於使用者運行時環境的視圖,可以調用public static FileSystemView getFileSystemView()方法。這個類的定義如下:

public abstract class FileSystemView {  // Constructors  public FileSystemView();  // Properties  // Properties  public File getDefaultDirectory();  public File getHomeDirectory();  public File[] getRoots();  // Class Methods  public static FileSystemView getFileSystemView();  // Other Methods  public File createFileObject(File directory, String filename);  public File createFileObject(String path);  protected File createFileSystemRoot(File file);  public abstract File createNewFolder(File containingDir) throws IOException;  public File getChild(File parent, String filename);  public File[] getFiles(File directory, boolean useFileHiding);  public File getParentDirectory(File file);  public String getSystemDisplayName(File file);  public Icon getSystemIcon(File file);  public String getSystemTypeDescription(File file);  public boolean isComputerNode(File file);  public boolean isDrive(File file);  public boolean isFileSystem(File file);  public boolean isFileSystemRoot(File file);  public boolean isFloppyDrive(File file);  public boolean isHiddenFile(File file);  public boolean isParent(File folder, File file);  public boolean isRoot(File file);  public Boolean isTraversable(File file);}

注意,isTraversable()方法返回Boolean,而不是boolean。

FileView類

我們將要探討的JFileChooser的最後一部分就是FileView地區,其中列出了所有的檔案名稱。每一個自訂的觀感類型都有其自己的FileView地區類。另外,某些預定義的觀感類型,例如Motif,是不可改變的。然而,至少在Metal與Windows檔案選取器,我們可以為不同的檔案類型自訂表徵圖,或是修改檔案的顯示名字。

FileView類的五個方法允許我們修改視圖中每一個File的名字,表徵圖或是描述(兩種形式)。另外,FileView實際上控制一個目錄是否是可遍曆的,從而使得我們可以以存取控制的弱層級進行編程。不可遍曆的目錄具有一個不同的預設表徵圖,因為這些目錄不能用於檔案選擇的瀏覽。

下面是抽象的FileView類的定義:

public abstract class FileView {  public FileView();  public String getDescription(File file);  public Icon getIcon(File file);  public String getName(File file);  public String getTypeDescription(File file);  public Boolean isTraversable(File file);}

注意,類似FileSystemView,isTraversable()方法返回Boolean,而不是boolean。

自訂FileView需要建立一個子類並重寫相應的方法。預設情況下,所有的方法返回null,表明我們並不希望為特定的方法定製自訂行為。

一旦我們定義了五個視圖,簡單的修改我們JFileChooser的fileView屬性:

fileChooser.setFileView(new JavaFileView());

圖9-29顯示了一個Metal JFileChooser在安裝了自訂的FileView之後的外觀樣式。

列表9-17中的JavaFileView類提供了一個FileView實現,這個實現自訂了與Java開發相關的檔案的顯示,特別是.java, .class, .jar以及.html或是.htm檔案。對於這些檔案類型中的每一種,一個特殊的表徵圖替換了預設表徵圖顯示在檔案名稱旁邊。另外,對於Java源檔案,顯示檔案長度。不幸的是,我們不可以修改FileView中的字型或顏色。

package swingstudy.ch09;import java.awt.Color;import java.io.File;import javax.swing.Icon;import javax.swing.filechooser.FileView;import swingstudy.ch04.DiamondIcon;public class JavaFileView extends FileView {Icon javaIcon =new DiamondIcon(Color.BLUE);Icon classIcon = new DiamondIcon(Color.GREEN);Icon htmlIcon = new DiamondIcon(Color.RED);Icon jarIcon = new DiamondIcon(Color.PINK);public String getName(File file) {String filename = file.getName();if(filename.endsWith(".java")) {String name = filename +" : "+file.length();return name;}return null;}public String getTypeDescription(File file) {String typeDescription = null;String filename = file.getName().toLowerCase();if(filename.endsWith(".java")) {typeDescription = "Java Source";}else if(filename.endsWith(".class")) {typeDescription = "Java Class File";}else if(filename.endsWith(".jar")) {typeDescription = "Java Archive";}else if(filename.endsWith(".html") || filename.endsWith(".htm")) {typeDescription = "Applet Loader";}return typeDescription;}public Icon getIcon(File file) {if(file.isDirectory()) {return null;}Icon icon = null;String filename = file.getName().toLowerCase();if(filename.endsWith(".java")) {icon = javaIcon;}else if(filename.endsWith(".class")) {icon = classIcon;}else if(filename.endsWith(".jar")) {icon = jarIcon;}else if(filename.endsWith(".html") || filename.endsWith(".htm")) {icon = htmlIcon;}return icon;}}

9.5.5 自訂JFileChooser觀感

每一個可安裝的Swing觀感提供了不同的JFileChooser外觀以及預設的UIResource值集合。圖9-30顯示了預先安裝的觀感集合,Motif,Windows,以及Ocean的JFileChooser外觀。

JFileChooser可用的UIResource相關屬性集合顯示在表9-11中。對於JFileChooser組件,有83個不同的屬性。幾乎所有的屬性都與按鈕標籤,熱鍵,表徵圖與工具提示文本相關。

 

除了80多個的JFileChooser資源以外,另外還有FileView的五個,顯示在表9-12中。

9.6 小結

在本章中,我們探討了Swing快顯視窗以及選取器類的細節。除了後動建立一個JDialog並且為其填充必要的部分外,Swing組件集合包含了對多個不同的快顯視窗與選取器類的支援。由JOptionPane開始,我們瞭解了如何建立資訊,問題,以及輸入快顯視窗。另外,我們探討了如何通過使用ProgressMonitor與ProgressMonitorInputStream類來監視需要長時間完成的任務的進程。

在瞭解了通用的彈出類之後,我們探討了特殊的Swing顏色以及檔案選取器類:JColorChooser與JFileChooser。通過這兩個類,我們可以提示使用者用於請求輸入以及以我們可以想像的更多的方式自訂顯示。

現在我們已經對預定義的快顯視窗有一定的瞭解了,現在是開始第10章LayoutManager類的討論的時候了。藉助於系統布局管理器,我們可以建立更好的使用者介面。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.