1. 程式人生 > >JavaFX UI控制元件教程(二十七)之File Chooser

JavaFX UI控制元件教程(二十七)之File Chooser

翻譯自  File Chooser

本章介紹如何使用FileChooser該類使使用者能夠導航檔案系統。本章提供的示例說明了如何開啟一個或多個檔案,配置檔案選擇器對話方塊視窗以及儲存應用程式內容。

與其他使用者介面元件類不同,FileChooser該類不屬於該javafx.scene.controls包。但是,這個類值得在JavaFX UI Controls教程中提及,因為它支援典型的GUI應用程式功能之一:檔案系統導航。

FileChooser類位於javafx.stage包與其他的基本根圖形元素,例如沿著StageWindow,和Popup圖26-1中的“檢視圖片”視窗是Windows中檔案選擇器對話方塊的示例。

圖26-1檔案選擇器視窗示例

 

開啟檔案

檔案選擇器可用於呼叫開啟的對話方塊視窗,用於選擇單個檔案或多個檔案,以及啟用檔案儲存對話方塊視窗。要顯示檔案選擇器,通常使用FileChooser該類。例26-1提供了在應用程式中啟用檔案選擇器的最簡單方法。

示例26-1顯示檔案選擇器

FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Open Resource File");
fileChooser.showOpenDialog(stage);

示例26-1中

的程式碼新增到JavaFX應用程式後,應用程式啟動時會立即顯示檔案選擇器對話方塊視窗,如圖26-2所示。

圖26-2簡單檔案選擇器

注意:

圖26-2顯示了Windows中的檔案選擇器。在其他支援此功能的作業系統中開啟檔案選擇器時,您將收到備用視窗。圖26-3圖26-4顯示了Linux和Mac OS中檔案選擇器視窗的示例。


圖26-3 Linux中的檔案選擇器視窗

圖26-4 Mac OS中的“檔案選擇器”視窗

Description of Figure 26-4 follows

雖然在前面的示例中,檔案選擇器在應用程式啟動時自動出現,但更典型的方法是通過選擇相應的選單項或單擊專用按鈕來呼叫檔案選擇器。在本教程中,您將建立一個應用程式,使使用者可以單擊按鈕並開啟位於檔案系統中的一個或多個圖片。例26-2

顯示了實現此任務的FileChooserSample應用程式的程式碼。

示例26-2開啟單個和多個選擇的檔案選擇器

import java.awt.Desktop;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
 
public final class FileChooserSample extends Application {
 
    private Desktop desktop = Desktop.getDesktop();
 
    @Override
    public void start(final Stage stage) {
        stage.setTitle("File Chooser Sample");
 
        final FileChooser fileChooser = new FileChooser();
 
        final Button openButton = new Button("Open a Picture...");
        final Button openMultipleButton = new Button("Open Pictures...");
 
        openButton.setOnAction(
            new EventHandler<ActionEvent>() {
                @Override
                public void handle(final ActionEvent e) {
                    File file = fileChooser.showOpenDialog(stage);
                    if (file != null) {
                        openFile(file);
                    }
                }
            });
 
        openMultipleButton.setOnAction(
            new EventHandler<ActionEvent>() {
                @Override
                public void handle(final ActionEvent e) {
                    List<File> list =
                        fileChooser.showOpenMultipleDialog(stage);
                    if (list != null) {
                        for (File file : list) {
                            openFile(file);
                        }
                    }
                }
            });
 
 
        final GridPane inputGridPane = new GridPane();
 
        GridPane.setConstraints(openButton, 0, 0);
        GridPane.setConstraints(openMultipleButton, 1, 0);
        inputGridPane.setHgap(6);
        inputGridPane.setVgap(6);
        inputGridPane.getChildren().addAll(openButton, openMultipleButton);
 
        final Pane rootGroup = new VBox(12);
        rootGroup.getChildren().addAll(inputGridPane);
        rootGroup.setPadding(new Insets(12, 12, 12, 12));
 
        stage.setScene(new Scene(rootGroup));
        stage.show();
    }
 
    public static void main(String[] args) {
        Application.launch(args);
    }
 
    private void openFile(File file) {
        try {
            desktop.open(file);
        } catch (IOException ex) {
            Logger.getLogger(
                FileChooserSample.class.getName()).log(
                    Level.SEVERE, null, ex
                );
        }
    }
}

示例26-2中,“開啟圖片”按鈕使使用者可以開啟檔案選擇器進行單個選擇,“開啟圖片”按鈕使使用者可以開啟檔案選擇器進行多項選擇。setOnAction這些按鈕的方法幾乎相同。唯一的區別在於用於呼叫a的方法FileChooser

  • showOpenDialog方法顯示一個新的檔案開啟對話方塊,其中可以選擇一個檔案。該方法返回指定使用者選擇的檔案的值,或者null是否未進行選擇。

  • showOpenMultipleDialog方法顯示了一個新的檔案開啟對話方塊,其中可以選擇多個檔案。該方法返回指定使用者選擇的檔案列表的值,或者null是否未進行選擇。無法修改返回的列表,並UnsupportedOperationException在每次修改嘗試時丟擲。

