Seret dan lepas secara real-time di Swing

Saya menggunakan drag and drop di ayunan untuk menempatkan tombol pada salah satu dari empat komponen. Untuk membuatnya lebih menarik daripada hanya mouse yang menunjukkan sesuatu sedang diseret (yang berfungsi dengan baik), saya ingin menunjukkannya secara real time. Ini berfungsi kecuali jika mouse kembali ke komponen yang sedang diseret, pendengar tarik mendaftarkan peristiwa dragExit yang menghilangkan tombol yang menyebabkan pendengar fokus kembali pada komponen induk dan mengaktifkan dragEnter yang menyebabkan kedipan. Saya perlu membuat tombol tersebut tidak memengaruhi pendengar drag. Ada ide?

menyeret DndButton yang mengucapkan halo di antara empat DndLabel

ini jlabel yang saya tambahkan juga (saya tahu jlabel bukan pilihan yang baik tetapi berfungsi dengan baik dan dapat dengan mudah menampilkan gambar yang saya perlukan)

import java.awt.Point;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.*;
import java.io.IOException;
import javax.swing.*;


//and here is the button to drag   
public class DndLabel extends JLabel implements DropTargetListener {

    private DropTarget target;
    private DndButton button;
    public DndLabel last;

    //initialize the JTable with the data
    public DndLabel() {
        super();

        //mark this a DropTarget
        target = new DropTarget(this, this);

        //have it utilize a custom transfer handler
        setTransferHandler(new MyTransferHandler());
    }

    public void dragEnter(DropTargetDragEvent dtde) {
        System.out.println("enter");

        try {
            //get the Point where the drop occurred
            Point loc = dtde.getLocation();

            //get Transfer data
            Transferable t = dtde.getTransferable();

            //get the Data flavors transferred with the Transferable
            DataFlavor[] d = t.getTransferDataFlavors();

            button = (DndButton) t.getTransferData(d[0]);

            button.setBounds(loc.x, 0, 100, 50);

            add(button);

            //and if the DataFlavors match for the DnDTable 
            //(ie., we don't want an ImageFlavor marking an image transfer)
            if (getTransferHandler().canImport(this, d)) {

                //then import the Draggable JComponent and repaint() the JTable
                ((MyTransferHandler) getTransferHandler()).importData(this, (DndButton) t.getTransferData(d[0]), loc);
                repaint();
            } else {
                return;
            }
        } catch (UnsupportedFlavorException  ex) {
            ex.printStackTrace();
        } catch(IOException ex){
            ex.printStackTrace();
        }
    }

    @Override
    public void dragOver(DropTargetDragEvent dtde) {
        button.setLocation(dtde.getLocation().x, 0);
    }

    public void dragExit(DropTargetEvent dte) {
        System.out.println("remove");

        last = null;
        remove(button);
        repaint();

    }

    //This is what happens when a Drop occurs
    public void drop(DropTargetDropEvent dtde) {
        System.out.println("drop!");
        try {
            //get the Point where the drop occurred
            Point loc = dtde.getLocation();

            //get Transfer data
            Transferable t = dtde.getTransferable();

            //get the Data flavors transferred with the Transferable
            DataFlavor[] d = t.getTransferDataFlavors();

            DndButton tempButton = (DndButton) t.getTransferData(d[0]);

            tempButton.setBounds(loc.x, 0, 100, 50);

            add(tempButton);

            //and if the DataFlavors match for the DnDTable 
            //(ie., we don't want an ImageFlavor marking an image transfer)
            if (getTransferHandler().canImport(this, d)) {

                //then import the Draggable JComponent and repaint() the JTable
                ((MyTransferHandler) getTransferHandler()).importData(this, (DndButton) t.getTransferData(d[0]), loc);
                repaint();
            } else {
                return;
            }

        } catch (UnsupportedFlavorException ex) {
            ex.printStackTrace();
        }catch(IOException ex){

        }finally {
            dtde.dropComplete(true);
        }
    }

    @Override
    public void dropActionChanged(DropTargetDragEvent dtde) {
    }

    class MyTransferHandler extends TransferHandler {

        //tests for a valid JButton DataFlavor
        public boolean canImport(JComponent c, DataFlavor[] f) {
            DataFlavor temp = new DataFlavor(DndButton.class, "JButton");
            for (DataFlavor d : f) {
                if (d.equals(temp)) {
                    return true;
                }

            }
            return false;
        }

