Geertjan's Blog

  • March 16, 2009

Drag a Node from a BeanTreeView onto a TopComponent

Geertjan Wielenga
Product Manager
The question of the day comes from someone only known as John, who wants to drag an item from the Palette into an explorer view, such as the BeanTreeView. Well, I don't have the complete answer yet, but the first steps, which might end up providing the beginning of the end for John.

At the end of this blog entry, you'll be able to drag a Node from a BeanTreeView (which could be a Node anywhere, such as in a Palette) into a TopComponent, where the drop results in the change to the text in the JLabel that is found there:

Do this:

  1. Create a new module and then create two TopComponents. The first TopComponent contains the Node shown in the Explorer mode on the left above, the second TopComponent is in the Output mode, containing a JLabel.

  2. In the TopComponent in the explorer mode, implement ExplorerManager.Provider, with a BeanTreeView, and then create a Children.Keys or ChildFactory that provides the Node. You also need a Customer domain class that implements Transferable:
    import java.awt.datatransfer.DataFlavor;
    import java.awt.datatransfer.Transferable;
    import java.awt.datatransfer.UnsupportedFlavorException;
    import java.io.IOException;
    public class Customer implements Transferable {
    public static final DataFlavor DATA_FLAVOR = new DataFlavor(Customer.class, "customer");
    String name;
    public String getName() {
    return name;
    public void setName(String name) {
    this.name = name;
    public DataFlavor[] getTransferDataFlavors() {
    return new DataFlavor[]{DATA_FLAVOR};
    public boolean isDataFlavorSupported(DataFlavor flavor) {
    return flavor == DATA_FLAVOR;
    public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
    if (flavor == DATA_FLAVOR) {
    return this;
    } else {
    throw new UnsupportedFlavorException(flavor);

    In the class that creates the Children, make sure to override the drag() to return the current Customer, as shown here:

    private class NodeChildFactory extends ChildFactory<Customer> {
    protected boolean createKeys(List<Customer> list) {
    String[] names = {"Tom", "Dick", "Harry"};
    for (String name : names) {
    Customer c = new Customer();
    return true;
    protected Node createNodeForKey(final Customer c) {
    Node node = new AbstractNode(Children.LEAF){
    public Transferable drag() throws IOException {
    return c;
    return node;

  3. At the end of the constructor of the TopComponent in the Output mode, add the following code:
    MyDropTargetListener dtl = new MyDropTargetListener();
    DropTarget dt = new DropTarget(this, dtl);

    Then create the MyDropTargetListener, as an inner class of the same TopComponent, like this:

    public class MyDropTargetListener implements DropTargetListener {
    public void dragEnter(DropTargetDragEvent dtde) {}
    public void dragExit(DropTargetEvent dtde) {}
    public void dragOver(DropTargetDragEvent dtde) {}
    public void dropActionChanged(DropTargetDragEvent dtde) {}
    public void drop(DropTargetDropEvent dtde) {
    if (dtde.isDataFlavorSupported(Customer.DATA_FLAVOR)) {
    try {
    Object transData = dtde.getTransferable().getTransferData(Customer.DATA_FLAVOR);
    if (transData instanceof Customer) {
    Customer c = (Customer) dtde.getTransferable().getTransferData(Customer.DATA_FLAVOR);
    } catch (UnsupportedFlavorException ufe) {
    } catch (IOException ioe) {
    } else {

  4. Now run the application and you should be able to drag and drop a Node into the window that is in the Output mode, because you have set that window to be the DropTarget. Make sure that you hold down the Ctrl key as you move the Node into the drop window, since that's what the Copy action requires. Then the cursor changes to the accept cursor and you can drop your Node, causing the label's text to change to the current customer name.

Now, since the Palette can display Nodes, just like any of the explorer views, you should be able to adapt this example to use a Palette instead of a BeanTreeView. Plus, you should then create a BeanTreeView in the second window, with a LookupListener that detects whenever an InstanceContent contains a new Customer class. But I'll explore that approach next time. For now, refer here and here for further details.

Join the discussion

Comments ( 5 )
  • Rajiv Wednesday, March 18, 2009

    Could you please post the full source code of this example.

  • Miguel Garcia-Lopez Wednesday, March 18, 2009

    Dear Geertjan these two last posts are such useful writings! I need to congratulate you again for the contents. Since I began developing my first NBP-based app your articles and the book you co-authored have been the most helpful contributions I've found.

    I must also admit I admire how productive and knowledge-spreading you remain in time... you have a huge work output throughput and quality!!

    And now, please excuse me while I go and add DnD functionality to my nodes :)

  • Geertjan Wielenga Thursday, March 19, 2009

    Hi Miguel, thanks very much for appreciating these blog entries. It would be pretty cool if I could interview you about your application (via e-mail) and write an article about it. If you like that idea, drop me an e-mail at geertjan DOT wielenga AT sun DOT com.

  • Mark Thursday, March 8, 2012

    Great example code. Would have taken me much longer to get D&D working without it. Though had to change a couple of lines in the Customer Class from

    flavor == DATA_FLAVOR



    to get it working. Hopefully this comment will save somebody some pain

  • guest Tuesday, March 20, 2012

    Hi Geertjan,

    How to drag multiple nodes (meaning tom,dick,harry at once?


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.