Почему DragHandler exportAsDrag отключает мой MouseMotionListener?

Я хочу реализовать простой JComponent-Drag-and-Drop с превью от O.Reilly-Swing.Hacks Hack 69. Прозрачный Drag-and-Drop. Моя проблема заключается в том, что если TransferHandler запустит Drag, то MouseMotionListener прекратит выполнение mouseDragged().

Вот небольшой пример кода:

Небольшое окно с зеленой и красной стороной. Зеленая сторона не запускает Drag, всегда выполняется mouseDragged (), но exportDone () никогда не будет достигнут.

Красная сторона запускает перетаскивание через exportAsDrag (), но после этого mouseDragged () больше не будет работать.

public class Drag extends JPanel implements Transferable, MouseMotionListener, MouseListener {
public Drag() {
    this.setTransferHandler( new TransferHandler() {
        @Override
        protected Transferable createTransferable( JComponent c ) {
            return (Drag)c;
        }
        @Override
        public boolean canImport( JComponent comp, DataFlavor[] transferFlavors ) {
            return false;
        }
        @Override
        public int getSourceActions( JComponent c ) {
            return MOVE;
        }
        @Override
        protected void exportDone( JComponent source, Transferable data, int action ) {
            super.exportDone( source, data, action );
            System.out.println( "done" );
        }
    } );
    this.setPreferredSize( new Dimension( 200, 100 ) );
    this.addMouseMotionListener( this );
    this.addMouseListener( this );
}
@Override
public void mouseDragged( MouseEvent e ) {
    System.out.println( "drag" );
}
@Override
public void mouseMoved( MouseEvent e ) { }
@Override
public void mousePressed( MouseEvent e ) {
    if( e.getX() > getWidth() / 2 ) {
        System.out.println( "EXPORT" );
        this.getTransferHandler().exportAsDrag( this, e, TransferHandler.MOVE );
    } else {
        System.out.println( "no Export" );
    }
}
@Override
public void paint( Graphics g ) {
    super.paint( g );
    g.setColor( Color.GREEN );
    g.fillRect( 0, 0, getWidth() / 2, getHeight() );
    g.setColor( Color.RED );
    g.fillRect( getWidth() / 2, 0, getWidth(), getHeight() );
}
public boolean isDataFlavorSupported( DataFlavor flavor ) {
    return false;
}
public DataFlavor[] getTransferDataFlavors() {
    return new DataFlavor[] {};
}
public Object getTransferData( DataFlavor flavor ) throws UnsupportedFlavorException, IOException {
    return new Object();
}
@Override
public void mouseClicked( MouseEvent e ) { }
@Override
public void mouseEntered( MouseEvent e ) { }
@Override
public void mouseExited( MouseEvent e ) { }
@Override
public void mouseReleased( MouseEvent e ) { }

static public void main( String[] s ) {
    JFrame f = new JFrame();
    f.setSize( 200, 200 );
    f.getContentPane().setLayout( new BorderLayout() );
    Drag d = new Drag();
    f.getContentPane().add( d, BorderLayout.NORTH );
    f.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
    f.setVisible( true );
}

}

2 ответа

Решение

После запуска действия перетаскивания событие движения не будет отправлено как обычное событие перетаскивания мышью. Во время перетаскивания DragSourceDragEvent запускается при перемещении мыши. В следующем примере будет напечатано "DRAGMOUSEMOVED" при перетаскивании красной области. Просто вставьте источник ниже в ваш конструктор. DragSourceDragEvent имеет большинство методов MouseEvent, поэтому он должен быть хорошей альтернативой.

DragSource.getDefaultDragSource().addDragSourceMotionListener(new DragSourceMotionListener() {
    @Override
    public void dragMouseMoved(DragSourceDragEvent dsde) {
        System.out.println("DRAGMOUSEMOVED");
    }
});

Измените эту строку:

this.getTransferHandler().exportAsDrag( this, e, TransferHandler.MOVE );

чтобы:

this.getTransferHandler().exportAsDrag( this, e, TransferHandler.NONE );

Когда я это сделал, я увидел ожидаемое вами поведение ("перетаскивание" печаталось на консоль после "EXPORT").

Другие вопросы по тегам