在同一个JTree中使用两个不同的对象时,JTree和CellEditor无法正常工作

时间:2022-06-30 12:37:19

I am currently having a problem with the cell editor from the JTree. I have two different objects inside my JTree, Users and Books.

我目前正在使用JTree的单元格编辑器。我的JTree,Users和Books中有两个不同的对象。

在同一个JTree中使用两个不同的对象时,JTree和CellEditor无法正常工作

So the user is Bianca and the books are the nodes. The labels inside those nodes (the eye, the paint label and the trash can) are also clickable. However, when I set my cell editor, it gives me a null exception. I think it's because I am working with two different objects so I can't set the cell editor properly. This is the specific method where I think I have the problem:

所以用户是Bianca,书籍是节点。这些节点(眼睛,油漆标签和垃圾桶)内的标签也是可点击的。但是,当我设置我的单元格编辑器时,它给了我一个null异常。我认为这是因为我正在使用两个不同的对象,所以我无法正确设置单元格编辑器。这是我认为我遇到问题的具体方法:

public Component getTreeCellEditorComponent(JTree tree, Object value, boolean isSelected, boolean expanded,
        boolean leaf, int row) {
    Component returnValue = null;
    System.out.println("loo");
    if ((value != null) && (value instanceof DefaultMutableTreeNode)) {
        Object userObject = ((DefaultMutableTreeNode) value)
                .getUserObject();
        System.out.println("b");
        if(userObject instanceof Book){
            Book feature = (Book) userObject;
            title.setText(feature.getTitulo());
            renderer.setEnabled(tree.isEnabled());
            returnValue = renderer;
            System.out.println("hi!!");
        }
    }
    if (returnValue == null) {
        System.out.println("hi1");
        returnValue = defaultEditor.getTreeCellEditorComponent(tree, value, isSelected, expanded, leaf, row);
        System.out.println(defaultEditor);

    } 
    return returnValue;
}

I don't know how to return the DefaultCellEditor when the type of the node is not Book.

当节点的类型不是Book时,我不知道如何返回DefaultCellEditor。

Below is my entire code if someone wants to replicate the problem:

如果有人想要复制问题,下面是我的整个代码:

Class Book:

public class Book {
    String titulo;

    public String getTitulo() {
        return titulo;
    }

    public void setTitulo(String titulo) {
        this.titulo = titulo;
    }
    public Book(String titulo){
        this.titulo = titulo;
    }
}

Class User

public class User {
    String nomeUser;

    public String getNomeUser() {
        return nomeUser;
    }

    public void setNomeUser(String nomeUser) {
        this.nomeUser = nomeUser;
    }
    public User(String nome){
        this.nomeUser = nome;
    }
}

Class Render (used to set the cell editor and cell render of the JTree)

类Render(用于设置JTree的单元格编辑器和单元格渲染)

import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.IOException;
import java.io.InputStream;

import javax.imageio.ImageIO;
import javax.swing.AbstractCellEditor;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeCellEditor;
import javax.swing.tree.TreeCellRenderer;


public class Render{
public static class NodeCellRenderer implements TreeCellRenderer{
        private JLabel nomeRadar;
        private JPanel renderer;
        private JLabel btnVisible;
        private JLabel btnPaint;
        private JLabel btnTrash;

