Drag and drop does not work properly with jdk 1.5 on a JTable. It is no
longer possible to select and drag more than one row in a JTable. That
behavior existed in jdk 1.4.
The test was conducted with 1.5.0, 1.5.0_02 and 1.5.2_03. The problem exists in all of these. It appears that DnD feature existed with 1.4.2 has broken for 1.5.0 versions.
Test case:
1. Compile and run the Test.java application with jdk 1.4.2-03 (this will
demonstrate how things were working fine before jdk 1.5).
2. Click on the first row in the JTable to select it.
3. Hold down the CTRL key, click on the second row, and begin a drag.
4. You will note that the cursor changes to a '+' icon and both rows remain
selected. This is the correct behaviour.
5. Now, compile and run the Test.java application with jdk 1.5.0-02.
6. Click on the first row in the JTable to select it.
7. Hold down the CTRL key, click on the second row, and begin a drag.
8. You will now see that the cursor changes to a '+' icon and only the
second row remains selected when the drag starts.
This is the bug because CTRL can no longer be used to select and drag
more than one row from a JTable.
import java.awt.dnd.*;
import java.awt.datatransfer.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
public class Test extends JScrollPane
{
public static void main( String[] args )
{
JFrame f = new JFrame();
f.getContentPane().add( new Test() );
f.setVisible( true );
f.pack();
f.addWindowListener( new WindowAdapter() {
public void windowClosing( WindowEvent e )
{
System.exit( 0 );
}
} );
}
Test()
{
super();
DnDJTable table = new DnDJTable();
DefaultTableModel m = new DefaultTableModel( new String[] { "Column
One", "Column Two" }, 0 );
m.addRow( new String[] { "A", "B" } );
m.addRow( new String[] { "C", "D" } );
m.addRow( new String[] { "E", "F" } );
m.addRow( new String[] { "G", "H" } );
m.addRow( new String[] { "I", "J" } );
table.setModel( m );
this.getViewport().setView( table );
}
class DnDJTable extends JTable implements DragGestureListener,
DragSourceListener, DropTargetListener
{
// Data member variables
private DragSource _dSource = null;
private DropTarget _dTarget = null;
/**
* Constructor.
**/
DnDJTable()
{
super();
_dSource = DragSource.getDefaultDragSource();
_dSource.createDefaultDragGestureRecognizer( this,
DnDConstants.ACTION_COPY_OR_MOVE
| DnDConstants.ACTION_LINK,
this );
_dTarget = new DropTarget( this,
DnDConstants.ACTION_COPY_OR_MOVE |
DnDConstants.ACTION_LINK,
this,
true );
}
private String getSelectedRowStrings()
{
int[] selectedRows = getSelectedRows();
StringBuffer sb = new StringBuffer();
for ( int i=0; i < selectedRows.length; i++ ) {
sb.append( getValueAt( selectedRows[ i ] , 0 ) ).append( " " );
sb.append( getValueAt( selectedRows[ i ] , 1 ) ).append( "\r"
);
}
return sb.toString();
}
//------------ DragGestureListener interface methods --------------//
public void dragGestureRecognized( DragGestureEvent event )
{
// get the list item under the mouse (if one exists)
int clickedRow = rowAtPoint( event.getDragOrigin() );
int clickedColumn = columnAtPoint( event.getDragOrigin() );
// was a valid row/column clicked on?
if ( ( clickedRow > -1 ) && ( clickedColumn > -1 ) ) {
// if the row is not selected then add it to the current
selection
if ( !getSelectionModel().isSelectedIndex( clickedRow ) ) {
addRowSelectionInterval( clickedRow, clickedRow );
}
try {
// start drag with initial cursor, transferable, dsource
listener
event.startDrag( DragSource.DefaultCopyNoDrop,
new StringSelection( getSelectedRowStrings() ),
this );
} catch ( InvalidDnDOperationException idoe ) {}
}
}
//---------- end DragGestureListener interface methods ------------//
//------------ DragSourceListener interface methods ---------------//
public void dragOver( DragSourceDragEvent event )
{
DragSourceContext context = event.getDragSourceContext();
int targetAction = event.getTargetActions();
context.setCursor( null );
if ( targetAction == DnDConstants.ACTION_LINK ) {
context.setCursor( DragSource.DefaultLinkDrop );
} else if ( targetAction == DnDConstants.ACTION_COPY ) {
context.setCursor( DragSource.DefaultCopyDrop );
} else if ( targetAction == DnDConstants.ACTION_MOVE ) {
context.setCursor( DragSource.DefaultMoveDrop );
} else {
context.setCursor( DragSource.DefaultCopyNoDrop );
}
}
public void dragDropEnd(DragSourceDropEvent event) {}
public void dragEnter( DragSourceDragEvent event ) {}
public void dragExit( DragSourceEvent event ) {}
public void dropActionChanged ( DragSourceDragEvent event ) {}
//---------- end DragSourceListener interface methods -------------//
//------------ DropTargetListener interface methods ---------------//
public void dragEnter(DropTargetDragEvent e)
{
e.acceptDrag( DnDConstants.ACTION_COPY );
}
public void dragOver(DropTargetDragEvent e)
{
e.acceptDrag( DnDConstants.ACTION_COPY );
}
public void dropActionChanged(DropTargetDragEvent e)
{
e.acceptDrag( DnDConstants.ACTION_COPY );
}
public void drop(DropTargetDropEvent e)
{
// get the list item under the mouse (if one exists)
int row = rowAtPoint( e.getLocation() );
int column = columnAtPoint( e.getLocation() );
try {
// examine the drop action and call onCommand() with the
appropriate commands
Transferable transferable = e.getTransferable();
Object transferables = (Vector)transferable.getTransferData(
DataFlavor.stringFlavor );
switch ( e.getDropAction() ) {
case DnDConstants.ACTION_COPY:
{
// accept the drop
e.acceptDrop( e.getDropAction() );
e.dropComplete(true);
return;
}
default:
{
break;
}
}
} catch ( Exception ex ) {}
// reject the drop
e.rejectDrop();
e.dropComplete( false );
}
public void dragExit(DropTargetEvent e) {}
//---------- end DropTargetListener interface methods -------------//
}
}
###@###.### 2005-04-28 19:46:28 GMT