gpt4 book ai didi

java - JTree 节点渲染器和节点编辑器中的多个组件

转载 作者:行者123 更新时间:2023-11-29 08:18:19 25 4
gpt4 key购买 nike

我正在尝试创建一个 JTree,其中节点具有多个组件:一个包含 JCheckBox 的 JPanel,后跟一个 JLabel,然后是一个 JComboBox。如果有人想运行它,我已在底部附加了代码。幸运的是,JTree 正确地呈现了组件。但是,当我单击 JComboBox 时,该节点消失了;如果我单击 JCheckBox,它工作正常。看来我对 TreeCellEditor 的设置方式做了一些错误。我该如何解决这个问题?我是否超出了 JTree 的能力?

这是我在下面发布的代码的快速概述。

  • EntityListDialog 类仅创建用户界面。除了 createTree 方法之外,理解它没有任何用处。
  • Node 是保存有关 JTree 中每个节点的信息的数据结构。所有Node都有一个name,但samples可能为null或空数组。通过查看 EntityListDialogcreateTree 方法,这一点应该很明显。 name 用作 JCheckBox 的文本。如果 samples 非空,则将其用作 JCheckBox 的内容。
  • NodeWithSamplesRenderer 渲染 sample 非空的 Node。它使用由 JCheckBox 和 JComboBox 组成的 JPanel 创建复杂的用户界面。
  • NodeWithoutSamplesRenderersamples 为空时仅创建一个 JCheckBox。
  • RendererDispatcher 决定是使用 NodeWithSamplesRenderer 还是 NodeWithoutSamplesRenderer。这完全取决于 Node 是否有非空 samples 成员。它本质上是作为 NodeWith*SamplesRenderer 插入 JTree 的一种手段。

代码 list :

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.tree.*;

public class EntityListDialog {

final JDialog dialog;
final JTree entitiesTree;

public EntityListDialog() {
dialog = new JDialog((Frame) null, "Test");
entitiesTree = createTree();
JScrollPane entitiesTreeScrollPane = new JScrollPane(entitiesTree);
JCheckBox pathwaysCheckBox = new JCheckBox("Do additional searches");
JButton sendButton = new JButton("Send");
JButton cancelButton = new JButton("Cancel");
JButton selectAllButton = new JButton("All");
JButton deselectAllButton = new JButton("None");

dialog.getContentPane().setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();

JPanel selectPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
selectPanel.add(new JLabel("Select: "));
selectPanel.add(selectAllButton);
selectPanel.add(deselectAllButton);
c.gridx = 0;
c.gridy = 0;
c.weightx = 1.0;
c.weighty = 0.0;
c.fill = GridBagConstraints.HORIZONTAL;
dialog.getContentPane().add(selectPanel, c);

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);
dialog.getContentPane().add(entitiesTreeScrollPane, c);

c.gridx = 0;
c.gridy = 2;
c.weightx = 1.0;
c.weighty = 0.0;
c.insets = new Insets(0, 0, 0, 0);
c.fill = GridBagConstraints.HORIZONTAL;
dialog.getContentPane().add(pathwaysCheckBox, c);

JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
buttonsPanel.add(sendButton);
buttonsPanel.add(cancelButton);
c.gridx = 0;
c.gridy = 3;
c.weightx = 1.0;
c.weighty = 0.0;
c.fill = GridBagConstraints.HORIZONTAL;
dialog.getContentPane().add(buttonsPanel, c);

dialog.pack();
dialog.setVisible(true);
}

public static void main(String[] args) {
EntityListDialog dialog = new EntityListDialog();
}

private static JTree createTree() {
DefaultMutableTreeNode root = new DefaultMutableTreeNode(
new Node("All Entities"));
root.add(new DefaultMutableTreeNode(
new Node("Entity 1", "Sample A", "Sample B", "Sample C")));
root.add(new DefaultMutableTreeNode(
new Node("Entity 2", "Sample D", "Sample E", "Sample F")));
root.add(new DefaultMutableTreeNode(
new Node("Entity 3", "Sample G", "Sample H", "Sample I")));
JTree tree = new JTree(root);
RendererDispatcher rendererDispatcher = new RendererDispatcher(tree);
tree.setCellRenderer(rendererDispatcher);
tree.setCellEditor(rendererDispatcher);
tree.setEditable(true);
return tree;
}
}

class Node {

final String name;
final String[] samples;
boolean selected;
int selectedSampleIndex;

public Node(String name, String... samples) {
this.name = name;
this.selected = false;
this.samples = samples;
if (samples == null) {
this.selectedSampleIndex = -1;
} else {
this.selectedSampleIndex = 0;
}
}

public boolean isSelected() {
return selected;
}

public void setSelected(boolean selected) {
this.selected = selected;
}

public String toString() {
return name;
}

public int getSelectedSampleIndex() {
return selectedSampleIndex;
}

public void setSelectedSampleIndex(int selectedSampleIndex) {
this.selectedSampleIndex = selectedSampleIndex;
}

public String[] getSamples() {
return samples;
}
}

interface Renderer {

public void setForeground(final Color foreground);

public void setBackground(final Color background);

public void setFont(final Font font);

public void setEnabled(final boolean enabled);

public Component getComponent();

public Object getContents();
}