        DefaultTreeCellRenderer defaultRenderer = new DefaultTreeCellRenderer();
        public NodeCellRenderer() throws IOException{
            renderer = new JPanel(new FlowLayout(5, 5,5));
            nomeRadar = new JLabel();
            renderer.add(nomeRadar);
            btnVisible = new JLabel();
            btnPaint = new JLabel();
            btnTrash = new JLabel();
            InputStream visible = getClass().getResourceAsStream("/eye_visible-16.png");
            InputStream invisible = getClass().getResourceAsStream("/eye_invisible-16.png");
            InputStream paint = getClass().getResourceAsStream("/paint-16.png");
            InputStream trash = getClass().getResourceAsStream("/trash-16.png");
            btnVisible.setIcon(new ImageIcon(ImageIO.read(visible)));
            btnPaint.setIcon(new ImageIcon(ImageIO.read(paint)));
            btnTrash.setIcon(new ImageIcon(ImageIO.read(trash)));
            nomeRadar.addMouseListener(new MouseAdapter(){

                public void mouseClicked(MouseEvent e){
                    System.out.println("clicou no nome");
                }
            });
            btnVisible.addMouseListener(new MouseAdapter(){
                public void mouseClicked(MouseEvent e){
                    System.out.println("clicou no olho");
                }
            });
            btnPaint.addMouseListener(new MouseAdapter(){
                public void mouseClicked(MouseEvent e){
                    System.out.println("clicou no paint");
                }
            });
            btnTrash.addMouseListener(new MouseAdapter(){
                public void mouseClicked(MouseEvent e){
                    System.out.println("clicou no trash");
                }
            });
            renderer.add(nomeRadar);
            renderer.add(btnVisible);
            renderer.add(btnPaint);
            renderer.add(btnTrash);

        }
        @Override
        public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf,
                int row, boolean hasFocus) {
            Component returnValue = null;
            // TODO Auto-generated method stub
            if ((value != null) && (value instanceof DefaultMutableTreeNode)) {
                Object userObject = ((DefaultMutableTreeNode) value)
                        .getUserObject();
                if(userObject instanceof Book){
                    Book feature = (Book) userObject;
                    nomeRadar.setText(feature.getTitulo());
                    renderer.setEnabled(tree.isEnabled());
                    returnValue = renderer;
                }
            }
            if (returnValue == null) {
                returnValue = defaultRenderer.getTreeCellRendererComponent(tree,
                        value, selected, expanded, leaf, row, hasFocus);
            }
            return returnValue;
        }

    }
    public static class ButtonCellEditor extends AbstractCellEditor implements TreeCellEditor, ActionListener, MouseListener
    {
        /**
         * 
         */
        private static final long serialVersionUID = 1L;
        TreeCellEditor defaultEditor = JTreeOfObjects.currentStyle;
        JLabel title;
        JPanel renderer;
        JLabel btnVisible;
        JLabel btnPaint;
        JLabel btnTrash;
        private Object value;

        public ButtonCellEditor() throws IOException{
            renderer = new JPanel(new FlowLayout(5, 5,5));
            System.out.println("ulo");
            title = new JLabel();
            renderer.add(title);
            btnVisible = new JLabel();
            btnPaint = new JLabel();
            btnTrash = new JLabel(); 
            InputStream visible = getClass().getResourceAsStream("/eye_visible-16.png");
            InputStream invisible = getClass().getResourceAsStream("/eye_invisible-16.png");
            InputStream paint = getClass().getResourceAsStream("/paint-16.png");
            InputStream trash = getClass().getResourceAsStream("/trash-16.png");
            btnVisible.setIcon(new ImageIcon(ImageIO.read(visible)));
            btnPaint.setIcon(new ImageIcon(ImageIO.read(paint)));
            btnTrash.setIcon(new ImageIcon(ImageIO.read(trash)));
            System.out.println("nossa 1");
            title.addMouseListener(new MouseAdapter(){

                public void mouseClicked(MouseEvent e){
                    System.out.println("clicou no nome");
                    stopCellEditing();
                }
            });
            btnVisible.addMouseListener(new MouseAdapter(){
                public void mouseClicked(MouseEvent e){
                    System.out.println("clicou no olho");
                    stopCellEditing();
                }
            });
            btnPaint.addMouseListener(new MouseAdapter(){
                public void mouseClicked(MouseEvent e){
                    System.out.println("clicou no paint");
                    stopCellEditing();
                }
            });
            btnTrash.addMouseListener(new MouseAdapter(){
                public void mouseClicked(MouseEvent e){
                    System.out.println("clicou no trash");
                    stopCellEditing();
                }
            });
            renderer.add(title);
            renderer.add(btnVisible);
            renderer.add(btnPaint);
            renderer.add(btnTrash); 
        }


        @Override
        public Object getCellEditorValue() {
            // TODO Auto-generated method stub
            //return value.toString();
            return null;
        }


        @Override
        public void mouseClicked(MouseEvent e) {
            // TODO Auto-generated method stub
            System.out.println("clicou no b");
            stopCellEditing();
        }


        @Override
        public void mouseEntered(MouseEvent e) {
            // TODO Auto-generated method stub

        }


        @Override
        public void mouseExited(MouseEvent e) {
            // TODO Auto-generated method stub

        }


        @Override
        public void mousePressed(MouseEvent e) {
            // TODO Auto-generated method stub
            System.out.println("clicou no d");
            stopCellEditing();
        }


        @Override
        public void mouseReleased(MouseEvent e) {
            // TODO Auto-generated method stub

        }


        @Override
        public void actionPerformed(ActionEvent e) {
            // TODO Auto-generated method stub
            System.out.println("clicou no a");
            stopCellEditing();

        }


        @Override
        public Component getTreeCellEditorComponent(JTree tree, Object value, boolean isSelected, boolean expanded,
                boolean leaf, int row) {
            Component returnValue = null;
            System.out.println("loo");
            if ((value != null) && (value instanceof DefaultMutableTreeNode)) {
                Object userObject = ((DefaultMutableTreeNode) value)
                        .getUserObject();
                System.out.println("b");
                if(userObject instanceof Book){
                    Book feature = (Book) userObject;
                    title.setText(feature.getTitulo());
                    renderer.setEnabled(tree.isEnabled());
                    returnValue = renderer;
                    System.out.println("hi!!");
                }
            }
            if (returnValue == null) {
                System.out.println("hi1");
                returnValue = defaultEditor.getTreeCellEditorComponent(tree, value, isSelected, expanded, leaf, row);
                System.out.println(defaultEditor);

            } 
            return returnValue;
        }


    }
}

