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(目录,)