下面的代码应该从JFileChooser获取默认目录图标,然后在我自定义的“Recent Directories”列表中使用该图标,该列表作为JFileChooser对话框的附件提供。有人可以解释为什么下面的代码不起作用(特别是为什么在DefaultListRenderer上的setIcon没有做到这一点),并告诉我如何将图标放在JList中的每个项目旁边?我宁愿避免实现我自己的ListCellRenderer,除非这是使其工作的唯一方法。
import java.awt.*;
import java.io.File;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class Chooser extends JPanel {
private static final String[] BUTTON_TEXTS = { "Hello", "Goodbye",
"Hello Goodbye", "Adios", "This is a long String for WTF", "Hello",
"Goodbye", "Hello Goodbye", "Adios", "This string WTF" };
public Chooser(Icon icon) {
this.setLayout(new BorderLayout());
JPanel labelPanel = new JPanel(new BorderLayout());
JLabel label = new JLabel("Recent Directories:");
labelPanel.add(label, BorderLayout.LINE_START);
labelPanel.setBackground(Color.LIGHT_GRAY);
labelPanel.setBorder(new EmptyBorder(5, 10, 5, 0));
DefaultListModel model = new DefaultListModel();
JList list = new JList(model);
DefaultListCellRenderer renderer = (DefaultListCellRenderer)list.getCellRenderer();
renderer.setIcon(icon);
for (String s : BUTTON_TEXTS) model.addElement(s);
list.setBorder(new EmptyBorder(0, 5, 5, 0));
list.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
// respond to selection here
}
});
add(labelPanel, BorderLayout.PAGE_START);
// add(new JScrollPane(buttonPanel), BorderLayout.CENTER);
add(new JScrollPane(list), BorderLayout.CENTER);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
JFileChooser fileChooser = new JFileChooser();
Icon icon = fileChooser.getIcon(new File("."));
/*JFrame frame = new JFrame();
frame.setSize(100,100);
JPanel temp = new JPanel();
JLabel tlbl = new JLabel("picture");
tlbl.setIcon(icon);
temp.add(tlbl);
frame.add(temp);
frame.setVisible(true);*/
Chooser c = new Chooser(icon);
fileChooser.setAccessory(c);
fileChooser.showOpenDialog(null);
}
}
答案 0 :(得分:7)
只要调用DefaultListCellRenderer
方法,getListCellRendererComponent
就会清除图标。
相反,您可以通过子类化DefaultListCellRenderer
来干扰渲染器的方法:
list.setCellRenderer(new DefaultListCellRenderer() {
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
label.setIcon(icon);
return label;
}
});
答案 1 :(得分:4)
使用自定义单元格渲染器的提示,扩展为包含一些特定于处理File
中Icon
和JList
个对象的其他提示。
import java.awt.*;
import java.io.File;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.filechooser.FileSystemView;
public class Chooser extends JPanel {
private static final File[] RECENT_DIRECTORIES = File.listRoots();
public Chooser() {
this.setLayout(new BorderLayout());
JPanel labelPanel = new JPanel(new BorderLayout());
JLabel label = new JLabel("Recent Directories:");
labelPanel.add(label, BorderLayout.LINE_START);
labelPanel.setBackground(Color.LIGHT_GRAY);
labelPanel.setBorder(new EmptyBorder(5, 10, 5, 0));
JList list = new JList(RECENT_DIRECTORIES);
list.setCellRenderer(new DefaultListCellRenderer() {
FileSystemView fsv = FileSystemView.getFileSystemView();
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value instanceof File) {
label.setIcon(fsv.getSystemIcon((File)value));
}
return label;
}
});
list.setBorder(new EmptyBorder(0, 5, 5, 0));
list.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
// respond to selection here
}
});
add(labelPanel, BorderLayout.PAGE_START);
add(new JScrollPane(list), BorderLayout.CENTER);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFileChooser fileChooser = new JFileChooser();
Chooser c = new Chooser();
fileChooser.setAccessory(c);
fileChooser.showOpenDialog(null);
}
});
}
}
总之,这些提示是:
String
个对象来表示JList
个对象。使用File
。File
- > BUTTON_TEXTS
RECENT_DIRECTORIES
提供给File[]
的构造函数 - 无需迭代数组并添加每个项目。Jlist
绕过每个PLAF吐出的沉闷图标。列表中的FileSystemView.getSystemIcon(File)
个实例在原始左侧窗格中使用的图标旁边看起来很奇怪(以“1 Media”等开头)。如果将PLAF设置为系统PLAF,它们将匹配。重点是FSV将提供更好的Icon
,无论PLAF如何。如需更多提示(这是tip-a-palooza!),请参阅File Browser GUI。
我不明白关于“PLAF”的提示(我也不知道PLAF是什么意思)。
幸运谷歌。尝试搜索并选择第一个提到“Java”的链接(这里是第二个链接)。
我注意到使用代码产生的文件夹图标与JFileChooser上的文件夹/目录图标不同。 JFC的图标是蓝色的,看起来更像是java-y。我在原始代码中使用的getIcon()调用确实有效,但我不确定调用类似于你的相同图标(FileSystemView.getSystemIcon()或类似的)
所有 File Browser (FileBro) GUI屏幕截图中显示的图标都是使用文件选择器Icon
方法制作的,但它们看起来就像您示例中由FSV,对吗?它们看起来像金属屏幕截图中看到的FSV图标的原因是PLAF是FileBro('Windows'PLAF)的系统默认值。当GUI使用该OS的“本机”PLAF时,为文件选择器返回的图标与FSV返回的图标匹配。
如果您在进行一些研究后需要更具体的答案,并仔细查看FileBro的getIcon()
以了解它如何设置PLAF,请提出更具体的问题。