Swing/FileSystemTreeWithCheckBox のバックアップの現在との差分(No.5)
TITLE:JCheckBox付きJTreeでディテクトリ構造を表示
Posted by aterai at 2011-08-15
JCheckBox付きJTreeでディテクトリ構造を表示
編集可能なJCheckBoxをノードに追加したJTreeでディテクトリ構造を表示します。-
category: swing
folder: FileSystemTreeWithCheckBox
title: JCheckBox付きJTreeでディレクトリ構造を表示
tags: [JTree, JCheckBox, TreeCellRenderer, TreeCellEditor, File, TreeModelListener, SwingWorker]
author: aterai
pubdate: 2011-08-15T15:43:03+09:00
description: 編集可能なJCheckBoxをノードに追加したJTreeでディレクトリ構造を表示します。
image:
hreflang:
href: https://java-swing-tips.blogspot.com/2011/08/filesystemtree-with-jcheckbox.html lang: en
概要
編集可能なJCheckBox
をノードに追加したJTree
でディレクトリ構造を表示します。
- &jar;
- &zip;
Screenshot
Advertisement
サンプルコード
#spanend
#spanadd
* サンプルコード [#sourcecode]
#spanend
#spanadd
#code(link){{
#spanend
class CheckBoxNodeEditor extends TriStateCheckBox implements TreeCellEditor {
private final FileSystemView fileSystemView;
private final JPanel panel = new JPanel(new BorderLayout());
private DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer();
private File file;
#spanadd
#spanend
public CheckBoxNodeEditor(FileSystemView fileSystemView) {
super();
this.fileSystemView = fileSystemView;
this.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
stopCellEditing();
}
});
panel.setFocusable(false);
panel.setRequestFocusEnabled(false);
panel.setOpaque(false);
panel.add(this, BorderLayout.WEST);
this.setOpaque(false);
}
#spanadd
#spanend
@Override public Component getTreeCellEditorComponent(
JTree tree, Object value, boolean isSelected, boolean expanded,
boolean leaf, int row) {
JLabel l = (JLabel)renderer.getTreeCellRendererComponent(
tree, value, true, expanded, leaf, row, true);
JLabel l = (JLabel) renderer.getTreeCellRendererComponent(
tree, value, true, expanded, leaf, row, true);
l.setFont(tree.getFont());
setOpaque(false);
if(value != null && value instanceof DefaultMutableTreeNode) {
if (value instanceof DefaultMutableTreeNode) {
this.setEnabled(tree.isEnabled());
this.setFont(tree.getFont());
Object userObject = ((DefaultMutableTreeNode)value).getUserObject();
if(userObject!=null && userObject instanceof CheckBoxNode) {
CheckBoxNode node = (CheckBoxNode)userObject;
if(node.status==Status.INDETERMINATE) {
Object userObject = ((DefaultMutableTreeNode) value).getUserObject();
if (userObject instanceof CheckBoxNode) {
CheckBoxNode node = (CheckBoxNode) userObject;
if (node.status == Status.INDETERMINATE) {
setIcon(new IndeterminateIcon());
}else{
} else {
setIcon(null);
}
file = node.file;
l.setIcon(fileSystemView.getSystemIcon(file));
l.setText(fileSystemView.getSystemDisplayName(file));
setSelected(node.status==Status.SELECTED);
setSelected(node.status == Status.SELECTED);
}
//panel.add(this, BorderLayout.WEST);
// panel.add(this, BorderLayout.WEST);
panel.add(l);
return panel;
}
return l;
}
#spanadd
#spanend
@Override public Object getCellEditorValue() {
return new CheckBoxNode(file, isSelected()?Status.SELECTED:Status.DESELECTED);
return new CheckBoxNode(file, isSelected() ? Status.SELECTED : Status.DESELECTED);
}
#spanadd
#spanend
@Override public boolean isCellEditable(EventObject e) {
if(e != null && e instanceof MouseEvent && e.getSource() instanceof JTree) {
MouseEvent me = (MouseEvent)e;
JTree tree = (JTree)e.getSource();
if (e instanceof MouseEvent && e.getSource() instanceof JTree) {
MouseEvent me = (MouseEvent) e;
JTree tree = (JTree) e.getSource();
TreePath path = tree.getPathForLocation(me.getX(), me.getY());
Rectangle r = tree.getPathBounds(path);
if(r==null) return false;
if (r == null) {
return false;
}
Dimension d = getPreferredSize();
r.setSize(new Dimension(d.width, r.height));
if(r.contains(me.getX(), me.getY())) {
if(file==null && System.getProperty("java.version").startsWith("1.7.0")) {
System.out.println("XXX: Java 7, only on first run\n"+getBounds());
setBounds(new Rectangle(0,0,d.width,r.height));
}
if (r.contains(me.getX(), me.getY())) {
// if (file == null && System.getProperty("java.version").startsWith("1.7.0")) {
// System.out.println("XXX: Java 7, only on first run\n" + getBounds());
// setBounds(new Rectangle(0, 0, d.width, r.height));
// }
return true;
}
}
return false;
}
#spanadd
#spanend
@Override public void updateUI() {
super.updateUI();
if(panel!=null) panel.updateUI();
//1.6.0_24 bug??? @see 1.7.0 DefaultTreeCellRenderer#updateUI()
if (panel != null) {
panel.updateUI();
}
// 1.6.0_24 bug??? @see 1.7.0 DefaultTreeCellRenderer#updateUI()
renderer = new DefaultTreeCellRenderer();
}
#spandel
//......
#spanend
#spanadd
// ...
#spanend
解説
このサンプルは、FileSystemViewを使ってディテクトリ構造をJTreeに表示すると、JTreeの葉ノードをJCheckBoxにするを組み合わせて作成しています。解説
このサンプルは、FileSystemViewを使ってディレクトリ構造をJTreeに表示すると、JTreeの葉ノードをJCheckBoxにするを組み合わせて作成しています。TreeCellEditor#isCellEditable(...)をオーバーライドして、JCheckBox付近をクリックした場合のみ編集可能(チェックの有無を切り替えることができる)にし、ラベールやアイコンなどをクリックした場合は、編集状態にせずノードの展開や折り畳みができるように設定しています。
- -
JTableHeaderにJCheckBoxを追加してセルの値を切り替えるのように親ノードをチェックすると子ノードのチェックをすべて切り替える機能には今のところ対応していません。
- 対応済み
-
TreeCellEditor#isCellEditable(...)
をオーバーライドしてJCheckBox
の領域内をクリックした場合のみ編集可能(チェックの有無を切り替えることができる)に設定 - ラベルやアイコンなどをクリックした場合は編集状態にせずノードの展開や折り畳みができるように設定
参考リンク
参考リンク
コメント
- JTreeのすべてのノードにJCheckBoxを追加する で使用しているTreeModelListenerを追加してJCheckBoxの状態を変更するように修正。 -- aterai
- チェックされたノード(最上位となる)の一覧をコンソールに表示するJButtonを追加(スクリーンショットなどは面倒なので更新しない)。 -- aterai
コメント
- JTreeのすべてのノードにJCheckBoxを追加する で使用している
TreeModelListener
を追加してJCheckBox
の状態を変更するように修正。 -- aterai - チェックされたノード(最上位となる)の一覧をコンソールに表示する
JButton
を追加(スクリーンショットなどは面倒なので更新しない)。 -- aterai - ノードをチェックしてから、そのディレクトリを開いても子ディレクトリにチェックが反映されない。 -- aterai
- いつも勉強させていただいております。サンプルでは
root
はデスクトップとなっていますが、もし例えばZ:\
またはZ:\aaa
とTOP
にしたい場合、どこを修正すれば宜しいでしょうか?ご教示をお願いいたします。 -- Tiger- こんばんは。このサンプルでは、
fileSystemView.getRoots()
でDesktop
フォルダ(Windows
の場合)を取得しているので、この箇所を、例えばFile fileSystemRoot = new File("Z:/"); /* for(File fileSystemRoot: fileSystemView.getRoots()) */ {
のように変更するのはどうでしょうか。 -- aterai
- こんばんは。このサンプルでは、
- ご教示、ありがとうございました。ご指摘のところを見落としました。やり方は理解できました。ついでに、もし
root
はデスクトップにしておいて、C:\
を表示させないで(または展開させないで)、X:\
,Y:\
のみ操作させるには、どこを弄れば宜しいでしょうか?ありがとうございました。来年もよろしくお願いします。 -- Tiger-
fileSystemView.getRoots()
でDesktop
フォルダを取得すると、 マイコンピュータとか、Desktop
フォルダがC:\
にある場合はマイドキュメントなどを選択不可にするのが、面倒な気がします。以下のようにnew File(System.getProperty("user.home")+"/Desktop")
とデスクトップを決め打ちにしてノードを作ってしまうのが簡単かもしれません。 -- aterai
-
#spanend
#spanadd
final FileSystemView fileSystemView = FileSystemView.getFileSystemView();
#spanend
#spanadd
DefaultMutableTreeNode root = new DefaultMutableTreeNode();
#spanend
#spanadd
final DefaultTreeModel treeModel = new DefaultTreeModel(root);
#spanend
#spanadd
File desktopFile = new File(System.getProperty("user.home")+"/Desktop");
#spanend
#spanadd
DefaultMutableTreeNode desktop = new DefaultMutableTreeNode(new CheckBoxNode(desktopFile, Status.DESELECTED));
#spanend
#spanadd
root.add(desktop);
#spanend
#spanadd
for (File file: fileSystemView.getFiles(desktopFile, true)) {
#spanend
if (file.isDirectory()) {
desktop.add(new DefaultMutableTreeNode(new CheckBoxNode(file, Status.DESELECTED)));
}
#spanadd
}
#spanend
#spanadd
for (File fileSystemRoot: Arrays.asList(new File("X:/"), new File("Y:/"))) {
#spanend
DefaultMutableTreeNode node = new DefaultMutableTreeNode(new CheckBoxNode(fileSystemRoot, Status.DESELECTED));
desktop.add(node);
for (File file: fileSystemView.getFiles(fileSystemRoot, true)) {
System.out.println(file.getAbsolutePath());
if (file.isDirectory()) {
node.add(new DefaultMutableTreeNode(new CheckBoxNode(file, Status.DESELECTED)));
}
}
#spanadd
}
#spanend
#spanadd
treeModel.addTreeModelListener(new CheckBoxStatusUpdateListener());
#spanend
#spanadd
- いつも勉強させていただいております。チェックしたファイルまたはフォルダーのチェックマークの外し方を教えていただけませんか? -- Tiger
- こんばんは。マウスを使わずにチェックを外したいということですよね。このサンプルの場合、
MutableTreeNode#setUserObject(...)
でチェックを外したnew CheckBoxNode(node.file, Status.DESELECTED)
を設定し、そのあとDefaultTreeModel#nodeChanged(...)メソッドを呼べばいいと思います。 -- aterai
- こんばんは。マウスを使わずにチェックを外したいということですよね。このサンプルの場合、
#spanend
#spanadd
//例えば、すべてのチェックを外す場合...
#spanend
#spanadd
private static void deselectedAll(DefaultTreeModel model, TreePath path) {
#spanend
Object o = path.getLastPathComponent();
if (!(o instanceof DefaultMutableTreeNode)) {
return;
}
DefaultMutableTreeNode node = (DefaultMutableTreeNode) o;
o = node.getUserObject();
if (!(o instanceof CheckBoxNode)) {
return;
}
CheckBoxNode check = (CheckBoxNode) o;
if (check.status == Status.SELECTED) {
node.setUserObject(new CheckBoxNode(check.file, Status.DESELECTED));
model.nodeChanged(node);
//or: model.valueForPathChanged(path, new CheckBoxNode(check.file, Status.DESELECTED));
} else if (!node.isLeaf()) {
// Java 9: Enumeration<TreeNode> e = node.children();
Enumeration<?> e = node.children();
while (e.hasMoreElements()) {
deselectedAll(model, path.pathByAddingChild(e.nextElement()));
}
}
#spanadd
}
#spanend
#spanadd