1

I'm trying to create a simple Java application that allows me to drag from Jtable header (TableColumn) and drop the column's name in JList and this is the code:

import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.EventQueue;

import javax.swing.DefaultListModel;
import javax.swing.DropMode;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.ListSelectionModel;
import javax.swing.TransferHandler;
import javax.swing.border.EmptyBorder;
import javax.swing.JScrollPane;

import java.awt.Dimension;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;

import javax.swing.JList;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumn;
import java.io.IOException;
import java.util.Enumeration;

public class DnDTableToList extends JFrame implements DragGestureListener, Transferable{

    private JPanel contentPane;
    private JTable table;
    private JList list;
    DefaultListModel model;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    DnDTableToList frame = new DnDTableToList();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the frame.
     */
    public DnDTableToList() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 672, 430);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(new BorderLayout(0, 0));

        JScrollPane scrollPane = new JScrollPane();
        scrollPane.setPreferredSize(new Dimension(150, 2));
        contentPane.add(scrollPane, BorderLayout.WEST);

        model = new DefaultListModel();
        list = new JList(model);
        scrollPane.setViewportView(list);

        JScrollPane scrollPane_1 = new JScrollPane();
        contentPane.add(scrollPane_1, BorderLayout.CENTER);

        table = new JTable();
        table.getTableHeader().setReorderingAllowed(false);
        table.setModel(new DefaultTableModel(
            new Object[][] {
                {"00001", "Mark", "Developper", "700"},
                {"00002", "Anna", "Developper", "700"},
                {"00003", "Jack", "Leader", "1200"},
            },
            new String[] {
                "Code", "Name", "Post", "Salary"
            }
        ));
        scrollPane_1.setViewportView(table);        

        //---set drop mode for JList--------------------------
        list.setDropMode(DropMode.INSERT);
        list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        list.setTransferHandler(new ListHandler(model));

        //----create drag source for JTableHeader-----------
        DragSource ds = new DragSource();
        ds.createDefaultDragGestureRecognizer(table.getTableHeader(), DnDConstants.ACTION_COPY, this);
    }



    @Override
    public Object getTransferData(DataFlavor e) throws UnsupportedFlavorException, IOException {
        return null;
    }

    @Override
    public DataFlavor[] getTransferDataFlavors() {
        System.out.println("getTransferDataFlavors");
        return new DataFlavor[0];
    }

    @Override
    public boolean isDataFlavorSupported(DataFlavor e) {
        System.out.println("isDataFlavorSupported");
        return false;
    }

    @Override
    public void dragGestureRecognized(DragGestureEvent event) {
        System.out.println("grag gesture");
        Cursor cursor = null;
        try {
            JTableHeader th = (JTableHeader) event.getComponent();
            Enumeration<?> e = th.getColumnModel().getColumns();

            while (e.hasMoreElements()) {
                TableColumn tc = (TableColumn) e.nextElement();
                System.out.println(tc.getHeaderValue());
            }
            TableColumn tb = th.getDraggedColumn();
            System.out.println("dragged column: "+tb.getHeaderValue());//---This is where the exception happens
            if (event.getDragAction() == DnDConstants.ACTION_COPY) {
                cursor = DragSource.DefaultCopyDrop;
            }
            event.startDrag(cursor, new TransferableTableColumn(tb));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

/**
 * Custom TransferHandler for JList
 *
 */
class ListHandler extends TransferHandler {
    private DefaultListModel model;
    public ListHandler(DefaultListModel model) {
        this.model = model;
    }

    public boolean canImport(TransferSupport support) {
         if (!support.isDrop()) {
             return false;
         }

         return support.isDataFlavorSupported(TransferableTableColumn.tableColumnFlavor);
     }

     public boolean importData(TransferSupport support) {
         if (!canImport(support)) {
             System.out.println("!canImport() -> return false");
           return false;
         }
         TableColumn tb;
         String line;
         try {
             Transferable transferable = support.getTransferable();
             tb = (TableColumn) transferable.getTransferData(TransferableTableColumn.tableColumnFlavor);
             line = (String) tb.getHeaderValue();
             JOptionPane.showMessageDialog(null, line);
         } catch (Exception e) {
             e.printStackTrace();
           return false;
         }

         JList.DropLocation dl = (JList.DropLocation) support.getDropLocation();
         int index = dl.getIndex();
         model.add(index++, line);
         JOptionPane.showMessageDialog(null, line);
         return true;
     }
}

/**
 * Custom Transferable with TableColumn DataFlavor
 *
 */
class TransferableTableColumn implements Transferable {

    protected static DataFlavor tableColumnFlavor = new DataFlavor(TableColumn.class, "A TableColumn Object");

    protected static DataFlavor[] supportedFlavors = {
        tableColumnFlavor,
        DataFlavor.stringFlavor,
    };

    TableColumn tabColumn;

    public TransferableTableColumn(TableColumn tabColumn) { this.tabColumn = tabColumn; }

    public DataFlavor[] getTransferDataFlavors() { return supportedFlavors; }

    public boolean isDataFlavorSupported(DataFlavor flavor) {
    if (flavor.equals(tableColumnFlavor) || 
        flavor.equals(DataFlavor.stringFlavor)) return true;
    return false;
  }


   public Object getTransferData(DataFlavor flavor)  throws UnsupportedFlavorException{
       System.out.println("getTransferData");
     if (flavor.equals(tableColumnFlavor))
         return tabColumn;
     else if (flavor.equals(DataFlavor.stringFlavor)) 
         return tabColumn.getHeaderValue();
     else 
         throw new UnsupportedFlavorException(flavor);
   }
}

But I'm getting a NullPointerException when I try to get the dragged column's name.
Exception stack trace:

java.lang.NullPointerException
    at pck.DnDTableToList.dragGestureRecognized(DnDTableToList.java:137)
    at java.awt.dnd.DragGestureRecognizer.fireDragGestureRecognized(Unknown Source)
    at sun.awt.windows.WMouseDragGestureRecognizer.mouseDragged(Unknown Source)
    at java.awt.AWTEventMulticaster.mouseDragged(Unknown Source)
    at java.awt.AWTEventMulticaster.mouseDragged(Unknown Source)
    at java.awt.Component.processMouseMotionEvent(Unknown Source)
    at javax.swing.JComponent.processMouseMotionEvent(Unknown Source)
    at java.awt.Component.processEvent(Unknown Source)
    at java.awt.Container.processEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Window.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$400(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)

What am I missing ?

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
SlimenTN
  • 3,383
  • 7
  • 31
  • 78
  • could you post the exact stack trace of this exception – Blip Jun 16 '15 at 13:24
  • @Blip you can check my post please. – SlimenTN Jun 16 '15 at 13:26
  • For NPEs, you also have to provide the line of code where it happens: at pck.DnDTableToList.dragGestureRecognized(DnDTableToList.java:137) - can you add this part of the code? – Risadinha Jun 16 '15 at 13:31
  • @Risadinha I edited the post and I put a comment in the line where the exception happens – SlimenTN Jun 16 '15 at 13:33
  • `TableColumn tb = th.getDraggedColumn(); System.out.println("dragged column: "+tb.getHeaderValue());//---This is where the exception happens` - so `tb` is null, not the header value. Which means that `th.getDraggedColumn()` returns null (I'm just stating this to clarify that the dragged column itself is null and not only its name). – Risadinha Jun 16 '15 at 13:38
  • @Risadinha yes you're right but in the 'while loop' it print in console the name of all columns without exception, so it means that the dragging process of JTableHeader is working fine, so why I can't get the dragged column ? – SlimenTN Jun 16 '15 at 13:42
  • 1
    possible duplicate of [What is a Null Pointer Exception, and how do I fix it?](http://stackoverflow.com/questions/218384/what-is-a-null-pointer-exception-and-how-do-i-fix-it) – Patrik Jun 16 '15 at 13:48

1 Answers1

0

Just quickly looking at the JavaDoc for: http://docs.oracle.com/javase/7/docs/api/java/awt/dnd/DragGestureEvent.html

It shows that the event has a method startDrag(). And in: http://docs.oracle.com/javase/7/docs/api/javax/swing/table/JTableHeader.html#getDraggedColumn() it says:

Returns the the dragged column, if and only if, a drag is in process, otherwise returns null.

So, I guess you need to call event.startDrag() before you can get anything from getDraggedColumn().

Maybe have a look at: http://www.programcreek.com/java-api-examples/index.php?api=java.awt.dnd.DragGestureEvent (and search for other tutorials or code examples).

Risadinha
  • 16,058
  • 2
  • 88
  • 91