我正在用java编写图表编辑器。此应用程序可以选择导出为各种标准图像格式,如.jpg,.png等。当用户单击文件 - >导出时,您会得到一个JFileChooser
,其中包含FileFilter
个在其中,.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();
}
});
}
}
答案 0 :(得分: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);
}
}
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));
}
});
答案 1 :(得分:4)
您还可以在附加后缀之前在SELECTED_FILE_CHANGED_PROPERTY上使用PropertyChangeListener。当针对新过滤器检查所选文件(并随后设置为null)时,实际上在 FILE_FILTER_CHANGED_PROPERTY事件之前触发了SELECTED_FILE_CHANGED_PROPERTY事件。
如果evt.getOldValue()!= null且evt.getNewValue()== null,您知道JFileChooser已经炸毁了您的文件。然后,您可以获取旧文件的名称(使用((File)evt.getOldValue())。getName(),如上所述),使用标准字符串解析函数拉出扩展,并将其存储到类中的命名成员变量中
这样,当触发FILE_FILTER_CHANGED事件时(紧接着就在我可以确定的位置附近),您可以从命名成员变量中提取该隐藏的根名称,为新文件过滤器类型应用扩展名,并设置相应地,JFileChooser选择了文件。
答案 2 :(得分:4)
这个怎么样:
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 );
}
}
}
}
答案 3 :(得分:4)
这是我的解决方案,它运行正常。它可能会帮助某人。您将创建自己的“MyExtension FileFilter”类,否则您必须修改代码。
public class MyFileChooser extends JFileChooser {
private File file = new File("");
public MyFileChooser() {
addPropertyChangeListener(JFileChooser.FILE_FILTER_CHANGED_PROPERTY, new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent e) {
String filename = MyFileChooser.this.file.getName();
String extold = null;
String extnew = null;
if (e.getOldValue() == null || !(e.getOldValue() instanceof MyExtensionFileFilter)) {
return;
}
if (e.getNewValue() == null || !(e.getNewValue() instanceof MyExtensionFileFilter)) {
return;
}
MyExtensionFileFilter oldValue = ((MyExtensionFileFilter) e.getOldValue());
MyExtensionFileFilter newValue = ((MyExtensionFileFilter) e.getNewValue());
extold = oldValue.getExtension();
extnew = newValue.getExtension();
if (filename.endsWith(extold)) {
filename = filename.replace(extold, extnew);
} else {
filename += ("." + extnew);
}
setSelectedFile(new File(filename));
}
});
}
@Override
public void setSelectedFile(File file) {
super.setSelectedFile(file);
if(getDialogType() == SAVE_DIALOG) {
if(file != null) {
super.setSelectedFile(file);
this.file = file;
}
}
}
@Override
public void approveSelection() {
if(getDialogType() == SAVE_DIALOG) {
File f = getSelectedFile();
if (f.exists()) {
String msg = "File existes ...";
msg = MessageFormat.format(msg, new Object[] { f.getName() });
int option = JOptionPane.showConfirmDialog(this, msg, "", JOptionPane.YES_NO_OPTION);
if (option == JOptionPane.NO_OPTION ) {
return;
}
}
}
super.approveSelection();
}
@Override
public void setVisible(boolean visible) {
super.setVisible(visible);
if(!visible) {
resetChoosableFileFilters();
}
}
}
答案 4 :(得分:2)
这是获取当前文件名(作为String)的方法。在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));
}
});
getFileName()
的{{1}}方法(由javax.swing.plaf.basic.BasicFileChooserUI
返回的FileChooserUI
的后代)将返回用于在文件中键入的对话框文本框的内容名称。似乎该值始终设置为非null String(如果该框为空,则返回空字符串)。另一方面,如果用户尚未选择现有文件,则JFileChooser.getUI()
返回null。
对话框的设计似乎受“文件选择”概念的支配;也就是说,当对话框可见时getSelectedFile()
仅在用户已选择现有文件或名为getSelectedFile()
的程序时才返回有意义的值。 setSelectedFile()
将返回用户在用户点击批准(即确定)按钮后输入的内容。
该技术仅适用于单选对话框,但是根据所选过滤器更改文件扩展名也应仅对单个文件有意义(“另存为...”对话框或类似对话框。)
此设计是2003年在sun.com上进行辩论的主题,有关详细信息,请参阅link。
答案 5 :(得分:0)
在之前使用getAbsolutePath()更改当前目录。 当我选择不同的FileFilter时,显示“我的文档”目录的JFileChooser对话框变为Netbeans的项目目录时,我感到很惊讶,因此我将其更改为使用getName()。 我还使用了JDK 6 FileNameExtensionFilter。
以下是代码:
final JFileChooser fc = new JFileChooser();
final File sFile = new File("test.xls");
fc.setSelectedFile(sFile);
// Store this filter in a variable to be able to select this after adding all FileFilter
// because addChoosableFileFilter add FileFilter in order in the combo box
final FileNameExtensionFilter excelFilter = new FileNameExtensionFilter("Excel document (*.xls)", "xls");
fc.addChoosableFileFilter(excelFilter);
fc.addChoosableFileFilter(new FileNameExtensionFilter("CSV document (*.csv)", "csv"));
// Force the excel filter
fc.setFileFilter(excelFilter);
// Disable All Files
fc.setAcceptAllFileFilterUsed(false);
// debug
fc.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
System.out.println("Property name=" + evt.getPropertyName() + ", oldValue=" + evt.getOldValue() + ", newValue=" + evt.getNewValue());
System.out.println("getSelectedFile()=" + fc.getSelectedFile());
}
});
fc.addPropertyChangeListener(JFileChooser.FILE_FILTER_CHANGED_PROPERTY, new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
Object o = evt.getNewValue();
if (o instanceof FileNameExtensionFilter) {
FileNameExtensionFilter filter = (FileNameExtensionFilter) o;
String ex = filter.getExtensions()[0];
File selectedFile = fc.getSelectedFile();
if (selectedFile == null) {
selectedFile = sFile;
}
String path = selectedFile.getName();
path = path.substring(0, path.lastIndexOf("."));
fc.setSelectedFile(new File(path + "." + ex));
}
}
});
答案 6 :(得分:0)
这是我对此的尝试。它使用accept()函数检查文件是否通过了过滤器。如果文件名没有,则扩展名将附加到末尾。
JFileChooser jfc = new JFileChooser(getFile()) {
public void approveSelection() {
if (getDialogType() == SAVE_DIALOG) {
File selectedFile = getSelectedFile();
FileFilter ff = getFileFilter();
// Checks against the current selected filter
if (!ff.accept(selectedFile)) {
selectedFile = new File(selectedFile.getPath() + ".txt");
}
super.setSelectedFile(selectedFile);
if ((selectedFile != null) && selectedFile.exists()) {
int response = JOptionPane.showConfirmDialog(
this,
"The file " + selectedFile.getName() + " already exists.\n" +
"Do you want to replace it?",
"Ovewrite file",
JOptionPane.YES_NO_OPTION,
JOptionPane.WARNING_MESSAGE
);
if (response == JOptionPane.NO_OPTION)
return;
}
}
super.approveSelection();
}
};
答案 7 :(得分:0)
如果您的Java版本支持 function resize_image($file, $w, $h, $crop=false) {
list($width, $height) = getimagesize($file);
$r = $width / $height;
if ($crop) {
if ($width > $height) {
$width = ceil($width-($width*abs($r-$w/$h)));
} else {
$height = ceil($height-($height*abs($r-$w/$h)));
}
$newwidth = $w;
$newheight = $h;
} else {
if ($w/$h > $r) {
$newwidth = $h*$r;
$newheight = $h;
} else {
$newheight = $w/$r;
$newwidth = $w;
}
}
//Get file extension
$exploding = explode(".",$file);
$ext = end($exploding);
switch($ext){
case "png":
$src = imagecreatefrompng($file);
break;
case "jpeg":
case "jpg":
$src = imagecreatefromjpeg($file);
break;
case "gif":
$src = imagecreatefromgif($file);
break;
default:
$src = imagecreatefromjpeg($file);
break;
}
$dst = imagecreatetruecolor($newwidth, $newheight);
imagecopyresampled($dst, $src, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
$file_name=time().'.png';
$stamp=imagecreatefrompng('stamp.png');
imagecopy($dst,$stamp,round($newwidth/2),round($newheight/2),0,0,60,17);
imagejpeg($dst,PRODUCT_IMAGE_SERVER_PATH.$file_name);
imagedestroy($dst);
imagedestroy($stamp);
imagedestroy($src);
return $file_name;
imagedestroy($file_name);
}
,则建议使用 $image=$_FILES['img1']['tmp_name'];
$file1 = resize_image($image, 250, 250);
$update_sql="update posted_ads set name='$name', price='$price', age='$age', location='$location', image='$file1',salername='$salername',phoneno='$phone',detail='$detail' where id='$id'";
mysqli_query($con,$update_sql);
$file1 = imagecreatetruecolor(100, 100);
imagedestroy($file1);
}
if($_FILES['img2']['name']!='') {
$image=$_FILES['img2']['tmp_name'];
$file2 = resize_image($image, 250, 250);
$update_sql="update posted_ads set name='$name', price='$price', age='$age', location='$location',imageTwo='$file2',salername='$salername',phoneno='$phone',detail='$detail' where id='$id'";
mysqli_query($con,$update_sql);
$file2 = imagecreatetruecolor(100, 100);
imagedestroy($file2);
}
而不是FileNameExtensionFilter
。否则,请创建您自己的新的相似抽象类,该抽象类从FileFilter
扩展并具有一个添加的方法FileFilter
(类似于getExtension
)。然后为您要使用的每个导出过滤器覆盖FileNameExtensionFilter.getExtensions
。
getExtension
然后对于一个示例JPG过滤器,您只需要比以前覆盖一个额外的方法:
public abstract class MyFileFilter extends FileFilter {
abstract public String getExtension();
}
用户选择文件后,只需调用 MyFileFilter filterJPG = new MyFileFilter () {
@Override
public String getDescription() {
return "A JPEG image (*." + getExtension() + ")";
}
@Override
public boolean accept(File f) {
String filename = f.getName().toLowerCase();
return filename.endsWith("."+getExtension());
}
@Override
public String getExtension() { return "jpg"; }
};
即可确定用户选择了哪个过滤器:
getFileFilter
如果您能够使用jfc.showDialog(frame, "export");
File file = jfc.getSelectedFile();
RvFileFilter filter = (RvFileFilter)jfc.getFileFilter();
String sExt = filter.getExtension(); //The extension to ensure the file has
,则只需使用数组中的第一个条目即可。