        //add the data into the JTable
        public boolean importData(JComponent comp, Transferable t, Point p) {
            try {
                DndButton tempButton = (DndButton) t.getTransferData(new DataFlavor(DndButton.class, "JButton"));

            } catch (UnsupportedFlavorException | IOException ex) {
                System.err.println(ex);
            }
            return true;
        }
    }
}
class DndButton extends JButton implements Transferable, DragSourceListener, DragGestureListener {

    //marks this JButton as the source of the Drag
    private DragSource source;
    private TransferHandler t;

    public DndButton() {
        this("");
    }

    public DndButton(String message) {
        super(message);

        //The TransferHandler returns a new DnDButton
        //to be transferred in the Drag
        t = new TransferHandler() {

            public Transferable createTransferable(JComponent c) {
                return new DndButton(getText());
            }
        };
        setTransferHandler(t);

        //The Drag will copy the DnDButton rather than moving it
        source = new DragSource();
        source.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_MOVE, this);
    }

    //The DataFlavor is a marker to let the DropTarget know how to
    //handle the Transferable
    public DataFlavor[] getTransferDataFlavors() {
        return new DataFlavor[]{new DataFlavor(DndButton.class, "JButton")};
    }

    public boolean isDataFlavorSupported(DataFlavor flavor) {
        return true;
    }

    public Object getTransferData(DataFlavor flavor) {
        return this;
    }

    public void dragEnter(DragSourceDragEvent dsde) {
    }

    public void dragOver(DragSourceDragEvent dsde) {
        //this.setLocation(dsde.getX()-150,0);
    }

    public void dropActionchanged(DragSourceDragEvent dsde) {
    }

    public void dragExit(DragSourceEvent dse) {
    }

    //when the drag finishes, then repaint the DnDButton
    //so it doesn't look like it has still been pressed down
    public void dragDropEnd(DragSourceDropEvent dsde) {
        // JComponent c = (JComponent) this.getParent();
        //c.remove(this);
        //c.repaint();
    }

    //when a DragGesture is recognized, initiate the Drag
    public void dragGestureRecognized(DragGestureEvent dge) {
        source.startDrag(dge, DragSource.DefaultMoveDrop, DndButton.this, this);
    }

    @Override
    public void dropActionChanged(DragSourceDragEvent dsde) {
    }
}

class Main {

    public static void main(String[] args) {
        JFrame f = new JFrame("sscce");
        f.setBounds(0, 0, 500, 80);
        f.setVisible(true);
        DndLabel trackOne = new DndLabel();
        trackOne.setBounds(0, 0, 500, 50);
        f.add(trackOne);
        DndButton b = new DndButton("hello");
        b.setBounds(0, 0, 100, trackOne.getHeight());

        trackOne.add(b);
        trackOne.revalidate();
        trackOne.repaint();
    }
}

person ghostbust555    schedule 05.08.2012    source sumber
comment
Untuk bantuan yang lebih baik dan lebih cepat, posting SSCCE.   -  person Andrew Thompson    schedule 05.08.2012
comment
@Andrew Thompson Oke saya mengubah kode menjadi SSCCE   -  person ghostbust555    schedule 05.08.2012


Jawaban (1)


Saya pribadi mungkin akan menolak melakukan hal seperti ini. Masalahnya adalah, setiap kali Anda menambahkan komponen, komponen tersebut mengganggu pendengar mouse dalam hierarki, menyebabkan penampung diberi tahu tentang peristiwa keluar, yang menyebabkan tombol dihapus dan penampung diberi tahu tentang peristiwa masuk. dan siklus itu terus berlanjut.

Secara pribadi, saya akan melakukan salah satu dari dua hal. Saya juga akan melakukannya

  • Cat ke panel kaca representasi tombol atau
  • Lukis representasi tombol pada panel drag

Ini menghilangkan kemungkinan tombol menyebabkan gangguan pada pendengar mouse yang terlibat.

Lihat Gambar Seret Saya lebih baik dari milikmu. Saat Anda menggali sedikit di sana, Tim membuat sejumlah artikel bagus tentang drag'n'drop yang layak untuk dibaca

person MadProgrammer    schedule 05.08.2012
comment
Ya, saya suka barang-barang Tim, sangat membantu saya - person MadProgrammer; 05.08.2012