兩種方法都不會返回結果,直到顯示的開啟對話方塊視窗被取消(換句話說,直到使用者提交或取消選擇)。

編譯並執行FileChooserSample應用程式時,它會生成如圖26-5所示的視窗。

圖26-5帶有兩個按鈕的FileChooserSample

單擊其中一個按鈕時,將出現如圖26-6所示的對話方塊視窗。開啟的檔案選擇器對話方塊視窗顯示作業系統的預設位置。

圖26-6預設檔案選擇器視窗

FileChooserSample應用程式的使用者可以導航到包含圖片的目錄並選擇圖片。選擇檔案後,將使用關聯的應用程式開啟該檔案。示例程式碼通過使用實現此open的方法java.awt.Desktop類:desktop.open(file);

注意:

Desktop該類的可用性取決於平臺。有關該類的更多資訊,請參閱API文件Desktop。您還可以使用該isDesktopSupported()方法檢查系統是否支援它。

通過將檔案選擇器目錄設定為包含圖片的特定目錄,可以改善此應用程式的使用者體驗。

 

配置檔案選擇器

您可以通過設定物件的屬性initialDirectorytitle屬性來配置檔案選擇器對話方塊視窗FileChooser例26-3顯示瞭如何指定初始目錄以及預覽和開啟圖片的合適標題。

示例26-3設定初始目錄和視窗標題

import java.awt.Desktop;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
 
public final class FileChooserSample extends Application {
 
    private Desktop desktop = Desktop.getDesktop();
 
    @Override
    public void start(final Stage stage) {
        stage.setTitle("File Chooser Sample");
 
        final FileChooser fileChooser = new FileChooser();
 
        final Button openButton = new Button("Open a Picture...");
        final Button openMultipleButton = new Button("Open Pictures...");
 
        openButton.setOnAction(
            new EventHandler<ActionEvent>() {
                @Override
                public void handle(final ActionEvent e) {
                    configureFileChooser(fileChooser);
                    File file = fileChooser.showOpenDialog(stage);
                    if (file != null) {
                        openFile(file);
                    }
                }
            });
 
        openMultipleButton.setOnAction(
            new EventHandler<ActionEvent>() {
                @Override
                public void handle(final ActionEvent e) {
                    configureFileChooser(fileChooser);
                    List<File> list = 
                        fileChooser.showOpenMultipleDialog(stage);
                    if (list != null) {
                        for (File file : list) {
                            openFile(file);
                        }
                    }
                }
            });
 
        final GridPane inputGridPane = new GridPane();
 
        GridPane.setConstraints(openButton, 0, 0);
        GridPane.setConstraints(openMultipleButton, 1, 0);
        inputGridPane.setHgap(6);
        inputGridPane.setVgap(6);
        inputGridPane.getChildren().addAll(openButton, openMultipleButton);
        
        final Pane rootGroup = new VBox(12);
        rootGroup.getChildren().addAll(inputGridPane);
        rootGroup.setPadding(new Insets(12, 12, 12, 12));
 
        stage.setScene(new Scene(rootGroup));
        stage.show();
    }
 
    public static void main(String[] args) {
        Application.launch(args);
    }
         
        private static void configureFileChooser(final FileChooser fileChooser){                           
        fileChooser.setTitle("View Pictures");
        fileChooser.setInitialDirectory(
            new File(System.getProperty("user.home"))
        ); 
    }
            
 
    private void openFile(File file) {
        try {
            desktop.open(file);
        } catch (IOException ex) {
            Logger.getLogger(
                FileChooserSample.class.getName()).log(
                    Level.SEVERE, null, ex
                );
        }
    }
}

configureFileChooser方法使用“我的圖片”子目錄設定“檢視圖片”標題和使用者主目錄的路徑。編譯並執行FileChooserSample並單擊其中一個按鈕時,將出現如圖26-7所示的檔案選擇器。

圖26-7開啟圖片庫

您還可以讓使用者使用DirectoryChooser該類指定目標目錄。在例26-4中顯示的程式碼片段中,單擊它會browseButton呼叫該directoryChooser.showDialog方法。

示例26-4使用DirectoryChooser類

final Button browseButton = new Button("...");
browseButton.setOnAction(
    new EventHandler<ActionEvent>() {
        @Override
        public void handle(final ActionEvent e) {
            final DirectoryChooser directoryChooser =
                new DirectoryChooser();
            final File selectedDirectory =
                    directoryChooser.showDialog(stage);
            if (selectedDirectory != null) {
                selectedDirectory.getAbsolutePath();
            }
        }
    }
);

執行選擇後,您可以按如下方式將相應的值分配給檔案選擇器:fileChooser.setInitialDirectory(selectedDirectory);

 

設定擴充套件過濾器

作為下一個配置選項,您可以設定擴充套件過濾器以確定在檔案選擇器中開啟哪些檔案,如例26-5所示。

