2016-04-28 20 views
5

Trình điều khiển chế độ xem của tôi có một cá thể FileChooser được sử dụng cho cả tệp mở và lưu.Trình tạo tệp JavaFX có thể "nhớ" thư mục cuối cùng được mở không?

Mỗi lần tôi gọi showOpenDialog() hoặc showSaveDialog() từ trường hợp đó, tôi mong đợi hộp thoại kết quả nằm trong cùng một thư mục khi tôi để nó lần cuối cùng tôi gọi một trong số chúng.

Thay vào đó, mỗi lần tôi gọi một trong các phương pháp đó, hộp thoại sẽ mở trong thư mục chính của người dùng.

Làm cách nào để làm cho "thư mục hiện tại" của các hộp thoại tồn tại trên các lời gọi khác nhau?


Ví dụ về hành vi hiện tại:

import java.io.File; 
import javafx.application.Application; 
import javafx.event.ActionEvent; 
import javafx.geometry.Insets; 
import javafx.geometry.Pos; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.control.Label; 
import javafx.scene.layout.VBox; 
import javafx.stage.FileChooser; 
import javafx.stage.Stage; 

/** 
* Demonstrates the use of an open dialog. 
* 
* @author N99x 
*/ 
public class FileChooserTest extends Application { 

    private final FileChooser open = new FileChooser(); 
    private File lastOpened = null; 

    @Override 
    public void start(Stage primaryStage) { 
     Label lbl = new Label("File Opened: <null>"); 
     lbl.setPadding(new Insets(8)); 
     Button btn = new Button(); 
     btn.setPadding(new Insets(8)); 
     btn.setText("Open"); 
     btn.setOnAction((ActionEvent event) -> { 
      open.setInitialDirectory(lastOpened); 
      File selected = open.showOpenDialog(primaryStage); 
      if (selected == null) { 
       lbl.setText("File Opened: <null>"); 
       // lastOpened = ??; 
      } else { 
       lbl.setText("File Opened: " + selected.getAbsolutePath()); 
       lastOpened = selected.getParentFile(); 
      } 
     }); 

     VBox root = new VBox(lbl, btn); 
     root.setPadding(new Insets(8)); 
     root.setAlignment(Pos.TOP_CENTER); 
     Scene scene = new Scene(root, 300, 300); 

     primaryStage.setTitle("FileChooser Testing!"); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

    /** 
    * @param args the command line arguments 
    */ 
    public static void main(String[] args) { 
     launch(args); 
    } 

} 

tôi quản lý để có được xung quanh cho một phần của vấn đề bằng cách lưu trữ các giá trị mở ra, nhưng điều này không hoạt động nếu hộp thoại đóng hoặc bị hủy.

Trả lời

4

Làm cách nào để làm cho "thư mục hiện tại" của các hộp thoại vẫn tồn tại trên các lời gọi khác nhau?

Bạn có thể thay đổi cách tiếp cận Singleton Pattern cho điều này

Nhờ đó mà bạn sẽ chỉ sử dụng một FileChooser và theo dõi/kiểm soát thư mục ban đầu có, nhưng không trực tiếp phơi bày các ví dụ để thay đổi bên ngoài của lớp


Ví dụ:

public class RetentionFileChooser { 
    private static FileChooser instance = null; 
    private static SimpleObjectProperty<File> lastKnownDirectoryProperty = new SimpleObjectProperty<>(); 

    private RetentionFileChooser(){ } 

    private static FileChooser getInstance(){ 
     if(instance == null) { 
      instance = new FileChooser(); 
      instance.initialDirectoryProperty().bindBidirectional(lastKnownDirectoryProperty); 
      //Set the FileExtensions you want to allow 
      instance.getExtensionFilters().setAll(new ExtensionFilter("png files (*.png)", "*.png")); 
     } 
     return instance; 
    } 

    public static File showOpenDialog(){ 
     return showOpenDialog(null); 
    } 

    public static File showOpenDialog(Window ownerWindow){ 
     File chosenFile = getInstance().showOpenDialog(ownerWindow); 
     if(chosenFile != null){ 
      //Set the property to the directory of the chosenFile so the fileChooser will open here next 
      lastKnownDirectoryProperty.setValue(chosenFile.getParentFile()); 
     } 
     return chosenFile; 
    } 

    public static File showSaveDialog(){ 
     return showSaveDialog(null); 
    } 

