Подтвердить что ты не робот

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

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

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

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

Красная сторона запускает Drag через 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 );
}

}

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

в

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

Когда я это сделал, я увидел поведение, которое вы ожидаете ( "перетащить", напечатанное на консоли после "ЭКСПОРТ" ).