2

ノードに複数のコンポーネントがある JTree を作成しようとしています。JCheckBox を保持する JPanel、その後に JLabel、JComboBox が続きます。実行したい場合は、下部にコードを添付しました。幸い、JTree はコンポーネントを正しくレンダリングします。ただし、JComboBox をクリックすると、ノードが消えます。JCheckBox をクリックすると、問題なく動作します。TreeCellEditor の設定方法に問題があるようです。この問題を解決するにはどうすればよいですか? JTree の機能を超えていますか?

以下に投稿したコードの概要を簡単に説明します。

  • このクラスEntityListDialogは、ユーザー インターフェイスを作成するだけです。方法以外を理解しても役に立ちませんcreateTree
  • NodeJTree の各ノードに関する情報を保持するデータ構造です。すべてNodeの s にはnamesamplesありますが、null または空の配列の場合があります。EntityListDialogこれは、のcreateTreeメソッドを見れば明らかです。はnameJCheckBox のテキストとして使用されます。空でない場合samplesは、JCheckBox の内容として使用されます。
  • NodeWithSamplesRenderers が空でないNodes をレンダリングします。sampleJCheckBox と JComboBox で構成される JPanel で複雑なユーザー インターフェイスを作成します。
  • NodeWithoutSamplesRenderersamplesが空の場合は JCheckBox のみを作成します。
  • RendererDispatcherNodeWithSamplesRendererまたはを使用するかどうかを決定しますNodeWithoutSamplesRendererNodeこれは、空でないsamplesメンバーがあるかどうかに完全に依存します。これは基本的に、NodeWith*SamplesRendererを JTree にプラグインするための手段として機能します。

コード リスト:

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;
    }
}
4

2 に答える 2

4

JTreeビアに伝えるのを忘れたJTree.cancelEditing()JTree.stopEditing()、編集セッションが終了しました。次に、JComboBox編集セッションでのみ表示する必要があります。JLabel現在の選択の標準レンダリングに法線を使用します。あなたの例は冗長すぎて実際に私の要点を示すことができないため、コードは提供しません。

編集:さらに、編集とレンダリングに同じコンポーネントを使用することは非常に悪い考えであることを指摘したいと思います。考えてみましょう。

  1. ノードの編集を開始します。
  2. 下のJComboBoxノードの上に が開きます。
  3. 以下のノードは再レンダリングする必要があります。
  4. 現在編集に使用されているものとまったく同じオブジェクトを使用すると、レンダリングのために削除されます。
  5. 説明JTreeされている問題を示しています。

TreeCellRenderer最終的には、を から分離した方がよいでしょうTreeCellEditor

于 2010-05-12T15:18:26.773 に答える
2
RendererDispatcher rendererDispatcher = new RendererDispatcher(tree);
RendererDispatcher editorDispatcher = new RendererDispatcher(tree);
tree.setCellRenderer(rendererDispatcher);
tree.setCellEditor(editorDispatcher);
于 2010-10-17T19:28:31.553 に答える