Skip to Main Content

Java SE (Java Platform, Standard Edition)

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Need Help with JTable Drag and Drop TransferHandler

843805May 23 2006 — edited May 25 2006
Hi,
I have one table with a Member List and then several other tables to witch I want to move the Members using Drag and Drop.
I used THIS CODE and it woks fine.
Then i tried to restrict the other tables to only 12 rows and it works fine in Single Selection Mode, but as soon as i allow multiple selections it is possible to Move more than 12 Member into one table. I tried several things but none was fine.
I just wondered if i have to add a new Transfer Handler to each table or if i have to add the same TransferHandler to each table? At the moment each table has its own Handler.
I need to know how many rows are selected and how many rows are in the table i want to drop them. I havent found a way to tell the accepting TransferHandler how many Rows are selected.


I also wanted to ask if someone can explain me the ViewportTransferHandler. I understand how the String and TableTransferHandler works but i'm not quite sure about the ViewportHandler especially about the getView() Method.


Another thing is that I highlight a single row in those tables on doubleclick or keypress, but as soon as i highlighted a row I get a NullPointerException when i want to move a row from that table, but it still works:
java.lang.NullPointerException
	at javax.swing.plaf.basic.BasicTableUI$TableDropTargetListener.restoreComponentState(Unknown Source)
	at javax.swing.plaf.basic.BasicDropTargetListener.dragExit(Unknown Source)
	at javax.swing.TransferHandler$SwingDropTarget.dragExit(Unknown Source)
	at sun.awt.dnd.SunDropTargetContextPeer.processExitMessage(Unknown Source)
	at sun.awt.dnd.SunDropTargetContextPeer.access$700(Unknown Source)
	at sun.awt.dnd.SunDropTargetContextPeer$EventDispatcher.dispatchExitEvent(Unknown Source)
	at sun.awt.dnd.SunDropTargetContextPeer$EventDispatcher.dispatchEvent(Unknown Source)
	at sun.awt.dnd.SunDropTargetEvent.dispatch(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.trackMouseEnterExit(Unknown Source)
	at java.awt.LightweightDispatcher.processDropTargetEvent(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.dispatchEvent(Unknown Source)
	at java.awt.EventDispatchThread.pumpOneEventForHierarchy(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)
Abd here the code of my CreateTable class:
public class CreateTable extends JPanel {
    
	//private String tableID = null;
	
	public CreateTable(String tableId) {
		createTable(tableId);
    }
    private void createTable(String tableId) {
   
        DefaultTableModel model = new DefaultTableModel() {
        	public boolean isCellEditable(int rowIndex, int columnIndex) {
                return false;
        }};
              
    	model.addColumn(tableId);
         
        table = new JTable(model);
       	table.getTableHeader().setReorderingAllowed(false);
      	//table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
       	table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
       	JScrollPane scrollPane = new JScrollPane(table);
   		scrollPane.setPreferredSize(new Dimension(200,211));
   		table.setDragEnabled(true);

    	table.setTransferHandler(new TableTransferHandler());
    	scrollPane.getViewport().setTransferHandler(new ViewportTransferHandler());
   		//JPanel panel = new JPanel();
   		this.add(scrollPane);
   		this.setBorder(BorderFactory.createTitledBorder(tableId));
        renderer = new MyRenderer();
        table.setDefaultRenderer(Object.class, renderer);
        table.setDefaultRenderer(Boolean.class, renderer);
        //protectRows(1,2);
        scrollPane.setViewportView(table);

        //On Keypress highlight row
        table.addKeyListener(new KeyAdapter(){
            public void keyPressed(KeyEvent e){
                if (e.getKeyChar() == 'l'){
                	 protectRows(table.getSelectedRow());
                }
            }
            } );
        
        //On DoubleClick highlight row
        table.addMouseListener(new MouseAdapter(){
             public void mouseClicked(MouseEvent e){
                 if (e.getClickCount() == 2){
                 	 protectRows(table.getSelectedRow());
                 }
             }
             } );
    }
    
    private void protectRows(int rowFrom){
        //if(rowsProtected.size() == 0)
    	if(rowsProtected.isEmpty())
        	rowsProtected.add(""+rowFrom);
        else if(rowsProtected.contains(""+rowFrom))
        	rowsProtected.clear();
        else {
        	rowsProtected.clear();
        	rowsProtected.add(""+rowFrom);
        }
        table.updateUI();
    }

    private JTable table;
    private DefaultTableCellRenderer renderer;
    private HashSet rowsProtected = new HashSet();
    private DefaultTableModel tablemodel;
    
    class MyRenderer extends DefaultTableCellRenderer {
        public MyRenderer(){
            super();
        }
        public Component getTableCellRendererComponent(
                JTable table,
                Object value,
                boolean isSelected,
                boolean hasFocus,
                int row,
                int column) {
            Color background, foreground;
            if(rowsProtected.contains(""+row)){
                background = Color.yellow;
                foreground = Color.blue;
                if(isSelected){
                    background = Color.orange;
                }
            }else{
                background = Color.white;
                foreground = Color.black;
                if(isSelected){
                    background = Color.lightGray;
                }
            }
            setBackground(background);
            setForeground(foreground);
            super.setValue(value);
            return this;
        }
    }
}

abstract class StringTransferHandler extends TransferHandler {
    
	public int rows;
	public int rows1;
	
	protected abstract String exportString(JComponent c);
    protected abstract void importString(JComponent c, String str);
    protected abstract void cleanup(JComponent c, boolean remove);
    protected Transferable createTransferable(JComponent c) {
        return new StringSelection(exportString(c));
    }
    public int getSourceActions(JComponent c) {
        return COPY_OR_MOVE;
    }
  
    public boolean importData(JComponent c, Transferable t) {
    	
    	if (canImport(c, t.getTransferDataFlavors())) {
            try {
                String str = (String)t.getTransferData(DataFlavor.stringFlavor);
                importString(c, str);
                return true;
            } catch (UnsupportedFlavorException ufe) {
            } catch (IOException ioe) {
            }
        }
        return false;
    }
    protected void exportDone(JComponent c, Transferable data, int action) {
    	cleanup(c, action == MOVE);
    }
    public boolean canImport(JComponent c, DataFlavor[] flavors) {

    	//More than 12 people in table?
        JTable t = (JTable) c;
        if(t.getRowCount() >= 12) return false;
    	
    	for (int ndx = 0; ndx < flavors.length; ndx++) {
            if (DataFlavor.stringFlavor.equals(flavors[ndx])) {
                return true;
            }
        }
        return false;
    }
}


class TableTransferHandler extends StringTransferHandler {
	
	public JTable target;
    public int[] rows = null;
    public int addIndex = -1; //Location where items were added
    public int addCount = 0;  //Number of items added.
    
    protected String exportString(JComponent c) {
        JTable table = (JTable)c;
        rows = table.getSelectedRows();

        super.rows1 = rows.length;
        
        int colCount = table.getColumnCount();
        StringBuffer buff = new StringBuffer();
        for (int ndx = 0; ndx < rows.length; ndx++) {
            for (int j = 0; j < colCount; j++) {
                Object val = table.getValueAt(rows[ndx], j);
                buff.append(val == null ? "" : val.toString());
                if (j != colCount - 1) {
                    buff.append(",");
                }
            }
            if (ndx != rows.length - 1) {
                buff.append("\n");
            }
        }
        return buff.toString();
    }
    protected void importString(JComponent c, String str) {
        target = (JTable)c;
        
        DefaultTableModel model = (DefaultTableModel)target.getModel();
        int index = target.getSelectedRow();
        //Prevent the user from dropping data back on itself.
        //For example, if the user is moving rows #4,#5,#6 and #7 and
        //attempts to insert the rows after row #5, this would
        //be problematic when removing the original rows.
        //So this is not allowed.
        if (rows != null && index >= rows[0] - 1 &&
                index <= rows[rows.length - 1]) {
            rows = null;
            return;
        }
        int max = model.getRowCount();
        if (index < 0) {
            index = max;
        } else {
            index++;
            if (index > max) {
                index = max;
            }
        }
        addIndex = index;
        String[] values = str.split("\n");
        addCount = values.length;
        int colCount = target.getColumnCount();
        for (int ndx = 0; ndx < values.length ; ndx++) {
            model.insertRow(index++, values[ndx].split(","));
        }
        //If we are moving items around in the same table, we
        //need to adjust the rows accordingly, since those
        //after the insertion point have moved.
        if (rows!= null && addCount > 0) {
            for (int ndx = 0; ndx < rows.length; ndx++) {
                if (rows[ndx] > addIndex) {
                    rows[ndx] += addCount;
                }
            }
        }
    }
    protected void cleanup(JComponent c, boolean remove) {
        JTable source = (JTable)c;
        if (remove && rows != null) {
            DefaultTableModel model =
                    (DefaultTableModel)source.getModel();
            for (int ndx = rows.length - 1; ndx >= 0; ndx--) {
                model.removeRow(rows[ndx]);
            }
        }
        rows = null;
        addCount = 0;
        addIndex = -1;
    }
}

 class ViewportTransferHandler extends TransferHandler {
    private JComponent getView(JComponent comp) {
        JViewport viewport = (JViewport) comp;
        return (JComponent) viewport.getView();
    }
    public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) {
        JComponent view = getView(comp);
        return view.getTransferHandler().canImport(view, transferFlavors);
    }
    public void exportAsDrag(JComponent comp, InputEvent e, int action) {
        JComponent view = getView(comp);
        view.getTransferHandler().exportAsDrag(view, e, action);
    }
    public void exportToClipboard(JComponent comp, Clipboard clip, int action) {
        JComponent view = getView(comp);
        view.getTransferHandler().exportToClipboard(view, clip, action);
    }

    public int getSourceActions(JComponent c) {
        JComponent view = getView(c);
        return view.getTransferHandler().getSourceActions(view);
    }
    public boolean importData(JComponent comp, Transferable t) {
        JComponent view = getView(comp);
        return view.getTransferHandler().importData(view, t);
    }

}
Thanks for your help
spoertsch
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Jun 22 2006
Added on May 23 2006
5 comments
832 views