Class JTreeOfObjects

public class JTreeOfObjects {


    public static TreeCellRenderer renderer;
    private JFrame frame;
    public static JTree tree;
    private DefaultTreeModel model;
    private DefaultMutableTreeNode parent;
    JLabel nomeRadar;
    JLabel btnVisible;
    JLabel btnPaint;
    JLabel btnTrash;
    public static TreeCellEditor currentStyle;
    public void initialize() throws IOException{
        frame = new JFrame("Árvore de Navegação");
        parent = new DefaultMutableTreeNode("Library",true);
        //DefaultMutableTreeNode undefined = new DefaultMutableTreeNode("Indefinida");
        //undefined.add(new DefaultMutableTreeNode("!"));
        System.out.println(parent.getUserObject());

        //parent.add(undefined);
        tree = new JTree(parent);
        System.out.println("Current"+tree.getCellEditor());
        //currentStyle = tree.getCellEditor();
        renderer  = new Render.NodeCellRenderer();
        model = (DefaultTreeModel) tree.getModel();

        tree.setEditable(true);
        tree.setCellRenderer(renderer);
        tree.setCellEditor(new Render.ButtonCellEditor());
        //frame.getContentPane().add(tree);
        nomeRadar = new JLabel();
        btnVisible = new JLabel();
        btnPaint = new JLabel();
        btnTrash = new JLabel(); 
        InputStream visible = getClass().getResourceAsStream("/eye_visible-16.png");
        InputStream invisible = getClass().getResourceAsStream("/eye_invisible-16.png");
        InputStream paint = getClass().getResourceAsStream("/paint-16.png");
        InputStream trash = getClass().getResourceAsStream("/trash-16.png");
        btnVisible.setIcon(new ImageIcon(ImageIO.read(visible)));
        btnPaint.setIcon(new ImageIcon(ImageIO.read(paint)));
        btnTrash.setIcon(new ImageIcon(ImageIO.read(trash)));
        frame.getContentPane().add(btnPaint);
        frame.getContentPane().add(btnVisible);
        frame.getContentPane().add(btnTrash);
        frame.getContentPane().add(tree);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setUndecorated(true);
        frame.getRootPane().setWindowDecorationStyle(JRootPane.PLAIN_DIALOG);
        frame.setSize(200, 200);
        frame.setVisible(true);

    }
    public void adicionarNoCamada(String nomePessoa){
        //DefaultTreeModel model = (DefaultTreeModel)tree.getModel();

        DefaultMutableTreeNode noCamada = new DefaultMutableTreeNode(nomePessoa);
        parent.add(noCamada);


    }
    public void adicionarLivro(String nomeCamada,Book feature) throws IOException{
        //tree.get
        DefaultMutableTreeNode node = null;
        Enumeration e = parent.breadthFirstEnumeration();
        while(e.hasMoreElements()){
            node = (DefaultMutableTreeNode) e.nextElement();
            if(nomeCamada.equals(node.getUserObject().toString())){
                node.add(new DefaultMutableTreeNode(feature));
                break;
            }
            else{

            }
        }
        tree.setCellEditor(new Render.ButtonCellEditor());
    }

}

