我只想更改 JTree 图标的第一个节点。有一个文件管理器使用 JTree 来显示文件。这是一个示意图示例。如何更改图标?
Back |->Please wait(this is leaf) Folder 1 |->file1 file2 file3 Folder 2 |->file1 file2 file3 Folder 3 |->file1 file2 file3
最佳答案
要更改树中条目的外观,请使用 TreeCellRenderer。例如
/** A TreeCellRenderer for a File. */
class FileTreeCellRenderer extends DefaultTreeCellRenderer {
private FileSystemView fileSystemView;
private JLabel label;
FileTreeCellRenderer() {
label = new JLabel();
label.setOpaque(true);
fileSystemView = FileSystemView.getFileSystemView();
}
@Override
public Component getTreeCellRendererComponent(
JTree tree,
Object value,
boolean selected,
boolean expanded,
boolean leaf,
int row,
boolean hasFocus) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;
File file = (File)node.getUserObject();
label.setIcon(fileSystemView.getSystemIcon(file));
label.setText(fileSystemView.getSystemDisplayName(file));
label.setToolTipText(file.getPath());
if (selected) {
label.setBackground(backgroundSelectionColor);
} else {
label.setBackground(backgroundNonSelectionColor);
}
return label;
}
}
在 Windows 上使用原生 PLAF。
这是用于抓取该屏幕截图的完整源代码(包括渲染器和表格模型)。
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
import javax.swing.tree.*;
import javax.swing.table.*;
import javax.swing.filechooser.FileSystemView;
import java.io.File;
import java.util.Date;
/**
A basic File Manager. Requires 1.6+ for the Desktop & SwingWorker
classes, amongst other minor things.
Includes support classes FileTableModel & FileTreeCellRenderer.
Neither Delete nor New has been implemented. See commented code for
hints on how to proceed for that functionality.
@TODO Still throws occasional AIOOBEs and NPEs, so some update on
the EDT must have been missed.
@author Andrew Thompson
@version 2011-05-29
@see <a href="https://stackoverflow.com/questions/6147965/change-icon-of-the-first-node-of-jtree/6153182#6153182">Change icon of the first node of JTree</a>
*/
class FileManager {
/** Used to open/edit/print files. */
private Desktop desktop;
/** Provides nice icons and names for files. */
private FileSystemView fileSystemView;
/** Main GUI container */
private JPanel gui;
/** File-system tree. Built Lazily */
private JTree tree;
/** Directory listing */
private JTable table;
private JProgressBar progressBar;
/* File controls. */
private JButton openFile;
private JButton printFile;
private JButton editFile;
private JButton deleteFile;
private JButton newFile;
/* File details. */
private JLabel fileName;
private JTextField path;
private JLabel date;
private JLabel size;
private JCheckBox readable;
private JCheckBox writable;
private JCheckBox executable;
private JCheckBox isDirectory;
private JCheckBox isFile;
/** Table model for File[]. */
private FileTableModel fileTableModel;
private ListSelectionListener listSelectionListener;
private boolean cellSizesSet = false;
/** currently selected File. */
private File currentFile;
private boolean safeMode = true;
public Container getGui() {
if (gui==null) {
gui = new JPanel(new BorderLayout(3,3));
gui.setBorder(new EmptyBorder(5,5,5,5));
fileSystemView = FileSystemView.getFileSystemView();
desktop = Desktop.getDesktop();
DefaultMutableTreeNode root = new DefaultMutableTreeNode();
File[] roots = fileSystemView.getRoots();
for (File fileSystemRoot : roots) {
DefaultMutableTreeNode node = new DefaultMutableTreeNode(fileSystemRoot);
root.add( node );
File[] files = fileSystemView.getFiles(fileSystemRoot, true);
for (File file : files) {
node.add(new DefaultMutableTreeNode(file));
}
}
TreeSelectionListener treeSelectionListener = new TreeSelectionListener() {
public void valueChanged(TreeSelectionEvent tse){
DefaultMutableTreeNode node =
(DefaultMutableTreeNode)tse.getPath().getLastPathComponent();
addChildren(node);
setFileDetails((File)node.getUserObject());
}
};
tree = new JTree(root);
tree.setRootVisible(false);
tree.addTreeSelectionListener(treeSelectionListener);
tree.setCellRenderer(new FileTreeCellRenderer());
tree.expandRow(0);
JScrollPane treeScroll = new JScrollPane(tree);
// as per trashgod tip
tree.setVisibleRowCount(15);
Dimension preferredSize = treeScroll.getPreferredSize();
Dimension widePreferred = new Dimension(
250,
(int)preferredSize.getHeight());
treeScroll.setPreferredSize( widePreferred );
JPanel detailView = new JPanel(new BorderLayout(3,3));
fileTableModel = new FileTableModel();
table = new JTable(fileTableModel);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
table.setAutoCreateRowSorter(true);
table.setShowVerticalLines(false);
// arbitrary size adjustment to better account for icons
table.setRowHeight( (int)(table.getRowHeight()*1.3) );
listSelectionListener = new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent lse) {
int row = table.getSelectionModel().getLeadSelectionIndex();
setFileDetails( ((FileTableModel)table.getModel()).getFile(row) );
}
};
table.getSelectionModel().addListSelectionListener(listSelectionListener);
JScrollPane tableScroll = new JScrollPane(table);
Dimension d = tableScroll.getPreferredSize();
tableScroll.setPreferredSize(new Dimension((int)d.getWidth(), (int)d.getHeight()/2));
detailView.add(tableScroll, BorderLayout.CENTER);
JPanel fileMainDetails = new JPanel(new BorderLayout(4,2));
fileMainDetails.setBorder(new EmptyBorder(0,6,0,6));
JPanel fileDetailsLabels = new JPanel(new GridLayout(0,1,2,2));
fileMainDetails.add(fileDetailsLabels, BorderLayout.WEST);
JPanel fileDetailsValues = new JPanel(new GridLayout(0,1,2,2));
fileMainDetails.add(fileDetailsValues, BorderLayout.CENTER);
fileDetailsLabels.add(new JLabel("File", JLabel.TRAILING));
fileName = new JLabel();
fileDetailsValues.add(fileName);
fileDetailsLabels.add(new JLabel("Path/name", JLabel.TRAILING));
path = new JTextField(5);
path.setEditable(false);
fileDetailsValues.add(path);
fileDetailsLabels.add(new JLabel("Last Modified", JLabel.TRAILING));
date = new JLabel();
fileDetailsValues.add(date);
fileDetailsLabels.add(new JLabel("File size", JLabel.TRAILING));
size = new JLabel();
fileDetailsValues.add(size);
int count = fileDetailsLabels.getComponentCount();
for (int ii=0; ii<count; ii++) {
fileDetailsLabels.getComponent(ii).setEnabled(false);
}
JToolBar toolBar = new JToolBar();
openFile = new JButton("Open");
openFile.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ae) {
try {
desktop.open(currentFile);
} catch(Throwable t) {
JOptionPane.showMessageDialog(
gui,
t.toString(),
t.getMessage(),
JOptionPane.ERROR_MESSAGE
);
}
gui.repaint();
}
});
toolBar.add(openFile);
editFile = new JButton("Edit");
editFile.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ae) {
try {
desktop.edit(currentFile);
} catch(Throwable t) {
showThrowable(t);
}
}
});
toolBar.add(editFile);
printFile = new JButton("Print");
printFile.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ae) {
try {
desktop.print(currentFile);
} catch(Throwable t) {
showThrowable(t);
}
}
});
toolBar.add(printFile);
// Check the actions are supported on this platform!
openFile.setEnabled(desktop.isSupported(Desktop.Action.OPEN));
editFile.setEnabled(desktop.isSupported(Desktop.Action.EDIT));
printFile.setEnabled(desktop.isSupported(Desktop.Action.PRINT));
toolBar.addSeparator();
deleteFile = new JButton("Delete");
deleteFile.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ae) {
if (currentFile==null) {
JOptionPane.showMessageDialog(
gui,
"No file selected for deletion.",
"Select File",
JOptionPane.ERROR_MESSAGE
);
return;
}
if (safeMode) {
safeMessage();
} else {
int result = JOptionPane.showConfirmDialog(
gui,
"Are you sure you want to delete this file?",
"Delete File",
JOptionPane.ERROR_MESSAGE
);
if (result==JOptionPane.OK_OPTION) {
try {
boolean deleted = currentFile.delete();
if (deleted) {
// delete the node..
} else {
JOptionPane.showMessageDialog(
gui,
"The file '" +
currentFile +
"' could not be deleted.",
"Delete Failed",
JOptionPane.ERROR_MESSAGE
);
}
} catch(Throwable t) {
showThrowable(t);
}
}
}
gui.repaint();
}
});
toolBar.add(deleteFile);
final JPanel newPanel = new JPanel(new GridLayout(0,1,3,3));
final JRadioButton newTypeFile = new JRadioButton("New File");
JRadioButton newTypeDirectory = new JRadioButton("New Directory");
ButtonGroup bg = new ButtonGroup();
bg.add(newTypeFile);
bg.add(newTypeDirectory);
final JTextField name = new JTextField(15);
newPanel.add( name );
newPanel.add( newTypeFile );
newPanel.add( newTypeDirectory );
newFile = new JButton("New");
newFile.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ae) {
if (currentFile==null) {
JOptionPane.showMessageDialog(
gui,
"No location selected for new file.",
"Select Location",
JOptionPane.ERROR_MESSAGE
);
return;
}
if (safeMode) {
safeMessage();
} else {
int result = JOptionPane.showConfirmDialog(gui, newPanel);
if (result==JOptionPane.OK_OPTION) {
try {
boolean created;
File file = new File( currentFile, name.getText() );
if (newTypeFile.isSelected()) {
created = file.createNewFile();
} else {
created = file.mkdir();
}
if (created) {
// add the new node..
} else {
JOptionPane.showMessageDialog(
gui,
"The file '" +
file +
"' could not be created.",
"Create Failed",
JOptionPane.ERROR_MESSAGE
);
}
} catch(Throwable t) {
showThrowable(t);
}
}
}
gui.repaint();
}
});
toolBar.add(newFile);
JPanel flags = new JPanel(new GridLayout(1,0,4,4));
readable = new JCheckBox("Read");
readable.setEnabled(false);
flags.add(readable);
writable = new JCheckBox("Write");
writable.setEnabled(false);
flags.add(writable);
executable = new JCheckBox("Execute");
executable.setEnabled(false);
flags.add(executable);
isDirectory = new JCheckBox("Directory");
isDirectory.setEnabled(false);
flags.add(isDirectory);
isFile = new JCheckBox("File");
isFile.setEnabled(false);
flags.add(isFile);
//flags.setBorder(new TitledBorder("Flags"));
JPanel fileView = new JPanel(new BorderLayout(3,3));
fileView.add(toolBar,BorderLayout.NORTH);
fileView.add(fileMainDetails,BorderLayout.CENTER);
fileView.add(flags,BorderLayout.SOUTH);
detailView.add(fileView, BorderLayout.SOUTH);
JSplitPane splitPane = new JSplitPane(
JSplitPane.HORIZONTAL_SPLIT,
treeScroll,
detailView);
gui.add(splitPane, BorderLayout.CENTER);
JPanel simpleOutput = new JPanel(new BorderLayout(3,3));
progressBar = new JProgressBar();
simpleOutput.add(progressBar, BorderLayout.EAST);
progressBar.setVisible(false);
gui.add(simpleOutput, BorderLayout.SOUTH);
}
return gui;
}
private void safeMessage() {
String safe =
"This is a test program! " +
"Delete/New have not been enabled. " +
"Recompile with safeMode=false; to enable.";
JOptionPane.showMessageDialog( gui, safe, "Not Enabled", JOptionPane.ERROR_MESSAGE );
}
private void showThrowable(Throwable t) {
JOptionPane.showMessageDialog(
gui,
t.toString(),
t.getMessage(),
JOptionPane.ERROR_MESSAGE
);
gui.repaint();
}
/** Update the table on the EDT */
private void setTableDate(final File[] files) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
table.getSelectionModel().removeListSelectionListener(listSelectionListener);
fileTableModel.setFiles(files);
table.getSelectionModel().addListSelectionListener(listSelectionListener);
int max = table.getRowCount();
if (!cellSizesSet) {
setColumnWidth(0,-1);
setColumnWidth(3,60);
table.getColumnModel().getColumn(3).setMaxWidth(120);
setColumnWidth(4,-1);
setColumnWidth(5,-1);
setColumnWidth(6,-1);
setColumnWidth(7,-1);
cellSizesSet = true;
}
}
});
}
private void setColumnWidth(int column, int width) {
TableColumn tableColumn = table.getColumnModel().getColumn(column);
if (width<0) {
// use the preferred width of the header..
JLabel label = new JLabel( (String)tableColumn.getHeaderValue() );
Dimension preferred = label.getPreferredSize();
width = (int)preferred.getWidth()+10;
}
tableColumn.setPreferredWidth(width);
tableColumn.setMaxWidth(width);
tableColumn.setMinWidth(width);
}
/** Add the files that are contained within the directory of this node. */
private void addChildren(final DefaultMutableTreeNode node) {
SwingWorker worker = new SwingWorker() {
@Override
public String doInBackground() {
tree.setEnabled(false);
progressBar.setVisible(true);
progressBar.setIndeterminate(true);
File file = (File)node.getUserObject();
if ( file.isDirectory() ) {
File[] files = fileSystemView.getFiles(file, true);
if (node.isLeaf()) {
for (File child : files) {
node.add( new DefaultMutableTreeNode(child) );
}
}
setTableDate(files);
}
progressBar.setIndeterminate(false);
progressBar.setVisible(false);
tree.setEnabled(true);
return "done";
}
};
worker.execute();
}
/** Update the File details view with the details of this File. */
private void setFileDetails(File file) {
currentFile = file;
fileName.setIcon(fileSystemView.getSystemIcon(file));
fileName.setText(fileSystemView.getSystemDisplayName(file));
path.setText(file.getPath());
date.setText(new Date(file.lastModified()).toString());
size.setText(file.length() + " bytes");
readable.setSelected(file.canRead());
writable.setSelected(file.canWrite());
executable.setSelected(file.canExecute());
isDirectory.setSelected(file.isDirectory());
isFile.setSelected(file.isFile());
gui.repaint();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
// Significantly improves the look of the output in
// terms of the file names returned by FileSystemView!
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch(Exception weTried) {
}
JFrame f = new JFrame("File Manager");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
FileManager fileManager = new FileManager();
f.setContentPane(fileManager.getGui());
f.pack();
f.setLocationRelativeTo(null);
f.setLocationByPlatform(true);
f.setMinimumSize(f.getSize());
f.setVisible(true);
}
});
}
}
/** A TableModel to hold File[]. */
class FileTableModel extends AbstractTableModel {
private File[] files;
private FileSystemView fileSystemView = FileSystemView.getFileSystemView();
private String[] columns = {
"Icon",
"File",
"Path/name",
"Size",
"Last Modified",
"R",
"W",
"E"
};
FileTableModel() {
this(new File[0]);
}
FileTableModel(File[] files) {
this.files = files;
}
public Object getValueAt(int row, int column) {
File file = files[row];
switch (column) {
case 0:
return fileSystemView.getSystemIcon(file);
case 1:
return fileSystemView.getSystemDisplayName(file);
case 2:
return file.getPath();
case 3:
return file.length();
case 4:
return file.lastModified();
case 5:
return file.canRead();
case 6:
return file.canWrite();
case 7:
return file.canExecute();
default:
System.err.println("Logic Error");
}
return "";
}
public int getColumnCount() {
return columns.length;
}
public Class<?> getColumnClass(int column) {
switch (column) {
case 0:
return ImageIcon.class;
case 3:
return Long.class;
case 4:
return Date.class;
case 5:
case 6:
case 7:
return Boolean.class;
}
return String.class;
}
public String getColumnName(int column) {
return columns[column];
}
public int getRowCount() {
return files.length;
}
public File getFile(int row) {
return files[row];
}
public void setFiles(File[] files) {
this.files = files;
fireTableDataChanged();
}
}
/** A TreeCellRenderer for a File. */
class FileTreeCellRenderer extends DefaultTreeCellRenderer {
private FileSystemView fileSystemView;
private JLabel label;
FileTreeCellRenderer() {
label = new JLabel();
label.setOpaque(true);
fileSystemView = FileSystemView.getFileSystemView();
}
@Override
public Component getTreeCellRendererComponent(
JTree tree,
Object value,
boolean selected,
boolean expanded,
boolean leaf,
int row,
boolean hasFocus) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;
File file = (File)node.getUserObject();
label.setIcon(fileSystemView.getSystemIcon(file));
label.setText(fileSystemView.getSystemDisplayName(file));
label.setToolTipText(file.getPath());
if (selected) {
label.setBackground(backgroundSelectionColor);
} else {
label.setBackground(backgroundNonSelectionColor);
}
return label;
}
}
这基本是一样的answer already provided by trashgod ,但带有代码和屏幕截图。
关于java - 改变JTree第一个节点的图标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6147965/
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta
我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何
我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象
关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我有一个正在构建的应用程序,我需要一个模型来创建另一个模型的实例。我希望每辆车都有4个轮胎。汽车模型classCar轮胎模型classTire但是,在make_tires内部有一个错误,如果我为Tire尝试它,则没有用于创建或新建的activerecord方法。当我检查轮胎时,它没有这些方法。我该如何补救?错误是这样的:未定义的方法'create'forActiveRecord::AttributeMethods::Serialization::Tire::Module我测试了两个环境:测试和开发,它们都因相同的错误而失败。 最佳答案
我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b
我想让一个yaml对象引用另一个,如下所示:intro:"Hello,dearuser."registration:$introThanksforregistering!new_message:$introYouhaveanewmessage!上面的语法只是它如何工作的一个例子(这也是它在thiscpanmodule中的工作方式。)我正在使用标准的rubyyaml解析器。这可能吗? 最佳答案 一些yaml对象确实引用了其他对象:irb>require'yaml'#=>trueirb>str="hello"#=>"hello"ir
我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www