我有一个JTree,其节点由JLabel和JComboBox组成。我想要的是,当单击时,选定的JComboBox会展开,但似乎第一次单击是JTree本身(?)占用的,因此我必须单击两次。
这是我的代码:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.plaf.ColorUIResource;
import javax.swing.tree.*;
public class JComboBoxJTree extends JPanel {
final JTree entitiesTree;
public JComboBoxJTree() {
entitiesTree = createTree();
JScrollPane entitiesTreeScrollPane = new JScrollPane(entitiesTree);
this.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 1;
c.weightx = 1.0;
c.weighty = 1.0;
c.fill = GridBagConstraints.BOTH;
c.insets = new Insets(0, 5, 0, 5);
this.add(entitiesTreeScrollPane, c);
entitiesTree.setBackground(Color.black);
entitiesTreeScrollPane.setBackground(Color.black);
this.setBackground(Color.black);
}
public static void main(String[] args) {
try {
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
UIManager.getLookAndFeelDefaults().put("Button.background",
Color.BLACK);
UIManager.getLookAndFeelDefaults().put(
"TextField.background", Color.BLACK);
UIManager.getLookAndFeelDefaults().put(
"ComboBox.background", Color.BLACK);
UIManager.getLookAndFeelDefaults().put(
"TextField.foreground", Color.WHITE);
UIManager.getLookAndFeelDefaults().put("List.foreground",
Color.WHITE);
UIManager.getLookAndFeelDefaults().put("List.background",
Color.BLACK);
UIManager.put("textForeground", Color.white);
UIManager.put("info", new ColorUIResource(Color.BLACK));
UIManager.put("ScrollPane.background", Color.black);
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
JComboBoxJTree dialog = new JComboBoxJTree();
JDialog jd = new JDialog();
jd.add(dialog);
jd.pack();
jd.setVisible(true);
}
private static JTree createTree() {
DefaultMutableTreeNode root = new DefaultMutableTreeNode(new Node(
"Plugins"));
root.add(new DefaultMutableTreeNode(new Node("Plugin 1", "Running",
"Paused", "Stopped")));
root.add(new DefaultMutableTreeNode(new Node("Plugin 2", "Running",
"Paused", "Stopped")));
DefaultMutableTreeNode leaf = new DefaultMutableTreeNode(new Node(
"Plugin 3", "Running", "Paused", "Stopped"));
root.add(leaf);
leaf.add(new DefaultMutableTreeNode(new Node("Plugin 3A", "Running",
"Paused", "Stopped")));
leaf.add(new DefaultMutableTreeNode(new Node("Plugin 3B", "Running",
"Paused", "Stopped")));
JTree tree = new JTree(root);
RendererDispatcher rendererDispatcher = new RendererDispatcher(tree);
RendererDispatcher editorDispatcher = new RendererDispatcher(tree);
tree.setCellRenderer(rendererDispatcher);
tree.setCellEditor(editorDispatcher);
tree.setEditable(true);
return tree;
}
}
class Node {
final String name;
final String[] plugins;
boolean selected;
int selectedPluginIndex;
public Node(String name, String... plugins) {
this.name = name;
this.selected = false;
this.plugins = plugins;
if (plugins == null) {
this.selectedPluginIndex = -1;
} else {
this.selectedPluginIndex = 0;
}
}
public boolean isSelected() {
return selected;
}
public void setSelected(boolean selected) {
this.selected = selected;
}
public String toString() {
return name;
}
public int getSelectedPluginIndex() {
return selectedPluginIndex;
}
public void setSelectedPluginIndex(int selectedPluginIndex) {
this.selectedPluginIndex = selectedPluginIndex;
}
public String[] getPlugins() {
return plugins;
}
}
class RendererDispatcher extends AbstractCellEditor implements
TreeCellRenderer, TreeCellEditor {
final static Color selectionForeground = UIManager
.getColor("Tree.selectionForeground");
final static Color selectionBackground = UIManager
.getColor("Tree.selectionBackground");
final static Color textForeground = UIManager
.getColor("Tree.textForeground");
final static Color textBackground = UIManager
.getColor("Tree.textBackground");
final JTree tree;
final DefaultComboBoxModel comboBoxModel = new DefaultComboBoxModel();
final JPanel panel = new JPanel();
JLabel pluginName = new JLabel();
final JComboBox comboBox = new JComboBox(comboBoxModel);
final JComponent components[] = { panel, pluginName, comboBox };
public RendererDispatcher(JTree tree) {
this.tree = tree;
Font font = UIManager.getFont("Tree.font");
panel.add(pluginName);
setForeground(Color.white);
setBackground(Color.BLACK);
if (font != null) {
this.setFont(font);
}
}
public Component getTreeCellRendererComponent(JTree tree, Object value,
boolean selected, boolean expanded, boolean leaf, int row,
boolean hasFocus) {
final Node node = extractNode(value);
this.setContents(node);
this.setEnabled(tree.isEnabled());
this.setForeground(Color.white);
this.setBackground(Color.BLACK);
return this.getComponent();
}
public Component getTreeCellEditorComponent(JTree tree, Object value,
boolean selected, boolean expanded, boolean leaf, int row) {
return getTreeCellRendererComponent(tree, value, true, expanded, leaf,
row, true);
}
public Object getCellEditorValue() {
return this.getContents();
}
public boolean isCellEditable(final EventObject event) {
if (!(event instanceof MouseEvent)) {
return false;
}
final MouseEvent mouseEvent = (MouseEvent) event;
final TreePath path = tree.getPathForLocation(mouseEvent.getX(),
mouseEvent.getY());
if (path == null) {
return false;
}
Object node = path.getLastPathComponent();
if (node == null || (!(node instanceof DefaultMutableTreeNode))) {
return false;
}
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) node;
Object userObject = treeNode.getUserObject();
return (userObject instanceof Node);
}
private static Node extractNode(Object value) {
if ((value != null) && (value instanceof DefaultMutableTreeNode)) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
Object userObject = node.getUserObject();
if ((userObject != null) && (userObject instanceof Node)) {
return (Node) userObject;
}
}
return null;
}
public void setForeground(final Color foreground) {
for (int i = 0; i < components.length; i++) {
components[i].setForeground(foreground);
}
}
public void setBackground(final Color background) {
for (int i = 0; i < components.length; i++) {
components[i].setBackground(background);
}
}
public void setFont(final Font font) {
for (int i = 0; i < components.length; i++) {
components[i].setFont(font);
}
}
public void setEnabled(final boolean enabled) {
for (int i = 0; i < components.length; i++) {
components[i].setEnabled(enabled);
}
}
public void setContents(Node node) {
// checkBox.setText(node.toString());
pluginName.setText(node.toString());
comboBoxModel.removeAllElements();
if (node.getPlugins().length > 0) {
panel.add(comboBox);
for (int i = 0; i < node.getPlugins().length; i++) {
comboBoxModel.addElement(node.getPlugins()[i]);
}
} else {
panel.remove(comboBox);
}
}
public Object getContents() {
String title = pluginName.getText();
String[] plugins = new String[comboBoxModel.getSize()];
for (int i = 0; i < comboBoxModel.getSize(); i++) {
plugins[i] = comboBoxModel.getElementAt(i).toString();
}
Node node = new Node(title, plugins);
node.setSelectedPluginIndex(comboBoxModel.getIndexOf(comboBoxModel
.getSelectedItem()));
return node;
}
public Component getComponent() {
return panel;
}
}
Java 1.8.0
:Bug ID:JDK-8023474第一次按下鼠标并没有开始在JTree中进行编辑 import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.tree.*;
public class JComboBoxJTree2 {
public JComponent makeUI() {
String[] m = {"Running", "Paused", "Stopped"};
DefaultMutableTreeNode root = new DefaultMutableTreeNode(new Node("Plugins"));
root.add(new DefaultMutableTreeNode(new Node("Plugin 1", m)));
root.add(new DefaultMutableTreeNode(new Node("Plugin 2", m)));
DefaultMutableTreeNode leaf = new DefaultMutableTreeNode(new Node("Plugin 3", m));
root.add(leaf);
leaf.add(new DefaultMutableTreeNode(new Node("Plugin 3A", m)));
leaf.add(new DefaultMutableTreeNode(new Node("Plugin 3B", m)));
JTree tree = new JTree(root);
RendererDispatcher rendererDispatcher = new RendererDispatcher(new JComboBox<String>());
RendererDispatcher editorDispatcher = new RendererDispatcher(new JComboBox<String>());
tree.setCellRenderer(rendererDispatcher);
tree.setCellEditor(editorDispatcher);
tree.setEditable(true);
return new JScrollPane(tree);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new JComboBoxJTree2().makeUI());
f.setSize(320, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
class Node {
private final String name;
private final String[] plugins;
private int selectedPluginIndex;
public Node(String name, String... plugins) {
this.name = name;
this.plugins = plugins;
}
public String toString() {
return name;
}
public int getSelectedPluginIndex() {
return selectedPluginIndex;
}
public void setSelectedPluginIndex(int selectedPluginIndex) {
this.selectedPluginIndex = selectedPluginIndex;
}
public String[] getPlugins() {
return plugins;
}
}
class RendererDispatcher extends DefaultCellEditor implements TreeCellRenderer {
private final JPanel panel = new JPanel();
private final JLabel pluginName = new JLabel();
private final JComboBox<String> comboBox;
private Node node;
public RendererDispatcher(JComboBox<String> comboBox) {
super(comboBox);
this.comboBox = comboBox;
panel.setOpaque(false);
panel.add(pluginName);
panel.add(comboBox);
}
@Override public Component getTreeCellRendererComponent(
JTree tree, Object value, boolean selected, boolean expanded,
boolean leaf, int row, boolean hasFocus) {
Node node = extractNode(value);
setContents(node);
return panel;
}
@Override public Component getTreeCellEditorComponent(
JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row) {
Node node = extractNode(value);
setContents(node);
this.node = node;
return panel;
}
@Override public Object getCellEditorValue() {
Object o = super.getCellEditorValue();
DefaultComboBoxModel<String> m = (DefaultComboBoxModel<String>) comboBox.getModel();
Node n = new Node(pluginName.getText(), node.getPlugins());
n.setSelectedPluginIndex(m.getIndexOf(o));
return n;
}
@Override public boolean isCellEditable(final EventObject event) {
Object source = event.getSource();
if (!(source instanceof JTree) || !(event instanceof MouseEvent)) {
return false;
}
final JTree tree = (JTree) source;
final MouseEvent mouseEvent = (MouseEvent) event;
final TreePath path = tree.getPathForLocation(mouseEvent.getX(), mouseEvent.getY());
if (path == null) {
return false;
}
Object node = path.getLastPathComponent();
if (node == null || !(node instanceof DefaultMutableTreeNode)) {
return false;
}
Rectangle r = tree.getPathBounds(path);
if (r == null) {
return false;
}
Dimension d = panel.getPreferredSize();
r.setSize(new Dimension(d.width, r.height));
if (r.contains(mouseEvent.getX(), mouseEvent.getY())) {
EventQueue.invokeLater(new Runnable() {
@Override public void run() {
Point pt = SwingUtilities.convertPoint(tree, mouseEvent.getPoint(), panel);
//System.out.println(pt);
Object o = SwingUtilities.getDeepestComponentAt(panel, pt.x, pt.y);
if (o instanceof JComboBox) {
comboBox.showPopup();
} else if (o instanceof Component) {
Object oo = SwingUtilities.getAncestorOfClass(JComboBox.class, (Component) o);
if (oo instanceof JComboBox) {
comboBox.showPopup();
}
}
}
});
return true;
}
return delegate.isCellEditable(event);
}
private static Node extractNode(Object value) {
if (value instanceof DefaultMutableTreeNode) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
Object userObject = node.getUserObject();
if (userObject instanceof Node) {
return (Node) userObject;
}
}
return null;
}
private void setContents(Node node) {
if (node == null) {
return;
}
pluginName.setText(node.toString());
DefaultComboBoxModel<String> model = (DefaultComboBoxModel<String>) comboBox.getModel();
model.removeAllElements();
if (node.getPlugins().length > 0) {
panel.add(comboBox);
for (String s : node.getPlugins()) {
model.addElement(s);
}
comboBox.setSelectedIndex(node.getSelectedPluginIndex());
} else {
panel.remove(comboBox);
}
}
}
我正在开发一个使用JTree的java应用程序。我想归档的是,当我点击一个已经被选中的节点时,它会被取消选中。 我目前的解决方案是向jtree添加鼠标侦听器和树选择侦听器。但问题是,valueChanged只有在选择发生更改时才会被调用(而不是在两次选择同一节点时)。为了解决这个问题,我添加了一个布尔值,它指示是否第一次单击了节点,然后我在MouseRelease函数中处理取消选择。这是可行的,但
我知道如何通过鼠标左键点击所选项目来获取项目。我可以使用。 但我需要用鼠标右键点击项目。显示与单击的项目相关的弹出菜单。我试过这个: 但如果用户用右键点击该项,则会出现问题。右键单击不选择项目。如何按事件坐标选择项目或如何解决此问题?主要我需要得到的对象是点击没有选择项目,如果可能的话。
我有一个JTree,我可以(ctrl)选择多个节点。当我右键点击时,我会弹出一个窗口,在那里我可以选择“刷新”。(本网站上还有其他问题解释如何做到这一点) 问题是,当我选择多个节点并右键单击时,只有右键单击的节点被选中,其他节点被取消选择。 例如,我想选择3个节点(叶),右键单击,选择刷新,仍然选择这3个节点。 有什么建议吗?谢谢。 例子:
问题内容: 我有一个对话框,其中JTree中的每个条目在不同的面板中都有其相应的选项,当选择更改时会更新该面板。如果将其中一项的选项设置为无效状态,则当用户尝试更改树中的其他项时,我希望出现一个错误对话框,并且选择保持不变。 我尝试使用JTree上的valueChangeListener来执行此操作,但是目前如果有错误,则必须让valueChanged方法将“ setSelectionRow”调用
问题内容: 使用Informix,我创建了一个临时表,试图从select语句中填充它。此后,我想进行更新,以在临时表中填充更多字段。 所以我正在做类似的事情; 但是您不能选择null。 例如; 可以,但是 失败! (不要让我开始为什么我不能不指定表就只做“选择当前”之类的SQL Server!) 问题答案: 此页面说您不能执行此操作的原因是因为“ NULL”没有类型。因此,解决方法是创建一个仅以所
问题内容: 我需要将复选框添加到JTree。自定义TreeCellRenderer / TreeCellEditor似乎是正确的方法。到目前为止,我在此网页中使用了CheckBoxNodeRenderer方法。除了两件事,它可以正常工作: 复选框上方+下方有额外的空格;我想使其与常规JTree相同。 我想区分单击复选框本身(应尝试切换复选框)和单击与复选框相关联的文本(应允许事件侦听器将此解释为单