[英]Does Swing support Windows 7-style file choosers?
我剛剛根據Swing教程的JFileChooser
條目在正在編寫的小型桌面應用程序中添加了一個標准的“ 打開文件 ”對話框。 它正在生成一個如下所示的窗口:
但我希望有一個看起來像這樣的窗口:
換句話說,我希望文件選擇器具有Windows Vista / Windows 7的樣式,而不是Windows XP的樣式。 在Swing中有可能嗎? 如果是這樣,怎么做? (出於這個問題的目的,假定代碼將僅在Windows 7計算機上運行。)
似乎Java 6中的Swing不支持此功能。
當前,我找到打開此對話框的最簡單方法是通過SWT而不是Swing。 SWT的FileDialog( javadoc )彈出此對話框。 以下是對SWT的FileDialog代碼段的修改,以使用打開對話框而不是保存對話框。 我知道這並不是您想要的,但是您可以將其隔離到實用程序類,然后將swt.jar添加到您的類路徑中以實現此功能。
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
public class SWTFileOpenSnippet {
public static void main (String [] args) {
Display display = new Display ();
Shell shell = new Shell (display);
// Don't show the shell.
//shell.open ();
FileDialog dialog = new FileDialog (shell, SWT.OPEN | SWT.MULTI);
String [] filterNames = new String [] {"All Files (*)"};
String [] filterExtensions = new String [] {"*"};
String filterPath = "c:\\";
dialog.setFilterNames (filterNames);
dialog.setFilterExtensions (filterExtensions);
dialog.setFilterPath (filterPath);
dialog.open();
System.out.println ("Selected files: ");
String[] selectedFileNames = dialog.getFileNames();
for(String fileName : selectedFileNames) {
System.out.println(" " + fileName);
}
shell.close();
while (!shell.isDisposed ()) {
if (!display.readAndDispatch ()) display.sleep ();
}
display.dispose ();
}
}
甚至本機Windows應用程序也可以在Windows 7上顯示這種類型的對話框。這通常由OPENFILENAME
結構中的標志控制,其大小通過調用WinAPI函數GetOpenFileName
傳遞。 Swing(Java)使用鈎子從“打開文件”對話框中獲取事件; 這些事件在Windows XP和Windows 7版本之間傳遞的方式有所不同。
因此,答案是您無法控制Swing中FileChooser的外觀。 但是,當Java獲得這種新外觀的支持時,您將自動獲得新樣式。
另一個選擇是使用SWT,如該答案中所建議。 另外,您可以使用JNA調用Windows API或編寫本機方法來執行此操作。
Java 8可能最終會為此提供解決方案,但不幸的是(對於Swing應用程序),它僅作為JavaFX類FileChooser出現 :
我從這里測試了此代碼,它的確彈出了一個現代對話框(此處為Windows 7):
FileChooser fileChooser = new FileChooser();
//Set extension filter
FileChooser.ExtensionFilter extFilterJPG = new FileChooser.ExtensionFilter("JPG files (*.jpg)", "*.JPG");
FileChooser.ExtensionFilter extFilterPNG = new FileChooser.ExtensionFilter("PNG files (*.png)", "*.PNG");
fileChooser.getExtensionFilters().addAll(extFilterJPG, extFilterPNG);
//Show open file dialog
File file = fileChooser.showOpenDialog(null);
這種集成到Swing應用程序,你必須在通過JavaFX的線程中運行它Platform.runLater
(如看到這里 )。
請注意,這將需要您初始化javafx線程(在示例中,這是在場景初始化時在new JFXPanel()
)。
綜上所述,swing應用程序中的准備運行的解決方案如下所示:
new JFXPanel(); // used for initializing javafx thread (ideally called once)
Platform.runLater(() -> {
FileChooser fileChooser = new FileChooser();
//Set extension filter
FileChooser.ExtensionFilter extFilterJPG = new FileChooser.ExtensionFilter("JPG files (*.jpg)", "*.JPG");
FileChooser.ExtensionFilter extFilterPNG = new FileChooser.ExtensionFilter("PNG files (*.png)", "*.PNG");
fileChooser.getExtensionFilters().addAll(extFilterJPG, extFilterPNG);
//Show open file dialog
File file = fileChooser.showOpenDialog(null);
});
有點hack,但功能比Swing版本要少,但是您是否考慮過使用java.awt.FileDialog
? 它不僅看起來像Windows文件選擇器,而且實際上應該是一個。
我不相信Swing會涵蓋所有內容,如果沒有,您可能需要查看SWT之類的東西,它會利用實際的本機組件,或者做一個自定義UI元素,例如《骯臟的富客戶》一書。
很好的問題+1,看起來就像他們“忘記”在Java6中實現Win7(defaultLookAndFeel)的實現一樣,但是對於WinXP來說卻是正確的,我也希望為此必須存在一些方法/屬性
無論如何,您可以使用此代碼進行嘗試,
import java.io.File;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
class ChooserFilterTest {
public static void main(String[] args) {
Runnable r = new Runnable() {
@Override
public void run() {
String[] properties = {"os.name", "java.version", "java.vm.version", "java.vendor"};
for (String property : properties) {
System.out.println(property + ": " + System.getProperty(property));
}
JFileChooser jfc = new JFileChooser();
jfc.showOpenDialog(null);
jfc.addChoosableFileFilter(new FileFilter() {
@Override
public boolean accept(File f) {
return f.isDirectory() || f.getName().toLowerCase().endsWith(".obj");
}
@Override
public String getDescription() {
return "Wavefront OBJ (*.obj)";
}
@Override
public String toString() {
return getDescription();
}
});
int result = JOptionPane.showConfirmDialog(null, "Description was 'All Files'?");
System.out.println("Displayed description (Metal): " + (result == JOptionPane.YES_OPTION));
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
SwingUtilities.updateComponentTreeUI(jfc);
} catch (Exception e) {
e.printStackTrace();
}
jfc.showOpenDialog(null);
result = JOptionPane.showConfirmDialog(null, "Description was 'All Files'?");
System.out.println("Displayed description (System): " + (result == JOptionPane.YES_OPTION));
}
};
SwingUtilities.invokeLater(r);
}
private ChooserFilterTest() {
}
}
但是無法使此工作適用於目錄!! DirectoryDialog使我們回到樹樣式目錄選擇器,該選擇器與問題中列出的選擇器相同。 問題是它不允許我選擇/選擇/打開隱藏文件夾。 它也不允許導航到AppData,ProgramData等文件夾。
Windows 7樣式文件對話框(swt)確實允許導航到這些文件夾,但隨后又不允許選擇文件夾:(
更新要查看隱藏的文件夾,請使用JFileChooser並設置setFileHidingEnabled(false)
。 唯一的要求是,用戶需要在工具欄中選擇“顯示隱藏的文件,文件夾和驅動器”
文件夾選項->查看
Windows資源管理器
您不會獲得地址欄的靈活性,但是如果您正在尋找Java中的非樹狀文件選擇器,那么它也可以瀏覽/查看隱藏的文件/文件夾-那么就足夠了
約翰·麥卡錫的答案似乎是最好的。 這里有一些建議。
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.graphics.Image;
在左上角添加圖像。 使用“ getResourceAsStream”很重要,在導出為Runnable jar后,您會注意到:
Display display = new Display();
Shell shell = new Shell(display);
InputStream inputImage = getClass().getResourceAsStream("/app/launcher.png");
if (inputImage != null) {
shell.setImage(new Image(display, inputImage));
}
用戶的主目錄:
String filterPath = System.getProperty("user.home");
獲取絕對路徑名,而不是依賴於過濾器的路徑名,這在其他驅動器上是錯誤的。
String absolutePath = dialog.open();
由於Swing模擬了各種L&F,因此我認為最好的選擇是將JRE升級到最新版本,並希望JFileChooser UI已更新。
JFileChooser在使用Swing時總是有些奇怪,也有點慢。
嘗試使用SWT的filechooser或將C調用包裝在JNA中。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.