java - 从 JTable 标题拖放到 JList

标签 java swing nullpointerexception drag-and-drop

我正在尝试创建一个简单的 Java 应用程序,它允许我从 Jtable 标题 (TableColumn) 中拖动并将列的名称放入 JList 中,这是代码:

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);
   }
}

但是当我尝试获取拖动的列的名称时,我收到了 NullPointerException
异常堆栈跟踪:

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)

我错过了什么?

最佳答案

快速查看 JavaDoc:http://docs.oracle.com/javase/7/docs/api/java/awt/dnd/DragGestureEvent.html

它表明该事件有一个方法startDrag()。并在: http://docs.oracle.com/javase/7/docs/api/javax/swing/table/JTableHeader.html#getDraggedColumn()它说:

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

所以,我想您需要先调用 event.startDrag(),然后才能从 getDraggedColumn() 获取任何内容。

也许看看:http://www.programcreek.com/java-api-examples/index.php?api=java.awt.dnd.DragGestureEvent (并搜索其他教程或代码示例)。

关于java - 从 JTable 标题拖放到 JList,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30868797/

相关文章:

java - 现实生活中非矩形 N 维数组的例子是什么?

java - 如何在 JScrollPane 之上绘制?

java - SwingWorker:在工作线程中创建 Swing 组件并添加到 EDT 中

java - 如果使用 try{}catch{} 捕获错误,代码是否会继续执行

java - setOnEditorActionListener 给出 NullPointerException

java - 使用 BouncyCaSTLe 生成 RSA key 时出现 NullPointerException

java - 如何修复 "java.lang.OutOfMemoryError at sun.misc.Unsafe.allocateMemory(Native Method)"?

java - 严重 : Failed to initialize Jenkins

java - StringBuilder 输出不包括构造函数中提供的字符

java - 这个键绑定(bind)有什么问题?