class NodeWithSamplesRenderer implements Renderer {

final DefaultComboBoxModel comboBoxModel = new DefaultComboBoxModel();
final JPanel panel = new JPanel();
final JCheckBox checkBox = new JCheckBox();
final JLabel label = new JLabel(" Samples: ");
final JComboBox comboBox = new JComboBox(comboBoxModel);
final JComponent components[] = {panel, checkBox, comboBox, label};

public NodeWithSamplesRenderer() {
Boolean drawFocus =
(Boolean) UIManager.get("Tree.drawsFocusBorderAroundIcon");
if (drawFocus != null) {
checkBox.setFocusPainted(drawFocus.booleanValue());
}
for (int i = 0; i < components.length; i++) {
components[i].setOpaque(true);
}

panel.add(checkBox);
panel.add(label);
panel.add(comboBox);
}

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());

comboBoxModel.removeAllElements();
for (int i = 0; i < node.getSamples().length; i++) {
comboBoxModel.addElement(node.getSamples()[i]);
}
}

public Object getContents() {
String title = checkBox.getText();
String[] samples = new String[comboBoxModel.getSize()];
for (int i = 0; i < comboBoxModel.getSize(); i++) {
samples[i] = comboBoxModel.getElementAt(i).toString();
}
Node node = new Node(title, samples);
node.setSelected(checkBox.isSelected());
node.setSelectedSampleIndex(comboBoxModel.getIndexOf(
comboBoxModel.getSelectedItem()));
return node;
}

public Component getComponent() {
return panel;
}
}

class NodeWithoutSamplesRenderer implements Renderer {

final JCheckBox checkBox = new JCheckBox();

public NodeWithoutSamplesRenderer() {
Boolean drawFocus =
(Boolean) UIManager.get("Tree.drawsFocusBorderAroundIcon");
if (drawFocus != null) {
checkBox.setFocusPainted(drawFocus.booleanValue());
}
}

public void setForeground(final Color foreground) {
checkBox.setForeground(foreground);
}

public void setBackground(final Color background) {
checkBox.setBackground(background);
}

public void setFont(final Font font) {
checkBox.setFont(font);
}

public void setEnabled(final boolean enabled) {
checkBox.setEnabled(enabled);
}

public void setContents(Node node) {
checkBox.setText(node.toString());
}

public Object getContents() {
String title = checkBox.getText();
Node node = new Node(title);
node.setSelected(checkBox.isSelected());
return node;
}

public Component getComponent() {
return checkBox;
}
}

class NoNodeRenderer implements Renderer {

final JLabel label = new JLabel();

public void setForeground(final Color foreground) {
label.setForeground(foreground);
}

public void setBackground(final Color background) {
label.setBackground(background);
}

public void setFont(final Font font) {
label.setFont(font);
}

public void setEnabled(final boolean enabled) {
label.setEnabled(enabled);
}

public void setContents(String text) {
label.setText(text);
}

public Object getContents() {
return label.getText();
}

public Component getComponent() {
return label;
}
}

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 NodeWithSamplesRenderer nodeWithSamplesRenderer =
new NodeWithSamplesRenderer();
final NodeWithoutSamplesRenderer nodeWithoutSamplesRenderer =
new NodeWithoutSamplesRenderer();
final NoNodeRenderer noNodeRenderer = new NoNodeRenderer();
final Renderer[] renderers = {
nodeWithSamplesRenderer, nodeWithoutSamplesRenderer, noNodeRenderer
};
Renderer renderer = null;

public RendererDispatcher(JTree tree) {
this.tree = tree;
Font font = UIManager.getFont("Tree.font");
if (font != null) {
for (int i = 0; i < renderers.length; i++) {
renderers[i].setFont(font);
}
}
}

public Component getTreeCellRendererComponent(JTree tree,
Object value, boolean selected, boolean expanded,
boolean leaf, int row, boolean hasFocus) {
final Node node = extractNode(value);
if (node == null) {
renderer = noNodeRenderer;
noNodeRenderer.setContents(tree.convertValueToText(
value, selected, expanded, leaf, row, false));
} else {
if (node.getSamples() == null || node.getSamples().length == 0) {
renderer = nodeWithoutSamplesRenderer;
nodeWithoutSamplesRenderer.setContents(node);
} else {
renderer = nodeWithSamplesRenderer;
nodeWithSamplesRenderer.setContents(node);
}
}

renderer.setEnabled(tree.isEnabled());
if (selected) {
renderer.setForeground(selectionForeground);
renderer.setBackground(selectionBackground);
} else {
renderer.setForeground(textForeground);
renderer.setBackground(textBackground);
}

renderer.getComponent().repaint();
renderer.getComponent().invalidate();
renderer.getComponent().validate();

return renderer.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 renderer.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;
}
}

最佳答案

您忘记通过 JTree.cancelEditing()JTree.stopEditing() 告诉 JTree 编辑 session 已结束。其次,您应该只在编辑 session 中显示 JComboBox。使用普通的 JLabel 来标准呈现当前选择。我不会给你代码,因为你的例子太冗长,无法真正表达我的观点。

编辑:此外,我想指出,使用相同的组件进行编辑和渲染是一个非常糟糕的主意。我们想一下吧。

  1. 您开始编辑节点。
  2. JComboBox 在下面的节点上方打开。
  3. 下面的节点必须重新渲染。
  4. 现在将使用当前用于编辑的完全相同的对象进行渲染。
  5. 您的 JTree 显示了所描述的问题。

最后,如果将 TreeCellRendererTreeCellEditor 分开,效果会更好。

关于java - JTree 节点渲染器和节点编辑器中的多个组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2539960/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com