Class Main App

课程主要应用程序

public class MainApp {

    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
        Book b1 = new Book("The Book of Life");
        Book b2 = new Book ("The Book of Death");
        User u1 = new User("Bianca");
        JTreeOfObjects object = new JTreeOfObjects();
        object.initialize();
        object.adicionarNoCamada(u1.getNomeUser());
        object.adicionarLivro(u1.getNomeUser(), b1);
        object.adicionarLivro(u1.getNomeUser(), b2);

    }

}

Any help would be greatly appreciated. It's not a duplicated since I know how to fix a NullPointer Exception (have to instatiate the object). I just don't know what to return in the case of a TreeCellEditor, how to return its default.

任何帮助将不胜感激。它不是重复的,因为我知道如何修复NullPointer异常(必须实例化对象)。我只是不知道在TreeCellEditor的情况下返回什么,如何返回其默认值。

1 个解决方案

#1


2  

You might need to override CellEditor#isCellEditable(...) and CellEditor#getCellEditorValue(), but I'm not sure this will give you what you want.

你可能需要覆盖CellEditor#isCellEditable(...)和CellEditor#getCellEditorValue(),但我不确定这会给你你想要的。

  @Override public boolean isCellEditable(EventObject e) {
    Object source = e.getSource();
    if (!(source instanceof JTree) || !(e instanceof MouseEvent)) {
      return false;
    }
    JTree tree = (JTree) source;
    Point p = ((MouseEvent) e).getPoint();
    Object node = tree.getPathForLocation(p.x, p.y).getLastPathComponent();
    if (!(node instanceof DefaultMutableTreeNode)) {
      return false;
    }
    Object userObject = ((DefaultMutableTreeNode) node).getUserObject();
    if (!(userObject instanceof Book)) {
      return false;
    }
    return super.isCellEditable(e);
  }

  @Override
  public Object getCellEditorValue() {
    return new Book(renderer.nomeRadar.getText());
  }

Here's a quick example:

这是一个简单的例子:

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

public class MainApp2 {
  public JComponent makeUI() {
    JTree tree = new JTree(makeModel());
    tree.setEditable(true);
    tree.setCellRenderer(new NodeCellRenderer());
    tree.setCellEditor(new ButtonCellEditor());

    JPanel p = new JPanel(new BorderLayout());
    p.add(new JScrollPane(tree));
    return p;
  }
  private static DefaultMutableTreeNode makeModel() {
    Book b1 = new Book("The Book of Life");
    Book b2 = new Book("The Book of Death");
    User u1 = new User("Bianca");

    DefaultMutableTreeNode noCamada = new DefaultMutableTreeNode(u1);
    noCamada.add(new DefaultMutableTreeNode(b1));
    noCamada.add(new DefaultMutableTreeNode(b2));

    DefaultMutableTreeNode root = new DefaultMutableTreeNode("Library", true);
    root.add(noCamada);
    return root;
  }
  public static void main(String[] args) {
    EventQueue.invokeLater(() -> {
      JFrame f = new JFrame("Arvore de Navegacao");
      f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
      f.getContentPane().add(new MainApp2().makeUI());
      f.setSize(320, 240);
      f.setLocationRelativeTo(null);
      f.setVisible(true);
    });
  }
}

class NodePanel extends JPanel {
  public final JLabel nomeRadar = new JLabel();
  public final JLabel btnVisible = new JLabel(new ColorIcon(Color.RED));
  public final JLabel btnPaint = new JLabel(new ColorIcon(Color.GREEN));
  public final JLabel btnTrash = new JLabel(new ColorIcon(Color.BLUE));
  protected NodePanel() {
    super(new FlowLayout(FlowLayout.LEADING, 5, 5));
    add(nomeRadar);
    add(btnVisible);
    add(btnPaint);
    add(btnTrash);
  }
}

