编辑JTree中返回的java意外值
在下面的代码中,有一个示例JTree
,每行有两个JToggleButtons
,一个JLabel
都包含在Holder (subclass of JPanel)
中
这个JTree
上的叶子可能如下所示
当其中一个JToggleButtons
被点击时,点击的切换按钮应该会改变颜色。然而,输出是非常不同的,如下所示
为什么会发生这种情况?我如何解决这个问题
注意:这个返回值可以在public component getTreeCellEditorComponent(...)
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
import javax.swing.tree.*;
import javax.swing.table.*;
import javax.swing.plaf.basic.*;
import javax.swing.plaf.metal.*;
@SuppressWarnings("serial")
public class DirectoryExplorer extends JFrame {
private DirectoryExplorer() {
super("Directory Explorer");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new GridLayout(1, 1));
createPanel();
setSize(800,600);
setVisible(true);
}
private void createPanel() {
DefaultMutableTreeNode colors = new DefaultMutableTreeNode("Colours");
colors.add(new DefaultMutableTreeNode("Red"));
colors.add(new DefaultMutableTreeNode("Green"));
colors.add(new DefaultMutableTreeNode("Blue"));
DefaultMutableTreeNode falvors = new DefaultMutableTreeNode("Flavours");
falvors.add(new DefaultMutableTreeNode("Toffee"));
falvors.add(new DefaultMutableTreeNode("Fudge"));
falvors.add(new DefaultMutableTreeNode("Chocolate"));
DefaultMutableTreeNode root = new DefaultMutableTreeNode("root");
root.add(colors);
root.add(falvors);
root.add(new DefaultMutableTreeNode("Leafy"));
JPanel panel = new JPanel(new GridLayout(1, 1));
JTree tree = new JTree(root);
FileNameRenderer fileRender = new FileNameRenderer();
tree.setCellRenderer(fileRender);
tree.setCellEditor(new CheckBoxNodeEditor(tree));
tree.setEditable(true);
tree.setShowsRootHandles(true);
panel.add(new JScrollPane(tree));
getContentPane().add(panel);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> new DirectoryExplorer());
}
private class FileNameRenderer extends DefaultTreeCellRenderer {
private DefaultChkBx def = new DefaultChkBx();
private FavouriteChkBx fav = new FavouriteChkBx();
protected DefaultChkBx getDefBut() {
return def;
}
protected FavouriteChkBx getFavBut() {
return fav;
}
@Override
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
JComponent c = (JComponent) super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
return new Holder((JLabel) c, def, fav);
}
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus, boolean defSel, boolean favSel) {
JComponent c = (JComponent) super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
def.setSelected(defSel);
fav.setSelected(favSel);
return new Holder((JLabel) c, def, fav);
}
}
private class CheckBoxNodeEditor extends AbstractCellEditor implements TreeCellEditor {
FileNameRenderer renderer = new FileNameRenderer();
ChangeEvent changeEvent = null;
JTree t;
TreePath path;
DefaultChkBx def = renderer.getDefBut();
FavouriteChkBx fav = renderer.getFavBut();
public CheckBoxNodeEditor(JTree tree) {
t = tree;
}
public Object getCellEditorValue() {
def = renderer.getDefBut();
fav = renderer.getFavBut();
def.setSelected(def.isSelected());
fav.setSelected(fav.isSelected());
Holder checkBoxNode = new Holder(new JLabel((((DefaultMutableTreeNode) path.getLastPathComponent()).getUserObject().toString())), def, fav);
return checkBoxNode;
}
public boolean isCellEditable(EventObject event) {
if(event instanceof MouseEvent) {
MouseEvent mouseEvent = (MouseEvent) event;
path = t.getPathForLocation(mouseEvent.getX(), mouseEvent.getY());
if (path != null) {
Object node = path.getLastPathComponent();
if ((node != null) && (node instanceof DefaultMutableTreeNode)) {
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) node;
Object userObject = treeNode.getUserObject();
return (userObject instanceof String);
}
}
}
return false;
}
public Component getTreeCellEditorComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row) {
Component editor = renderer.getTreeCellRendererComponent(tree, value, true, expanded, leaf, row, true);
ItemListener itemListener = new ItemListener() {
public void itemStateChanged(ItemEvent itemEvent) {
if (stopCellEditing())
fireEditingStopped();
}
};
if (editor instanceof Holder) {
for(Component c : ((Holder) editor).getComponents()) {
if(c instanceof DefaultChkBx)
((DefaultChkBx) c).addItemListener(itemListener);
else if(c instanceof FavouriteChkBx)
((FavouriteChkBx) c).addItemListener(itemListener);
}
}
return editor;
}
}
private class Holder extends JPanel {
public Holder(Component c, DefaultChkBx def, FavouriteChkBx fav) {
setLayout(new GridBagLayout());
setBackground(Color.BLACK);
setOpaque(false);
addComponents(c, def, fav);
}
private void addComponents(Component c, DefaultChkBx def, FavouriteChkBx fav) {
GridBagConstraints gBC = new GridBagConstraints();
gBC.insets = new Insets(0, 0, 0, 5);
add(c, gBC);
gBC.insets = new Insets(0, 0, 0, 0);
add(def, gBC);
add(fav, gBC);
}
}
private class DefaultChkBx extends JToggleButton {
public DefaultChkBx() {
setUI(new MetalToggleButtonUI() {
@Override
protected Color getSelectColor() {
return new Color(242, 0, 255);
}
});
setBorder(null);
setForeground(Color.GRAY);
setText("Default");
setFocusPainted(false);
}
}
private class FavouriteChkBx extends JToggleButton {
public FavouriteChkBx() {
setUI(new MetalToggleButtonUI() {
@Override
protected Color getSelectColor() {
return Color.RED;
}
});
setBorder(null);
setForeground(Color.GRAY);
setText("Favourite");
setFocusPainted(false);
}
}
}
# 1 楼答案
在
CheckBoxNodeEditor
中,您的getCellEditorValue()
应该返回已编辑对象的值(通常是叶中显示的String
对象)相反,您的方法返回
Holder
的实例。在这个对象上调用toString()
方法,并由树显示(这是“DirectoryExplorer$Holder[…”展示你正在看到的东西)首先,您可以从这个方法返回一个简单的字符串(比如“Leafy”)