    public static File showSaveDialog(Window ownerWindow){ 
     File chosenFile = getInstance().showSaveDialog(ownerWindow); 
     if(chosenFile != null){ 
      //Set the property to the directory of the chosenFile so the fileChooser will open here next 
      lastKnownDirectoryProperty.setValue(chosenFile.getParentFile()); 
     } 
     return chosenFile; 
    } 
} 

Điều này sẽ thiết lập các thư mục ban đầu của FileChooser là thư mục của tập tin người dùng mở cuối cùng/lưu khi nó là tái sử dụng

sử dụng Ví dụ:

File chosenFile = RetentionFileChooser.showOpenDialog(); 

Tuy nhiên có một hạn chế ở đây:

//Set the FileExtensions you want to allow 
instance.getExtensionFilters().setAll(new ExtensionFilter("png files (*.png)", "*.png")); 

Như mà không cung cấp bất kỳ ExtensionFilter 's các FileChooser trở nên ít người dùng thân thiện, đòi hỏi người sử dụng bằng tay appe loại tệp, nhưng việc cung cấp các bộ lọc khi tạo cá thể không có cách nào cập nhật chúng sẽ giới hạn nó với cùng một bộ lọc đó

Một cách để cải thiện điều này là phơi bày các bộ lọc tùy chọn trong RetentionFileChooser có thể được cung cấp bằng cách sử dụng varargs. bạn có thể chọn khi nào nên sửa đổi các bộ lọc như bạn hiển thị các hộp thoại

Ví dụ, xây dựng trên theo thời gian: sử dụng

public class RetentionFileChooser { 
    public enum FilterMode { 
     //Setup supported filters 
     PNG_FILES("png files (*.png)", "*.png"), 
     TXT_FILES("txt files (*.txt)", "*.txt"); 

     private ExtensionFilter extensionFilter; 

     FilterMode(String extensionDisplayName, String... extensions){ 
      extensionFilter = new ExtensionFilter(extensionDisplayName, extensions); 
     } 

     public ExtensionFilter getExtensionFilter(){ 
      return extensionFilter; 
     } 
    } 

    private static FileChooser instance = null; 
    private static SimpleObjectProperty<File> lastKnownDirectoryProperty = new SimpleObjectProperty<>(); 

    private RetentionFileChooser(){ } 

    private static FileChooser getInstance(FilterMode... filterModes){ 
     if(instance == null) { 
      instance = new FileChooser(); 
      instance.initialDirectoryProperty().bindBidirectional(lastKnownDirectoryProperty); 
     } 
     //Set the filters to those provided 
     //You could add check's to ensure that a default filter is included, adding it if need be 
     instance.getExtensionFilters().setAll(
       Arrays.stream(filterModes) 
         .map(FilterMode::getExtensionFilter) 
         .collect(Collectors.toList())); 
     return instance; 
    } 

    public static File showOpenDialog(FilterMode... filterModes){ 
     return showOpenDialog(null, filterModes); 
    } 

    public static File showOpenDialog(Window ownerWindow, FilterMode...filterModes){ 
     File chosenFile = getInstance(filterModes).showOpenDialog(ownerWindow); 
     if(chosenFile != null){ 
      lastKnownDirectoryProperty.setValue(chosenFile.getParentFile()); 
     } 
     return chosenFile; 
    } 

    public static File showSaveDialog(FilterMode... filterModes){ 
     return showSaveDialog(null, filterModes); 
    } 

    public static File showSaveDialog(Window ownerWindow, FilterMode... filterModes){ 
     File chosenFile = getInstance(filterModes).showSaveDialog(ownerWindow); 
     if(chosenFile != null){ 
      lastKnownDirectoryProperty.setValue(chosenFile.getParentFile()); 
     } 
     return chosenFile; 
    } 
} 

Ví dụ:

//Note the previous example still holds 
File chosenFile = RetentionFileChooser.showOpenDialog(); 
File file = RetentionFileChooser.showSaveDialog(FilterMode.PNG_FILES); 

nhưng điều này không hoạt động nếu hộp thoại bị đóng hoặc hủy.

Không may hiển thị thông tin về thư mục nào trước khi đóng/chấm dứt. Nếu bạn loại bỏ lớp và theo dõi, cuối cùng nó sẽ truy cập cuộc gọi native.Vì vậy, ngay cả khi FileChooser không final cho phép nó được subclassed, nó chỉ là như khó có khả năng có thể nhận được thông tin này

duy nhất đạt được cách tiếp cận trên đây cung cấp khoảng này là nó không làm thay đổi thư mục ban đầu nếu kịch bản này được đánh


Nếu bạn quan tâm, có một số câu trả lời rất tốt trên các từ khóa native trong câu hỏi này và những liên kết:

+0

Một giải pháp đơn giản cho đề xuất mở rộng tệp sẽ là đặt lại tiện ích mở rộng tệp mỗi khi bạn gọi. IE: 'fileChooser.getExtensionFilters(). Clear(); fileChooser.getExtensionFilters(). Thêm (FileChooser.ExtensionFilter mới ("PNG", "* .png")); ' –

1
private static String lastVisitedDirectory=System.getProperty("user.home"); 

FileChooser fileChooser = new FileChooser(); 
fileChooser.setTitle("View Pictures"); 
fileChooser.setInitialDirectory(new File(lastVisitedDirectory)); 
fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("--")); 

List<File> files = fileChooser.showOpenMultipleDialog(----); 


lastVisitedDir=(files!=null && files.size()>=1)?files.get(0).getParent():System.getProperty("user.home"); 
Các vấn đề liên quan