class NodeCellRenderer implements TreeCellRenderer {
  private final DefaultTreeCellRenderer defaultRenderer = new DefaultTreeCellRenderer();
  private final NodePanel renderer = new NodePanel();

  @Override public Component getTreeCellRendererComponent(
      JTree tree, Object value, boolean selected, boolean expanded,
      boolean leaf, int row, boolean hasFocus) {
    Component returnValue = null;
    if (value instanceof DefaultMutableTreeNode) {
      Object userObject = ((DefaultMutableTreeNode) value).getUserObject();
      if (userObject instanceof Book) {
        Book feature = (Book) userObject;
        renderer.nomeRadar.setText(feature.getTitulo());
        returnValue = renderer;
      }
    }
    if (returnValue == null) {
      returnValue = defaultRenderer.getTreeCellRendererComponent(
          tree, value, selected, expanded, leaf, row, hasFocus);
    }
    return returnValue;
  }
}

class ButtonCellEditor extends AbstractCellEditor implements TreeCellEditor {
  private final DefaultTreeCellRenderer defaultRenderer = new DefaultTreeCellRenderer();
  private final NodePanel renderer = new NodePanel();

  public ButtonCellEditor() {
    renderer.setBackground(Color.ORANGE);
    renderer.nomeRadar.addMouseListener(new MouseAdapter() {
      @Override public void mousePressed(MouseEvent e) {
        System.out.println("clicou no nome");
        stopCellEditing();
      }
    });
    renderer.btnVisible.addMouseListener(new MouseAdapter() {
      @Override public void mousePressed(MouseEvent e) {
        System.out.println("clicou no olho");
        stopCellEditing();
      }
    });
    renderer.btnPaint.addMouseListener(new MouseAdapter() {
      public void mousePressed(MouseEvent e) {
        System.out.println("clicou no paint");
        stopCellEditing();
      }
    });
    renderer.btnTrash.addMouseListener(new MouseAdapter() {
      public void mousePressed(MouseEvent e) {
        System.out.println("clicou no trash");
        stopCellEditing();
      }
    });
    renderer.addMouseListener(new MouseAdapter() {
      public void mousePressed(MouseEvent e) {
        System.out.println("renderer");
        stopCellEditing();
      }
    });
  }

  @Override public boolean isCellEditable(EventObject e) {
    Object source = e.getSource();
    if (!(source instanceof JTree) || !(e instanceof MouseEvent)) {
      return false;
    }
    JTree tree = (JTree) source;
    Point p = ((MouseEvent) e).getPoint();
    TreePath path = tree.getPathForLocation(p.x, p.y);
    if (Objects.isNull(path)) {
      return false;
    }
    Object node = path.getLastPathComponent();
    if (!(node instanceof DefaultMutableTreeNode)) {
      return false;
    }
    Object userObject = ((DefaultMutableTreeNode) node).getUserObject();
    if (!(userObject instanceof Book)) {
      return false;
    }
    return super.isCellEditable(e);
  }

  @Override
  public Object getCellEditorValue() {
    return new Book(renderer.nomeRadar.getText());
  }

  @Override
  public Component getTreeCellEditorComponent(
      JTree tree, Object value, boolean isSelected, boolean expanded,
      boolean leaf, int row) {
    Component returnValue = null;
    if (value instanceof DefaultMutableTreeNode) {
      Object userObject = ((DefaultMutableTreeNode) value).getUserObject();
      if (userObject instanceof Book) {
        Book feature = (Book) userObject;
        renderer.nomeRadar.setText(feature.getTitulo());
        returnValue = renderer;
      }
    }
    if (returnValue == null) {
      returnValue = defaultRenderer.getTreeCellRendererComponent(
          tree, value, isSelected, expanded, leaf, row, true);
    }
    return returnValue;
  }
}

class Book {
  String titulo;
  public String getTitulo() {
    return titulo;
  }
  public void setTitulo(String titulo) {
    this.titulo = titulo;
  }
  public Book(String titulo) {
    this.titulo = titulo;
  }
}

class User {
  String nomeUser;
  public String getNomeUser() {
    return nomeUser;
  }
  public void setNomeUser(String nomeUser) {
    this.nomeUser = nomeUser;
  }
  public User(String nome) {
    this.nomeUser = nome;
  }
  @Override public String toString() {
    return nomeUser;
  }
}

