简体   繁体   English

JTree中的JTextField-使其可编辑

[英]JTextField in JTree - make it editable

does anybody have a sample code for a tree with check boxes and text fields? 有人有带有复选框和文本字段的树的示例代码吗? Because now I have a code for check box (only) based tree. 因为现在我有一个代码用于基于复选框的树(仅)。 I tried to implement also text fields in the tree (with Jlabels ). 我还尝试在树中实现文本字段(使用Jlabels )。 But I get stucked and I am really confused. 但是我被困住了,我真的很困惑。 I can't get any further and I hoped that you can help me. 我再无所求,希望您能帮助我。

The issue is. 问题是。 I cant modify the text of JTextFields. 我无法修改JTextFields的文本。 The modification doesnt get saved. 修改不会保存。 And I do not know how to add a JLabel in the same line of the JTextField 而且我不知道如何在JTextField的同一行中添加JLabel

Root
|
|- Node 1
    | - [-] Activate simulation
    | - [100] Iterations
|- Node 2
    | - [x] Activate simulation
    | - [2000] Iterations

package view;
import javax.swing.BoxLayout;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JTextField;
import org.jdesktop.swingx.JXTreeTable;
import org.jdesktop.swingx.treetable.AbstractTreeTableModel;
import org.jdesktop.swingx.treetable.DefaultMutableTreeTableNode;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.event.DocumentListener;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.util.EventObject;
import java.util.Vector;

import javax.swing.AbstractCellEditor;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.DocumentEvent;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeCellEditor;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreePath;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

public class test {

  private Document dom;

  private void parseXmlFile(String xmlpath){
        //get the factory
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

        try {

            //Using factory get an instance of document builder
            DocumentBuilder db = dbf.newDocumentBuilder();

            //parse using builder to get DOM representation of the XML file
            dom = db.parse(xmlpath);


        }catch(ParserConfigurationException pce) {
            pce.printStackTrace();
        }catch(SAXException se) {
            se.printStackTrace();
        }catch(IOException ioe) {
            ioe.printStackTrace();
        }
  } 

  public static void main(String args[]) {
    JFrame frame = new JFrame("CheckBox Tree");

    CheckBoxNode accessibilityOptions[] = {
        new CheckBoxNode(
            "Move system caret with focus/selection changes", false),
        new CheckBoxNode("Always expand alt text for images", true) };
    CheckBoxNode browsingOptions[] = {
        new CheckBoxNode("Notify when downloads complete", true),
        new CheckBoxNode("Disable script debugging", true),
        new CheckBoxNode("Use AutoComplete", true),
        new CheckBoxNode("Browse in a new process", false) 
        };
    TextBoxNode loloptions[] =
        {
                new TextBoxNode("oha", "lol"),
                new TextBoxNode("oha1", "lol"),
                new TextBoxNode("oha2", "lol")
        };

    Vector accessVector = new NamedVector("Accessibility",
        accessibilityOptions);
    Vector browseVector = new NamedVector("Browsing", browsingOptions);
    Vector browse1Vector = new NamedVector("Browsing", browsingOptions);
    Vector browse2Vector = new NamedVector("textboxnodes", loloptions);
    Object lolNodes[] = {browse1Vector, browseVector, browse2Vector};
    Vector lolvec = new NamedVector("Overking", lolNodes);
    Object rootNodes[] = { accessVector, lolvec};
    lolvec.add(new CheckBoxNode("oh",false));
    Vector rootVector = new NamedVector("Root", rootNodes);
    JTree tree = new JTree(rootVector);


    CheckBoxNodeRenderer renderer = new CheckBoxNodeRenderer();
    tree.setCellRenderer(renderer);

    tree.setCellEditor(new CheckBoxNodeEditor(tree));
    tree.setEditable(true);
    for (int i = 0; i < tree.getRowCount(); i++) {
        tree.expandRow(i);
    }

    JScrollPane scrollPane = new JScrollPane(tree);
    frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
    frame.setSize(300, 150);
    frame.setVisible(true);
  }
}

class CheckBoxNodeRenderer implements TreeCellRenderer {
      private JCheckBox leafRenderer = new JCheckBox();
      private JTextField leafRendererAlt = new JTextField();
      private DefaultTreeCellRenderer nonLeafRenderer = new DefaultTreeCellRenderer();

      Color selectionBorderColor, selectionForeground, selectionBackground,
          textForeground, textBackground;

      protected Object getLeafRenderer() {
        if(leafRenderer.getText().length() > 0)
            return leafRenderer;
        else
            return leafRendererAlt;
      }

