ama*_*ion 11 java swing jfilechooser
我正在用java编写一个图编辑器.此应用程序可以选择导出到各种标准图像格式,如.jpg,.png等.当用户单击文件 - >导出时,您将获得JFileChooser
其中包含FileFilter
s 的数量.jpg
,.png
等等.
现在这是我的问题:
有没有办法将默认值的扩展调整到所选的文件过滤器?例如,如果文档名为"lolcat",则在选择png过滤器时,默认选项应为"lolcat.png",当用户选择jpg文件过滤器时,默认值应自动更改为"lolcat.jpg".
这可能吗?我该怎么做?
编辑:基于下面的答案,我写了一些代码.但它还没有完全奏效.我添加了一个propertyChangeListener
到FILE_FILTER_CHANGED_PROPERTY
,但似乎在这个方法getSelectedFile()
返回null.这是代码.
package nl.helixsoft;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.filechooser.FileFilter;
public class JFileChooserTest {
public class SimpleFileFilter extends FileFilter {
private String desc;
private List<String> extensions;
private boolean showDirectories;
/**
* @param name example: "Data files"
* @param glob example: "*.txt|*.csv"
*/
public SimpleFileFilter (String name, String globs) {
extensions = new ArrayList<String>();
for (String glob : globs.split("\\|")) {
if (!glob.startsWith("*."))
throw new IllegalArgumentException("expected list of globs like \"*.txt|*.csv\"");
// cut off "*"
// store only lower case (make comparison case insensitive)
extensions.add (glob.substring(1).toLowerCase());
}
desc = name + " (" + globs + ")";
}
public SimpleFileFilter(String name, String globs, boolean showDirectories) {
this(name, globs);
this.showDirectories = showDirectories;
}
@Override
public boolean accept(File file) {
if(showDirectories && file.isDirectory()) {
return true;
}
String fileName = file.toString().toLowerCase();
for (String extension : extensions) {
if (fileName.endsWith (extension)) {
return true;
}
}
return false;
}
@Override
public String getDescription() {
return desc;
}
/**
* @return includes '.'
*/
public String getFirstExtension() {
return extensions.get(0);
}
}
void export() {
String documentTitle = "lolcat";
final JFileChooser jfc = new JFileChooser();
jfc.setDialogTitle("Export");
jfc.setDialogType(JFileChooser.SAVE_DIALOG);
jfc.setSelectedFile(new File (documentTitle));
jfc.addChoosableFileFilter(new SimpleFileFilter("JPEG", "*.jpg"));
jfc.addChoosableFileFilter(new SimpleFileFilter("PNG", "*.png"));
jfc.addPropertyChangeListener(JFileChooser.FILE_FILTER_CHANGED_PROPERTY, new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent arg0) {
System.out.println ("Property changed");
String extold = null;
String extnew = null;
if (arg0.getOldValue() == null || !(arg0.getOldValue() instanceof SimpleFileFilter)) return;
if (arg0.getNewValue() == null || !(arg0.getNewValue() instanceof SimpleFileFilter)) return;
SimpleFileFilter oldValue = ((SimpleFileFilter)arg0.getOldValue());
SimpleFileFilter newValue = ((SimpleFileFilter)arg0.getNewValue());
extold = oldValue.getFirstExtension();
extnew = newValue.getFirstExtension();
String filename = "" + jfc.getSelectedFile();
System.out.println ("file: " + filename + " old: " + extold + ", new: " + extnew);
if (filename.endsWith(extold)) {
filename.replace(extold, extnew);
} else {
filename += extnew;
}
jfc.setSelectedFile(new File (filename));
}
});
jfc.showDialog(frame, "export");
}
JFrame frame;
void run() {
frame = new JFrame();
JButton btn = new JButton ("export");
frame.add (btn);
btn.addActionListener (new ActionListener() {
public void actionPerformed(ActionEvent ae) {
export();
}
});
frame.setSize (300, 300);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFileChooserTest x = new JFileChooserTest();
x.run();
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
Ama*_*a S 11
看起来您可以监听属性JFileChooser
的更改FILE_FILTER_CHANGED_PROPERTY
,然后使用适当更改所选文件的扩展名setSelectedFile()
.
编辑:你是对的,这个解决方案不起作用.事实证明,当文件过滤器更改时,如果所选文件的文件类型与新过滤器不匹配,则会删除该文件.这就是为什么你在null
尝试时得到的原因getSelectedFile()
.
你考虑过稍后添加扩展吗?当我写一篇文章时JFileChooser
,我通常会在用户选择要使用的文件后添加扩展名,然后点击"保存":
if (result == JFileChooser.APPROVE_OPTION)
{
File file = fileChooser.getSelectedFile();
String path = file.getAbsolutePath();
String extension = getExtensionForFilter(fileChooser.getFileFilter());
if(!path.endsWith(extension))
{
file = new File(path + extension);
}
}
Run Code Online (Sandbox Code Playgroud)
fileChooser.addPropertyChangeListener(JFileChooser.FILE_FILTER_CHANGED_PROPERTY, new PropertyChangeListener()
{
public void propertyChange(PropertyChangeEvent evt)
{
FileFilter filter = (FileFilter)evt.getNewValue();
String extension = getExtensionForFilter(filter); //write this method or some equivalent
File selectedFile = fileChooser.getSelectedFile();
String path = selectedFile.getAbsolutePath();
path.substring(0, path.lastIndexOf("."));
fileChooser.setSelectedFile(new File(path + extension));
}
});
Run Code Online (Sandbox Code Playgroud)
小智 6
在附加后缀之前,您还可以在 SELECTED_FILE_CHANGED_PROPERTY 上使用 PropertyChangeListener。当根据新过滤器检查所选文件(随后设置为空)时,实际上会在FILE_FILTER_CHANGED_PROPERTY 事件之前触发 SELECTED_FILE_CHANGED_PROPERTY 事件。
如果 evt.getOldValue() != null 且 evt.getNewValue() == null,则您知道 JFileChooser 已破坏您的文件。然后,您可以获取旧文件的名称(如上所述使用 ((File)evt.getOldValue()).getName() ),使用标准字符串解析函数提取扩展名,并将其存储到类中的命名成员变量中。
这样,当 FILE_FILTER_CHANGED 事件被触发时(立即触发,据我所知),您可以从指定的成员变量中提取隐藏的根名称,应用新文件过滤器类型的扩展名,并设置 JFileChooser 的选定文件因此。
小智 5
这个怎么样:
class MyFileChooser extends JFileChooser {
public void setFileFilter(FileFilter filter) {
super.setFileFilter(filter);
FileChooserUI ui = getUI();
if( ui instanceof BasicFileChooserUI ) {
BasicFileChooserUI bui = (BasicFileChooserUI) ui;
String file = bui.getFileName();
if( file != null ) {
String newFileName = ... change extension
bui.setFileName( newFileName );
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
小智 5
这是获取当前文件名(作为字符串)的方法。在 的属性更改监听器中JFileChooser.FILE_FILTER_CHANGED_PROPERTY
,您可以进行以下调用:
final JFileChooser fileChooser = new JFileChooser();
fileChooser.addPropertyChangeListener(JFileChooser.FILE_FILTER_CHANGED_PROPERTY, new PropertyChangeListener()
{
@Override
public void propertyChange(PropertyChangeEvent e) {
String currentName = ((BasicFileChooserUI)fileChooser.getUI()).getFileName();
MyFileFilter filter = (MyFileFilter) e.getNewValue();
// ... Transform currentName as you see fit using the newly selected filter.
// Suppose the result is in newName ...
fileChooser.setSelectedFile(new File(newName));
}
});
Run Code Online (Sandbox Code Playgroud)
(由 返回的的后代)getFileName()
的方法将返回用于输入文件名的对话框文本框的内容。似乎该值始终设置为非空字符串(如果框为空,则返回空字符串)。另一方面,如果用户尚未选择现有文件,则返回 null。javax.swing.plaf.basic.BasicFileChooserUI
FileChooserUI
JFileChooser.getUI()
getSelectedFile()
对话框的设计似乎受“文件选择”概念的约束;也就是说,虽然对话框可见,getSelectedFile()
但仅当用户已选择现有文件或名为 的程序时才返回有意义的值setSelectedFile()
。将在用户单击批准(即确定)按钮后getSelectedFile()
返回用户输入的内容。
该技术仅适用于单选对话框,但是根据所选过滤器更改文件扩展名也应仅适用于单个文件(“另存为...”对话框或类似对话框)。
这种设计早在 2003 年就在 sun.com 上引起了争论,详情请参阅链接。
归档时间: |
|
查看次数: |
23499 次 |
最近记录: |