class ColorIcon implements Icon {
  private final Color color;
  protected ColorIcon(Color color) {
    this.color = color;
  }
  @Override public void paintIcon(Component c, Graphics g, int x, int y) {
    Graphics2D g2 = (Graphics2D) g.create();
    g2.translate(x, y);
    g2.setPaint(color);
    g2.fillRect(0, 0, getIconWidth(), getIconHeight());
    g2.dispose();
  }
  @Override public int getIconWidth() {
    return 16;
  }
  @Override public int getIconHeight() {
    return 16;
  }
}

#1


2  

You might need to override CellEditor#isCellEditable(...) and CellEditor#getCellEditorValue(), but I'm not sure this will give you what you want.

你可能需要覆盖CellEditor#isCellEditable(...)和CellEditor#getCellEditorValue(),但我不确定这会给你你想要的。

  @Override public boolean isCellEditable(EventObject e) {
    Object source = e.getSource();
    if (!(source instanceof JTree) || !(e instanceof MouseEvent)) {
      return false;
    }
    JTree tree = (JTree) source;
    Point p = ((MouseEvent) e).getPoint();
    Object node = tree.getPathForLocation(p.x, p.y).getLastPathComponent();
    if (!(node instanceof DefaultMutableTreeNode)) {
      return false;
    }
    Object userObject = ((DefaultMutableTreeNode) node).getUserObject();
    if (!(userObject instanceof Book)) {
      return false;
    }
    return super.isCellEditable(e);
  }

  @Override
  public Object getCellEditorValue() {
    return new Book(renderer.nomeRadar.getText());
  }

Here's a quick example:

这是一个简单的例子:

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

public class MainApp2 {
  public JComponent makeUI() {
    JTree tree = new JTree(makeModel());
    tree.setEditable(true);
    tree.setCellRenderer(new NodeCellRenderer());
    tree.setCellEditor(new ButtonCellEditor());

    JPanel p = new JPanel(new BorderLayout());
    p.add(new JScrollPane(tree));
    return p;
  }
  private static DefaultMutableTreeNode makeModel() {
    Book b1 = new Book("The Book of Life");
    Book b2 = new Book("The Book of Death");
    User u1 = new User("Bianca");

    DefaultMutableTreeNode noCamada = new DefaultMutableTreeNode(u1);
    noCamada.add(new DefaultMutableTreeNode(b1));
    noCamada.add(new DefaultMutableTreeNode(b2));

    DefaultMutableTreeNode root = new DefaultMutableTreeNode("Library", true);
    root.add(noCamada);
    return root;
  }
  public static void main(String[] args) {
    EventQueue.invokeLater(() -> {
      JFrame f = new JFrame("Arvore de Navegacao");
      f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
      f.getContentPane().add(new MainApp2().makeUI());
      f.setSize(320, 240);
      f.setLocationRelativeTo(null);
      f.setVisible(true);
    });
  }
}

class NodePanel extends JPanel {
  public final JLabel nomeRadar = new JLabel();
  public final JLabel btnVisible = new JLabel(new ColorIcon(Color.RED));
  public final JLabel btnPaint = new JLabel(new ColorIcon(Color.GREEN));
  public final JLabel btnTrash = new JLabel(new ColorIcon(Color.BLUE));
  protected NodePanel() {
    super(new FlowLayout(FlowLayout.LEADING, 5, 5));
    add(nomeRadar);
    add(btnVisible);
    add(btnPaint);
    add(btnTrash);
  }
}

class NodeCellRenderer implements TreeCellRenderer {
  private final DefaultTreeCellRenderer defaultRenderer = new DefaultTreeCellRenderer();
  private final NodePanel renderer = new NodePanel();

  @Override public Component getTreeCellRendererComponent(
      JTree tree, Object value, boolean selected, boolean expanded,
      boolean leaf, int row, boolean hasFocus) {
    Component returnValue = null;
    if (value instanceof DefaultMutableTreeNode) {
      Object userObject = ((DefaultMutableTreeNode) value).getUserObject();
      if (userObject instanceof Book) {
        Book feature = (Book) userObject;
        renderer.nomeRadar.setText(feature.getTitulo());
        returnValue = renderer;
      }
    }
    if (returnValue == null) {
      returnValue = defaultRenderer.getTreeCellRendererComponent(
          tree, value, selected, expanded, leaf, row, hasFocus);
    }
    return returnValue;
  }
}