      public CheckBoxNodeRenderer() {
        Font fontValue;
        fontValue = UIManager.getFont("Tree.font");
        if (fontValue != null) {
          leafRenderer.setFont(fontValue);
        }
        Boolean booleanValue = (Boolean) UIManager
            .get("Tree.drawsFocusBorderAroundIcon");
        leafRenderer.setFocusPainted((booleanValue != null)
            && (booleanValue.booleanValue()));

        selectionBorderColor = UIManager.getColor("Tree.selectionBorderColor");
        selectionForeground = UIManager.getColor("Tree.selectionForeground");
        selectionBackground = UIManager.getColor("Tree.selectionBackground");
        textForeground = UIManager.getColor("Tree.textForeground");
        textBackground = UIManager.getColor("Tree.textBackground");
      }

      public Component getTreeCellRendererComponent(JTree tree, Object value,
          boolean selected, boolean expanded, boolean leaf, int row,
          boolean hasFocus) {

        Component returnValue;
        if (leaf) {

          String stringValue = tree.convertValueToText(value, selected,
              expanded, leaf, row, false);

          if(stringValue.contains("TextBoxNode"))
          {
              leafRenderer = new JCheckBox();
              leafRendererAlt.setText(stringValue);
              //leafRendererAlt.setValue(value);

              leafRendererAlt.setEnabled(tree.isEnabled());

              if (selected) {
                  leafRendererAlt.setForeground(selectionForeground);
                  leafRendererAlt.setBackground(selectionBackground);
              } else {
                  leafRendererAlt.setForeground(textForeground);
                  leafRendererAlt.setBackground(textBackground);
              }

              if ((value != null) && (value instanceof DefaultMutableTreeNode)) {
                Object userObject = ((DefaultMutableTreeNode) value)
                    .getUserObject();
                if (userObject instanceof TextBoxNode) {
                  TextBoxNode node = (TextBoxNode) userObject;
                  leafRendererAlt.setText(node.getText());
                }
              }
              returnValue = leafRendererAlt;
          }
          else
          {
              leafRendererAlt = new JTextField();
              leafRenderer.setText(stringValue);
              leafRenderer.setSelected(false);

              leafRenderer.setEnabled(tree.isEnabled());

              if (selected) {
                leafRenderer.setForeground(selectionForeground);
                leafRenderer.setBackground(selectionBackground);
              } else {
                leafRenderer.setForeground(textForeground);
                leafRenderer.setBackground(textBackground);
              }

              if ((value != null) && (value instanceof DefaultMutableTreeNode)) {
                Object userObject = ((DefaultMutableTreeNode) value)
                    .getUserObject();
                if (userObject instanceof CheckBoxNode) {
                  CheckBoxNode node = (CheckBoxNode) userObject;
                  leafRenderer.setText(node.getText());
                  leafRenderer.setSelected(node.isSelected());
                }
              }
              returnValue = leafRenderer;
          }
        } else {
          returnValue = nonLeafRenderer.getTreeCellRendererComponent(tree,
              value, selected, expanded, leaf, row, hasFocus);
        }
        return returnValue;
      }
}

class CheckBoxNodeEditor extends AbstractCellEditor implements TreeCellEditor {

      CheckBoxNodeRenderer renderer = new CheckBoxNodeRenderer();

      ChangeEvent changeEvent = null;

      JTree tree;

      public CheckBoxNodeEditor(JTree tree) {
        this.tree = tree;
      }

      public Object getCellEditorValue() {
        JCheckBox checkbox;
        JTextField textfield;
        CheckBoxNode checkBoxNode;
        TextBoxNode txtBoxNode;
        if(renderer.getLeafRenderer() instanceof JCheckBox)
        {
            checkbox = (JCheckBox) renderer.getLeafRenderer();
            checkBoxNode = new CheckBoxNode(checkbox.getText(),
            checkbox.isSelected());
            return checkBoxNode;
        }
        else
        {
            textfield = (JTextField) renderer.getLeafRenderer();
            String txt = textfield.getText();
            txtBoxNode = new TextBoxNode(txt, txt);
            return txtBoxNode;  
        }


      }

