JTree编辑器没有设置变量

时间:2016-01-25 11:04:03

标签: java swing jcombobox jtree

我正在尝试在Renderer中使用JTree作为我正在开发的Swing应用程序,仅当树是叶对象并且由流布局组成时才使用自定义渲染器。带有图像的空标签,JComboBox,最后是包含字符串的标签。

最初Renderer通过getTreeCellRendererComponent()中的HazardRenderer.java方法传递一个字符串值,然后使用编辑器setText()中的HazardComboBox.java方法设置它获取选定的渲染器实例并使用相同的setText()方法设置文本。

但是,在ItemListener内调用HazardEditor()时,标签文字会被清除。我可以验证这一点,因为注释掉侦听器会消除问题,但我需要一个侦听器能够告诉应用程序编辑编辑器已经可靠地完成。这个问题的解决方案是什么?代码如下;

Main.java

public class Main {
  public JComponent makeUI() {
    JTree tree = new JTree();
    tree.setEditable(true);
    tree.setRootVisible(false);
    tree.setCellRenderer(new HazardRenderer());
    tree.setCellEditor(new HazardEditor());
    //tree.setModel() excluded for brevity
    return new JScrollPane(tree);
  }
  public static void main(String[] args) {
    EventQueue.invokeLater(() -> {
      JFrame f = new JFrame();
      f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
      f.getContentPane().add(new Main().makeUI());
      f.pack();
      f.setLocationRelativeTo(null);
      f.setVisible(true);
    });
  }
}

HazardComboBox.java

public class HazardComboBox extends JPanel {
    private JLabel lblLabel = new JLabel("Placeholder");
    private JComboBox comboBox = new JComboBox(HazardSelection.values());

    public HazardComboBox() {
        setBackground(Color.WHITE);
        setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));

        JLabel label = new JLabel("");
        label.setIcon(new ImageIcon(HazardComboBox.class.getResource("/javax/swing/plaf/metal/icons/ocean/file.gif")));
        add(label);

        comboBox.setBorder(new EmptyBorder(2, 5, 2, 5));
        comboBox.setBackground(Color.WHITE);
        add(comboBox);

        lblLabel.setFont(new Font("Tahoma", Font.PLAIN, 11));
        add(lblLabel);
    }

    public JComboBox getComboBox() {
        return comboBox;
    }

    public JLabel getLabel() {
        return lblLabel;
    }

    public void setText(String name) {
        getLabel().setText(name);
    }

}

HazardRenderer.java

public class HazardRenderer implements TreeCellRenderer {
    private HazardComboBox leafRenderer = new HazardComboBox();
    private DefaultTreeCellRenderer nonLeafRenderer = new DefaultTreeCellRenderer();

    @Override
    public Component getTreeCellRendererComponent(JTree tree, Object hazard, boolean selected, boolean expanded, boolean leaf,
            int row, boolean hasFocus) {
        if (leaf) {
            leafRenderer.setText(hazard.toString());
            return leafRenderer;
        }
        return nonLeafRenderer.getTreeCellRendererComponent(tree, hazard, selected, expanded, leaf, row, hasFocus);
    }

}

HazardEditor.java

public class HazardEditor extends AbstractCellEditor implements TreeCellEditor {

    private HazardRenderer renderer = new HazardRenderer();
    private HazardComboBox component;
    private DefaultMutableTreeNode treeNode;
    //private ServerInfo info;
    //private JComboBox comboBox;
    private String val;

    @Override
    public Component getTreeCellEditorComponent(JTree tree, Object value,
            boolean isSelected, boolean expanded, boolean leaf, int row) {

        val = value.toString();
        component = (HazardComboBox)renderer.getTreeCellRendererComponent(tree, value, isSelected, expanded, leaf, row, true);

        if(leaf) {

            treeNode = (DefaultMutableTreeNode)value;
            component.setText(val);

            //info = (ServerInfo)treeNode.getUserObject();

            //comboBox = component.getComboBox();

            ItemListener itemListener = new ItemListener() {
                public void itemStateChanged(ItemEvent arg0) {
                    component.getComboBox().removeItemListener(this);
                    fireEditingStopped();
                }
            };

            component.getComboBox().addItemListener(itemListener);
        }

        return component;
    }

    @Override
    public Object getCellEditorValue() {
        //info.setChecked(comboBox.isSelected());
        //return info;
        return null;
    }

    @Override
    public boolean isCellEditable(EventObject event) {

        if(!(event instanceof MouseEvent)) return false;

        MouseEvent mouseEvent = (MouseEvent)event;
        JTree tree = (JTree)event.getSource();

        TreePath path = tree.getPathForLocation(mouseEvent.getX(), mouseEvent.getY());

        if(path == null) return false;

        Object lastComponent = path.getLastPathComponent();

        if(lastComponent == null) return false;

        DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)lastComponent;

        return treeNode.isLeaf();
    }

}

HazardSelection.java

public enum HazardSelection {
    NOTCONSIDERED("Not Considered"), NOTAPPLICABLE("Not Applicable"), CONSIDERED("Considered"), HAZARD("Hazard");

    private String name;

    private HazardSelection (String n) {
        name = n;
    }

    @Override
    public String toString() {
        return name;
    }
}

1 个答案:

答案 0 :(得分:3)

问题在于覆盖getCellEditorValue()中的HazardEditor.java方法。你这样做了如下:

@Override
public Object getCellEditorValue() {
    //info.setChecked(comboBox.isSelected());
    //return info;
    return null;
}

因此,您要返回null,然后您的Renderer会将null呈现为标签的文字。

您可以按照以下方式更正:

@Override
public Object getCellEditorValue() {
    return component.getComboBox().getSelectedItem();
}

祝你好运。