class ButtonCellEditor extends AbstractCellEditor implements TreeCellEditor {
  private final DefaultTreeCellRenderer defaultRenderer = new DefaultTreeCellRenderer();
  private final NodePanel renderer = new NodePanel();

  public ButtonCellEditor() {
    renderer.setBackground(Color.ORANGE);
    renderer.nomeRadar.addMouseListener(new MouseAdapter() {
      @Override public void mousePressed(MouseEvent e) {
        System.out.println("clicou no nome");
        stopCellEditing();
      }
    });
    renderer.btnVisible.addMouseListener(new MouseAdapter() {
      @Override public void mousePressed(MouseEvent e) {
        System.out.println("clicou no olho");
        stopCellEditing();
      }
    });
    renderer.btnPaint.addMouseListener(new MouseAdapter() {
      public void mousePressed(MouseEvent e) {
        System.out.println("clicou no paint");
        stopCellEditing();
      }
    });
    renderer.btnTrash.addMouseListener(new MouseAdapter() {
      public void mousePressed(MouseEvent e) {
        System.out.println("clicou no trash");
        stopCellEditing();
      }
    });
    renderer.addMouseListener(new MouseAdapter() {
      public void mousePressed(MouseEvent e) {
        System.out.println("renderer");
        stopCellEditing();
      }
    });
  }

  @Override public boolean isCellEditable(EventObject e) {
    Object source = e.getSource();
    if (!(source instanceof JTree) || !(e instanceof MouseEvent)) {
      return false;
    }
    JTree tree = (JTree) source;
    Point p = ((MouseEvent) e).getPoint();
    TreePath path = tree.getPathForLocation(p.x, p.y);
    if (Objects.isNull(path)) {
      return false;
    }
    Object node = path.getLastPathComponent();
    if (!(node instanceof DefaultMutableTreeNode)) {
      return false;
    }
    Object userObject = ((DefaultMutableTreeNode) node).getUserObject();
    if (!(userObject instanceof Book)) {
      return false;
    }
    return super.isCellEditable(e);
  }

  @Override
  public Object getCellEditorValue() {
    return new Book(renderer.nomeRadar.getText());
  }

  @Override
  public Component getTreeCellEditorComponent(
      JTree tree, Object value, boolean isSelected, boolean expanded,
      boolean leaf, int row) {
    Component returnValue = null;
    if (value instanceof DefaultMutableTreeNode) {
      Object userObject = ((DefaultMutableTreeNode) value).getUserObject();
      if (userObject instanceof Book) {
        Book feature = (Book) userObject;
        renderer.nomeRadar.setText(feature.getTitulo());
        returnValue = renderer;
      }
    }
    if (returnValue == null) {
      returnValue = defaultRenderer.getTreeCellRendererComponent(
          tree, value, isSelected, expanded, leaf, row, true);
    }
    return returnValue;
  }
}

class Book {
  String titulo;
  public String getTitulo() {
    return titulo;
  }
  public void setTitulo(String titulo) {
    this.titulo = titulo;
  }
  public Book(String titulo) {
    this.titulo = titulo;
  }
}

class User {
  String nomeUser;
  public String getNomeUser() {
    return nomeUser;
  }
  public void setNomeUser(String nomeUser) {
    this.nomeUser = nomeUser;
  }
  public User(String nome) {
    this.nomeUser = nome;
  }
  @Override public String toString() {
    return nomeUser;
  }
}

class ColorIcon implements Icon {
  private final Color color;
  protected ColorIcon(Color color) {
    this.color = color;
  }
  @Override public void paintIcon(Component c, Graphics g, int x, int y) {
    Graphics2D g2 = (Graphics2D) g.create();
    g2.translate(x, y);
    g2.setPaint(color);
    g2.fillRect(0, 0, getIconWidth(), getIconHeight());
    g2.dispose();
  }
  @Override public int getIconWidth() {
    return 16;
  }
  @Override public int getIconHeight() {
    return 16;
  }
}