      public boolean isCellEditable(EventObject event) {
        boolean returnValue = false;
        if (event instanceof MouseEvent) {
          MouseEvent mouseEvent = (MouseEvent) event;
          TreePath path = tree.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();
              if((userObject instanceof TextBoxNode) || (userObject instanceof CheckBoxNode))
                  returnValue = treeNode.isLeaf();
            }
          }
        }
        return returnValue;
      }

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

        // editor always selected / focused
        ItemListener itemListener = new ItemListener() {
          public void itemStateChanged(ItemEvent itemEvent) {
            if (stopCellEditing()) {
              fireEditingStopped();
            }
          }
        };

        DocumentListener doclistener = new DocumentListener(){
              public void changedUpdate(DocumentEvent e) {
                    System.out.print(e);
                  }

            @Override
            public void insertUpdate(DocumentEvent arg0) {
                // TODO Auto-generated method stub
                javax.swing.text.Document test = arg0.getDocument();
                System.out.print(arg0);
                fireEditingStopped();


            }

            @Override
            public void removeUpdate(DocumentEvent arg0) {
                // TODO Auto-generated method stub
                System.out.print(arg0);
            }
        };
        if (editor instanceof JCheckBox) {
          ((JCheckBox) editor).addItemListener(itemListener);
        }
        else if (editor instanceof JTextField) 
        {
            ((JTextField) editor).getDocument().addDocumentListener(doclistener);
        }
        return editor;
      }
}

class CheckBoxNode {
      String text;

      boolean selected;

      public CheckBoxNode(String text, boolean selected) {
        this.text = text;
        this.selected = selected;
      }

      public boolean isSelected() {
        return selected;
      }

      public void setSelected(boolean newValue) {
        selected = newValue;
      }

      public String getText() {
        return text;
      }

      public void setText(String newValue) {
        text = newValue;
      }

      public String toString() {
        return getClass().getName() + "[" + text + "/" + selected + "]";
      }
}
class TextBoxNode{
      String text;

      String value;

      public TextBoxNode(String text, String value) {
        this.text = text;
        this.value = value;
      }

      public String getValue() {
        return value;
      }

      public void setValue(String newvalue) {
          value = newvalue;
      }

      public String getText() {
        return text;
      }

      public void setText(String newValue) {
        text = newValue;
      }

      public String toString() {
        return getClass().getName() + "[" + text + "/" + value + "]";
      }
}

class NamedVector extends Vector {
      String name;

      public NamedVector(String name) {
        this.name = name;
      }

      public NamedVector(String name, Object elements[]) {
        this.name = name;
        for (int i = 0, n = elements.length; i < n; i++) {
          add(elements[i]);
        }
      }

      public String toString() {
        return "[" + name + "]";
      }
}

The issue is. 问题是。 I cant modify the text of JTextFields . 我无法修改JTextFields的文本。 And I do not know how to add a JLabel in the same line of the JTextField 而且我不知道如何在JTextField的同一行中添加JLabel

I hope you can help me. 我希望你能帮助我。

In principle you should cleanly separate the renderer and the editor. 原则上,您应该彻底分离渲染器和编辑器。 In your case, they are closely tied together (in fact, the editor returns the JTextField instance of the renderer)... A renderer is not supposed to be editable. 在您的情况下,它们紧密地联系在一起(实际上,编辑器返回渲染器的JTextField实例)...渲染器不应被编辑。 I doubt in your case that the editor is ever called. 在您的情况下,我怀疑是否曾召集过编辑。

I see two possible solutions: 我看到两种可能的解决方案:

  • Heavily refactor your code, to separate rendering and editing (eg rendering with JLabel and editing with JTextField -- or simply using a DefaultTreeCellEditor -- example here ). 大量重构代码,以分离渲染和编辑(例如,使用JLabel渲染和使用JTextField编辑-或仅使用DefaultTreeCellEditor示例在此处 )。 Let the tree determine when the edit starts, when to call the editor, when to cancel an edit, etc... 让树确定何时开始编辑,何时调用编辑器,何时取消编辑等...
  • Or you can by-pass the standard editing mechanism (as you are already doing more or less): Completely remove the TreeCellEditor from your code and let the renderer do all the work. 或者,您可以绕过标准的编辑机制(因为您已经或多或少地做了一些工作):从代码中完全删除TreeCellEditor ,然后让渲染器完成所有工作。 Add appropriate listeners to your JTextField and JCheckBox inside the renderer, and update the model when changes are made. 将适当的侦听器添加到渲染器内的JTextFieldJCheckBox ,并在进行更改时更新模型。 (Note that one drawback is that you'll have a primitive editing mechanism: eg the edit is not cancelled if user presses ESC ). (请注意,一个缺点是您将拥有原始的编辑机制:例如,如果用户按下ESC,则不会取消编辑)。

As to: 关于:

And I do not know how to add a JLabel in the same line of the JTextField 而且我不知道如何在JTextField的同一行中添加JLabel

Just let your renderer return a JPanel to which you add the JTextField and the JLabel . 只需让您的渲染器返回一个JPanel即可,并在其中添加JTextFieldJLabel

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM