title: Drop location rendering with swing
body: <p>I want to implement custom drop location rendering for a component (e.g. JPanel or JLabel). My goal is to display a blue border when the user hovers the component with a droppable item and remove the border again when leaving the component.</p>
  
  <p>The swing tutorial provides this:<br>
  <a href="http://docs.oracle.com/javase/tutorial/uiswing/dnd/droplocation.html" rel="nofollow">Drop Location Rendering</a><br>
  Which didn't help me at all. I'm missing something like <code>enterComponent(Event e)</code> and <code>exitComponent(Event e)</code>, or does this page refer to something different than what I expected?</p>
  
  <p>So I searched through the world wide web and found some examples (mostly from <a href="http://rabbit-hole.blogspot.com.au/search/label/drag%20n%20drop" rel="nofollow">this blog</a>). After a little while I could accomplish to put together a working example for what I needed (source below). But the examples I found all used classes from java.awt to render the drop location. Because I still haven't got the full overview over all these drag-and-drop classes, I didn't find a way to achieve the custom drop location rendering by only using swing classes.</p>
  
  <p>So my question is:<br>
  <strong>Is is possible to render a JComponent on <code>"enterComponent"</code> and <code>"exitComponent"</code> events by only using swing classes?</strong></p>
  
  <p>Additional question:<br>
  If I remove the line <code>new DropTarget(label, dropListener);</code>, <code>ListItemTransfereHandler.importData(...)</code> will be called otherwise it won't be called. What is the reason for this? I would really appreciate some class and/or action chart about the dnd classes (this is not neccessary for an answer).</p>
  
  <p>(No JavaFX answers please)</p>
  
  <hr>
  
  <p>Source code of working example (with AWT classes). Sorry for the massive lines of code, but java dnd needs really much space.</p>
  
  <pre><code>public class DnDTransferableTest {
  
      public static void main(String[] args) {
          EventQueue.invokeLater(new Runnable() {
              @Override
              public void run() {
                  new DnDTransferableTest();
              }
          });
      }
  
      public DnDTransferableTest() {
          JFrame frame = new JFrame("Testing");
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.setSize(300, 300);
          frame.setLocationRelativeTo(null);
  
  //      JPanel panel = new JPanel(new MigLayout("wrap 2, fill", "fill, grow", "align center"));
          JPanel panel = new JPanel(new GridLayout(1,2));
  
          JList&lt;ListItem&gt; list = new JList&lt;ListItem&gt;();
          JLabel label = new JLabel();
  
          // Initializing list
          list.setDragEnabled(true);
          list.setTransferHandler(new ListTransferHandler());
  
          DefaultListModel&lt;ListItem&gt; model = new DefaultListModel&lt;ListItem&gt;();
          for (int index = 0; index &lt; 10; index++) {
  
              model.addElement(new ListItem("Item", index));
  
          }
          list.setModel(model);
  
          // Initializing label and its drop listener
          label.setText("Drag on me...");
          label.setTransferHandler(new ListTransferHandler());
  
          DropTargetListener dropListener = new JLabelDropTargetListener();
          new DropTarget(label, dropListener);
  
          // Adding the components to the panel
          panel.add(new JScrollPane(list), "sg test");
          panel.add(label, "sg test");
  
          frame.setContentPane(panel);
          frame.setVisible(true);
      }
  
  }
  
  class ListItem implements Transferable {
  
      public static final DataFlavor LIST_ITEM_DATA_FLAVOR = new DataFlavor(ListItem.class, ListItem.class.getName());
      private String text;
      private int number;
  
      public ListItem(String text, int number) {
          this.text = text;
          this.number = number;
      }
  
      public String getText() {
          return text;
      }
  
      public int getNumber() {
          return this.number;
      }
  
      @Override
      public String toString() {
          return this.getText() + ": " + this.getNumber();
      }
  
      @Override
      public DataFlavor[] getTransferDataFlavors() {
          return new DataFlavor[] { LIST_ITEM_DATA_FLAVOR };
      }
  
      @Override
      public boolean isDataFlavorSupported(DataFlavor flavor) {
          return flavor.equals(LIST_ITEM_DATA_FLAVOR);
      }
  
      @Override
      public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
          return this;
      }
  }
  
  class ListTransferHandler extends TransferHandler {
  
      private static final long serialVersionUID = 1L;
  
      @Override
      public boolean canImport(TransferSupport support) {
          return (support.getComponent() instanceof JLabel) &amp;&amp; support.isDataFlavorSupported(ListItem.LIST_ITEM_DATA_FLAVOR);
      }
  
      @Override
      public boolean importData(TransferSupport support) {
  
          boolean accept = false;
          if (canImport(support)) {
              try {
                  Transferable t = support.getTransferable();
                  Object value = t.getTransferData(ListItem.LIST_ITEM_DATA_FLAVOR);
                  if (value instanceof ListItem) {
                      Component component = support.getComponent();
                      if (component instanceof JLabel) {
                          ((JLabel) component).setText(((ListItem) value).getNumber() + ". " + ((ListItem) value).getText());
                      }
                  }
              } catch (Exception exp) {
                  exp.printStackTrace();
              }
          }
          System.out.println("import data " + accept);
          return accept;
      }
  
      @Override
      public int getSourceActions(JComponent c) {
          return COPY;
      }
  
      @Override
      protected Transferable createTransferable(JComponent c) {
  
          if (c instanceof JList&lt;?&gt;) {
              JList&lt;?&gt; list = (JList&lt;?&gt;) c;
              Object value = list.getSelectedValue();
              if (value instanceof ListItem) {
                  return (ListItem) value;
              }
          }
          return null;
      }
  
      @Override
      protected void exportDone(JComponent source, Transferable data, int action) {
          System.out.println("ExportDone");
          // Here you need to decide how to handle the completion of the
          // transfer,
          // should you remove the item from the list or not...
      }
  
  }
  
  class JLabelDropTargetListener implements DropTargetListener {
  
      private int thickness = 2;
      private Border blueBorder = BorderFactory.createLineBorder(Color.BLUE, thickness);
      private Border emptyBorder = BorderFactory.createEmptyBorder(thickness, thickness, thickness, thickness);
  
      @Override
      public void dragEnter(DropTargetDragEvent dtde) {
          System.out.println("dragEnter");
          Object src = dtde.getDropTargetContext().getComponent();
  
          if (src instanceof JLabel) {
              JLabel label = (JLabel) src;
              label.setForeground(Color.RED);
              label.setBorder(blueBorder);
          } else {
              System.out.println(src.getClass().getName());
              System.out.println(dtde.getDropTargetContext().getComponent());
          }
      }
  
      @Override
      public void dragOver(DropTargetDragEvent dtde) {
      }
  
      @Override
      public void dropActionChanged(DropTargetDragEvent dtde) {
      }
  
      @Override
      public void dragExit(DropTargetEvent dte) {
          System.out.println("dragExit");
          Component src = dte.getDropTargetContext().getComponent();
  
          if (src instanceof JLabel) {
              JLabel label = (JLabel) src;
              label.setForeground(null);
              label.setBorder(emptyBorder);
          }
  
      }
  
      @Override
      public void drop(DropTargetDropEvent dtde) {
          System.out.println("drop");
          Component src = dtde.getDropTargetContext().getComponent();
  
          if (src instanceof JLabel) {
              JLabel label = (JLabel) src;
              label.setForeground(null);
              label.setBorder(emptyBorder);
  
              Transferable t = dtde.getTransferable();
              Object value;
              try {
                  value = t.getTransferData(ListItem.LIST_ITEM_DATA_FLAVOR);
  
                  if (value instanceof ListItem) {
                      ListItem li = (ListItem) value;
                      label.setText(li.getNumber() + ". " + li.getText());
                  }
  
              } catch (UnsupportedFlavorException e) {
                  e.printStackTrace();
              } catch (IOException e) {
                  e.printStackTrace();
              }
  
          }
      }
  
  }
  </code></pre>