示例26-5設定影象型別過濾器

import java.awt.Desktop;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
 
public final class FileChooserSample extends Application {
 
    private Desktop desktop = Desktop.getDesktop();
 
    @Override
    public void start(final Stage stage) {
        stage.setTitle("File Chooser Sample");
 
        final FileChooser fileChooser = new FileChooser();
        final Button openButton = new Button("Open a Picture...");
        final Button openMultipleButton = new Button("Open Pictures...");     
      
        openButton.setOnAction(
            new EventHandler<ActionEvent>() {
                @Override
                public void handle(final ActionEvent e) {
                    configureFileChooser(fileChooser);
                    File file = fileChooser.showOpenDialog(stage);
                    if (file != null) {
                        openFile(file);
                    }
                }
            });
 
        openMultipleButton.setOnAction(
            new EventHandler<ActionEvent>() {
                @Override
                public void handle(final ActionEvent e) {
                    configureFileChooser(fileChooser);                               
                    List<File> list = 
                        fileChooser.showOpenMultipleDialog(stage);
                    if (list != null) {
                        for (File file : list) {
                            openFile(file);
                        }
                    }
                }
            });
 
 
        final GridPane inputGridPane = new GridPane();
 
        GridPane.setConstraints(openButton, 0, 1);
        GridPane.setConstraints(openMultipleButton, 1, 1);
        inputGridPane.setHgap(6);
        inputGridPane.setVgap(6);
        inputGridPane.getChildren().addAll(openButton, openMultipleButton);
        
        final Pane rootGroup = new VBox(12);
        rootGroup.getChildren().addAll(inputGridPane);
        rootGroup.setPadding(new Insets(12, 12, 12, 12));
 
        stage.setScene(new Scene(rootGroup));
        stage.show();
    }
 
    public static void main(String[] args) {
        Application.launch(args);
    }
 
    private static void configureFileChooser(
        final FileChooser fileChooser) {      
            fileChooser.setTitle("View Pictures");
            fileChooser.setInitialDirectory(
                new File(System.getProperty("user.home"))
            );                 
            fileChooser.getExtensionFilters().addAll(
                new FileChooser.ExtensionFilter("All Images", "*.*"),
                new FileChooser.ExtensionFilter("JPG", "*.jpg"),
                new FileChooser.ExtensionFilter("PNG", "*.png")
            );
    }
 
    private void openFile(File file) {
        try {
            desktop.open(file);
        } catch (IOException ex) {
            Logger.getLogger(FileChooserSample.class.getName()).log(
                Level.SEVERE, null, ex
            );
        }
    }
}

示例26-5中,您可以使用FileChooser.ExtensionFilter以定義檔案選擇的以下選項來設定擴充套件過濾器:所有影象,JPG和PNG。

編譯時,執行例26-5中的FileChooserSample程式碼,然後單擊其中一個按鈕,副檔名篩選器將出現在檔案選擇器視窗中。如果使用者選擇JPG,則檔案選擇器僅顯示JPG型別的圖片。圖26-8捕獲了My Pictures目錄中選擇JPG影象的時刻。

圖26-8在檔案選擇器中過濾JPG檔案

 

儲存檔案

除了開啟和過濾檔案之外,FileChooserAPI還提供了一種功能,允許使用者為應用程式儲存的檔案指定檔名(及其在檔案系統中的位置)。該類的showSaveDialog方法FileChooser開啟一個儲存對話方塊視窗。與其他show dialog方法一樣,該showSaveDialog方法返回使用者選擇的檔案,或者null如果沒有執行選擇。

例26-6中顯示的程式碼片段是Menu示例的補充。它還實現了上下文選單中的另一項,用於將顯示的影象儲存在檔案系統中。

示例26-6使用FileChooser類儲存影象

MenuItem cmItem2 = new MenuItem("Save Image");
    cmItem2.setOnAction(new EventHandler<ActionEvent>() {
        public void handle(ActionEvent e) {
            FileChooser fileChooser = new FileChooser();
            fileChooser.setTitle("Save Image");
            System.out.println(pic.getId());
            File file = fileChooser.showSaveDialog(stage);
            if (file != null) {
                try {
                    ImageIO.write(SwingFXUtils.fromFXImage(pic.getImage(),
                        null), "png", file);
                } catch (IOException ex) {
                    System.out.println(ex.getMessage());
                }
            }
        }
    }
);

Example 26-6新增到MenuSample應用程式(在Application Files中查詢原始碼),編譯並執行它時,啟用Save Image選單項,如圖26-9所示。

圖26-9儲存影象

使用者選擇“儲存影象”項後,將出現如圖26-10所示的“儲存影象”視窗。

圖26-10“儲存影象”視窗

“儲存影象”視窗對應於儲存對話方塊視窗的典型使用者體驗:使用者需要選擇目標目錄,鍵入儲存檔案的名稱,然後單擊“儲存”。

 

相關的API文件