Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/394.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在组合框中显示没有扩展名的文件名?_Java_Swing_Jcombobox - Fatal编程技术网

Java 如何在组合框中显示没有扩展名的文件名?

Java 如何在组合框中显示没有扩展名的文件名?,java,swing,jcombobox,Java,Swing,Jcombobox,我的用例如下:我想要一个组合框,它显示一个目录中经过过滤的文件列表,该目录在每次打开时都会刷新。我还希望组合框中显示的字符串是没有目录或扩展名的文件名(它们是我不想向用户公开的实现细节) 我实现了一个ComboBoxModel,如下所示: public class XMLComboModel extends DefaultComboBoxModel<Path> implements PopupMenuListener { public static final String EXT

我的用例如下:我想要一个组合框,它显示一个目录中经过过滤的文件列表,该目录在每次打开时都会刷新。我还希望组合框中显示的字符串是没有目录或扩展名的文件名(它们是我不想向用户公开的实现细节)

我实现了一个
ComboBoxModel
,如下所示:

public class XMLComboModel extends DefaultComboBoxModel<Path> implements PopupMenuListener {

public static final String EXT = ".xml";
private final Path directory;

public XMLComboModel(String pathName) {
    this.directory = Paths.get(pathName);
    populateModel();
}

public Path getSelectedPath() {
    return (Path) getSelectedItem();
}

@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
    populateModel();
}

private void populateModel() {
    removeAllElements();
    try {
        Files.newDirectoryStream(directory, "*" + EXT).forEach(this::addElement);
        if (getSelectedPath() != null) {
            for (int i = 0; i < getSize(); i++) {
                if (getElementAt(i).compareTo(getSelectedPath()) == 0)
                    setSelectedItem(getElementAt(i));
            }
        }
    } catch (IOException ex) {
        LOG.log(Level.SEVERE, null, ex);
    }
}
不幸的是,这不起作用。它正确显示被截断的文件名,但现在使用
字符串调用
setSelectedItem
,而不是
路径调用
,这很有意义,但与模型中的路径不匹配

我的选择似乎是:

  • 编写我自己的自定义组件,该组件复制
    basicComboxRenderer
    中的功能,但标签中的文本除外
  • 在模型中重写
    setSelectedItem
    ,以查找具有给定文件名的路径
第二个更容易实现:

@Override
public void setSelectedItem(Object item) {
    for (int i = 0; i < getSize(); i++) {
        if (super.getElementAt(i).equals(Paths.get(item.toString()))) {
            super.setSelectedItem(super.getElementAt(i));
            return;
        }
    }
}
@覆盖
公共无效集合selecteditem(对象项){
对于(int i=0;i
但这看起来相当笨拙,因为我已经从模型中传递了一个
路径
,最好能得到一个
路径
。我是否错过了一个更简单的方法来实现这一点

但是现在使用字符串而不是路径调用setSelectedItem

渲染器与组合框模型的其他方法无关

如果要将
Path
对象传递给
setSelectedItem(…)
方法,则需要确保
Path
对象实现
equals(…)
方法,以便模型可以选择正确的
路径

然后只需创建自定义渲染器,以显示要显示的
路径
对象的任何部分

最好能找到一条回去的路

如果模型包含路径对象,则
getSelectedItem()
方法将返回路径对象。您需要将其强制转换为路径,或者使用
getSelectedPath()
方法

因此,您不需要覆盖DefaultComboxModel的任何方法,只需添加
getSelectedPath()
方法即可

但是现在使用字符串而不是路径调用setSelectedItem

渲染器与组合框模型的其他方法无关

如果要将
Path
对象传递给
setSelectedItem(…)
方法,则需要确保
Path
对象实现
equals(…)
方法,以便模型可以选择正确的
路径

然后只需创建自定义渲染器,以显示要显示的
路径
对象的任何部分

最好能找到一条回去的路

如果模型包含路径对象,则
getSelectedItem()
方法将返回路径对象。您需要将其强制转换为路径,或者使用
getSelectedPath()
方法


因此,您不需要覆盖DefaultComboxModel的任何方法,只需添加
getSelectedPath()
方法。

为了清晰起见,如果其他读者发现此问题,以下是基于@camickr答案的完整工作代码。注意,我使用了现有的渲染器来创建新的渲染器,以保持外观和感觉的一致性

private JComboBox createDirectoryCombo(Path directory) {
    ComboBoxModel<Path> model = new DefaultComboBoxModel<>();
    populateModel(model);
    JComboBox<Path> comboBox = new JComboBox(model);
    comboBox.addPopupMenuListener(new PopupMenuListener() {
        @Override
        public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
            populateModel(model);
        }
        // Other methods omitted for clarity
    });
    ListCellRenderer renderer = comboBox.getRenderer();
    comboBox.setRenderer((list, path, index, selected, focus) -> {
        String fileName = path == null ? "" : path.getFileName().toString().replace(EXT, "");
        return renderer.getListCellRendererComponent(list, fileName, index, selected, focus);
    });

}

private void populateModel(ComboBoxModel<Path> model) {
    try {
        Path previousSelection = getSelectedPath();
        removeAllElements();
        for (Path path : Files.newDirectoryStream(directory, "*" + EXT)) {
            addElement(path);
            if (path.equals(previousSelection))
                setSelectedItem(path);
        }
    } catch (IOException ex) {
        LOG.log(Level.SEVERE, null, ex);
    }
}
private JComboBox createDirectoryCombo(路径目录){
ComboBoxModel=新的DefaultComboxModel();
人口模型(模型);
JComboBox组合框=新的JComboBox(型号);
comboBox.addPopupMenuListener(新的PopupMenuListener(){
@凌驾
public void弹出菜单将变为可见(弹出菜单事件e){
人口模型(模型);
}
//为清楚起见,省略了其他方法
});
ListCellRenderer=comboBox.getRenderer();
comboBox.setRenderer((列表、路径、索引、选定项、焦点)->{
字符串fileName=path==null?“:path.getFileName().toString().replace(EXT,”;
返回renderer.getListCellRendererComponent(列表、文件名、索引、选定项、焦点);
});
}
私有void populateModel(ComboBoxModel模型){
试一试{
Path previousSelection=getSelectedPath();
移除所有元素();
对于(路径:Files.newDirectoryStream(目录“*”+EXT)){
加法(路径);
if(路径等于(先前选择))
设置selecteditem(路径);
}
}捕获(IOEX异常){
LOG.LOG(Level.SEVERE,null,ex);
}
}

为了清晰起见,如果其他读者发现了这个问题,以下是基于@camickr答案的完整工作代码。注意,我使用了现有的渲染器来创建新的渲染器,以保持外观和感觉的一致性

private JComboBox createDirectoryCombo(Path directory) {
    ComboBoxModel<Path> model = new DefaultComboBoxModel<>();
    populateModel(model);
    JComboBox<Path> comboBox = new JComboBox(model);
    comboBox.addPopupMenuListener(new PopupMenuListener() {
        @Override
        public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
            populateModel(model);
        }
        // Other methods omitted for clarity
    });
    ListCellRenderer renderer = comboBox.getRenderer();
    comboBox.setRenderer((list, path, index, selected, focus) -> {
        String fileName = path == null ? "" : path.getFileName().toString().replace(EXT, "");
        return renderer.getListCellRendererComponent(list, fileName, index, selected, focus);
    });

}

private void populateModel(ComboBoxModel<Path> model) {
    try {
        Path previousSelection = getSelectedPath();
        removeAllElements();
        for (Path path : Files.newDirectoryStream(directory, "*" + EXT)) {
            addElement(path);
            if (path.equals(previousSelection))
                setSelectedItem(path);
        }
    } catch (IOException ex) {
        LOG.log(Level.SEVERE, null, ex);
    }
}
private JComboBox createDirectoryCombo(路径目录){
ComboBoxModel=新的DefaultComboxModel();
人口模型(模型);
JComboBox组合框=新的JComboBox(型号);
comboBox.addPopupMenuListener(新的PopupMenuListener(){
@凌驾
public void弹出菜单将变为可见(弹出菜单事件e){
人口模型(模型);
}
//为清楚起见,省略了其他方法
});
ListCellRenderer=comboBox.getRenderer();
comboBox.setRenderer((列表、路径、索引、选定项、焦点)->{
字符串fileName=path==null?“:path.getFileName().toString().replace(EXT,”;
返回renderer.getListCellRendererComponent(列表、文件名、索引、选定项、焦点);
});
}
私有void populateModel(ComboBoxModel模型){
试一试{
Path previousSelection=getSelectedPath();
移除所有元素();
对于(路径路径:Files.newDirectoryStream(目录,)