Java: 使用TransferHandler 复制JLabel 的文本时,如何获取两个JLabel 的文本?

Java: How do I get the text of two JLabels when copying JLabel's text with TransferHandler?

如何在使用 TransferHandler 复制 JLabel 的文本时获取两个 JLabel 的文本?

Label1111111 如何在复制到 Label2222222 时保留两个 JLabel 的文本。

因此,我将控制两个Jlabel的文本。这个shape只能拿到JLabel的text,先hold住。预先感谢您的帮助。

public class deneme2 extends JFrame {

    private static final int COPY = 0;
    private static final int NONE = 0;
    private JPanel contentPane;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    deneme2 frame = new deneme2();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public deneme2() {      
        JPanel panel= new JPanel();
        MouseListener listener = new DragMouseAdapter();    

        JLabel label1 = new JLabel("Label1111111", JLabel.CENTER);        
        handlerLabel(label1);
        label1.addMouseListener(listener);
        panel.add(label1);

        JLabel label2 = new JLabel("Label2222222", JLabel.CENTER);
        handlerLabel(label2);   
        label2.addMouseListener(listener);   
        panel.add(label2);

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        contentPane.setLayout(new BorderLayout(0, 0));

        contentPane.add(panel);
        setContentPane(contentPane);
    }

    private void handlerLabel (JLabel lbl)
    {
         lbl.setTransferHandler(new TransferHandler("text") {
                @Override
                protected void exportDone(JComponent source, Transferable data, int action) {
                    if (action == COPY){
                        ((JLabel)lbl.getDropTarget().getDropTargetContext().getComponent()).getText();
                        //((JLabel) source).setText("LabelEmpty");                                      
                        }
                }             
            });
    }

    private class DragMouseAdapter extends MouseAdapter
    {
        public void mousePressed(MouseEvent e)
        {
            JComponent comp = (JComponent)e.getSource();
            TransferHandler handler = comp.getTransferHandler();
            handler.exportAsDrag(comp, e, TransferHandler.COPY);   
        }          
    }   
}

也许是这样。我在你的 handlerLabel 中添加了内部 class MyLabel 和控制台输出。 Ctrl+v 这个在你的 main 下。它将打印以控制每个 MyLabels.

original String 属性
    public class MyLabel extends JLabel {
        String original;

        public MyLabel (String text)
        {
            super(text);
            this.original=text;
        }

        public String getOriginal() {
            return original;
        }

        public void setOriginal(String original) {
            this.original = original;
        }

    }
    public deneme2() {      
        JPanel panel= new JPanel();
        MouseListener listener = (MouseListener) new DragMouseAdapter();    

        MyLabel label1 = new MyLabel("Label1111111");        
        handlerLabel(label1);
        label1.addMouseListener(listener);
        panel.add(label1);

        MyLabel label2 = new MyLabel("Label2222222");
        handlerLabel(label2);   
        label2.addMouseListener(listener);   
        panel.add(label2);

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        contentPane.setLayout(new BorderLayout(0, 0));

        contentPane.add(panel);
        setContentPane(contentPane);
    }

        private void handlerLabel(MyLabel lbl) {
        lbl.setTransferHandler(new TransferHandler("text") {
            @Override
            protected void exportDone(JComponent source, Transferable data, int action) {
                if (action == COPY) {
                    System.out.println(((MyLabel) lbl.getDropTarget().getDropTargetContext().getComponent()).getOriginal());
                }
            }
        });
    }

编辑:检查一下。 Ctrl+V 在你的主目录下。它将打印到源标签的控制台文本和目标标签的文本,还有 original 属性。 Class MyLabel 实现 DropTargetListener ,然后由 new DropTarget(this, this) 注册。然后我们定义在重写的 drop 方法中会发生什么。

 public class MyLabel extends JLabel implements DropTargetListener {

        String original;

        public MyLabel(String text) {
            super(text);
            this.original = text;

            new DropTarget(this, this);

            this.setTransferHandler(new TransferHandler("text"));

            final MouseListener listener = new MouseAdapter() {
                @Override
                public void mousePressed(final MouseEvent me) {
                    final MyLabel label = (MyLabel) me.getSource();
                    final TransferHandler handler = label.getTransferHandler();
                    handler.exportAsDrag(label, me, TransferHandler.COPY);
                }
            };

            this.addMouseListener(listener);
        }

        public String getOriginal() {
            return original;
        }

        public void setOriginal(String original) {
            this.original = original;
        }

        @Override
        public void dragEnter(DropTargetDragEvent dtde) {

        }

        @Override
        public void dragOver(DropTargetDragEvent dtde) {

        }

        @Override
        public void dropActionChanged(DropTargetDragEvent dtde) {

        }

        @Override
        public void dragExit(DropTargetEvent dte) {

        }

        @Override
        public void drop(DropTargetDropEvent dtde) {
            try {
                final String sourceString = (String) dtde.getTransferable().getTransferData(new DataFlavor("application/x-java-jvm-local-objectref; class=java.lang.String"));
                System.out.println("Source: " + sourceString + " target: " + this.getText());
                this.setText(sourceString);
                System.out.println("Original target: "+this.getOriginal());
            } catch (final UnsupportedFlavorException | IOException | ClassNotFoundException e) {
                e.printStackTrace();
            }
        }

    }

    public deneme2() {
        JPanel panel = new JPanel();
        MyLabel label1 = new MyLabel("Label1111111a");
        panel.add(label1);

        MyLabel label2 = new MyLabel("Label2222222b");
        panel.add(label2);

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        contentPane.setLayout(new BorderLayout(0, 0));

        contentPane.add(panel);
        setContentPane(contentPane);
    }
}

EDIT2:以下代码生成 此结果 请参阅此答案末尾的结果:

它还会打印 original 属性 到控制台。这些可以以不同的方式组织(MyLabelMyLabelTransferableMyLabelDropTargetListenerMyLabelTransferHandler classes,只是为了为将来的重构提供一个想法)但它在这个方式太。将其视为您的用例的快速修复。

所以主要 class 是这样的:

 public class Deneme2 extends JFrame {

    private static final int COPY = 0;
    private static final int NONE = 0;

    public static void main(String[] args) {
      Deneme2 mainFrame = new Deneme2();
      SwingUtilities.invokeLater(() -> {//let's get that frame on EDT rollin lambda style:)
          mainFrame.setVisible(true);
      });

    }

    public Deneme2() {
        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());
        MyLabel label1 = new MyLabel("Label1111111a");
        panel.add(label1, BorderLayout.WEST);

        MyLabel label2 = new MyLabel("Label2222222b");
        panel.add(label2, BorderLayout.EAST);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setBounds(100, 100, 450, 300);

        panel.setBorder(new EmptyBorder(5, 5, 5, 5));
        this.add(panel);
    }
}

然后 MyLabel.java :

    public class MyLabel extends JLabel implements DropTargetListener, Transferable {

    String original;
    protected static final DataFlavor MYLABEL_DATA_FLAVOR = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + "; class=\"" + MyLabel.class.getCanonicalName() + "\"",
             "MyLabel label");
    protected static final DataFlavor[] SUPPORTED_FLAVORS = {MYLABEL_DATA_FLAVOR};

    public MyLabel(String text) {
        super(text);
        this.original = text;
        new DropTarget(this, this);
        this.setTransferHandler(new MyLabelTransferHandler()); //here we use our custom TransferHandler
        final MouseListener listener = new MouseAdapter() {
            @Override
            public void mousePressed(final MouseEvent me) {
                final MyLabel label = (MyLabel) me.getSource();
                final TransferHandler handler = label.getTransferHandler();
                handler.exportAsDrag(label, me, TransferHandler.COPY);
            }
        };
        this.addMouseListener(listener);

    }

    public String getOriginal() {
        return original;
    }

    public void setOriginal(String original) {
        this.original = original;
    }

    @Override
    public void dragEnter(DropTargetDragEvent dtde) {
        if (dtde.getTransferable().isDataFlavorSupported(MyLabel.MYLABEL_DATA_FLAVOR)) {
            System.out.println("Drop accept - MyLabel");
            dtde.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
        } else {
            dtde.rejectDrag();
        }
    }

    @Override
    public void dragOver(DropTargetDragEvent dtde) {
        //System.out.println("Drag over");
    }

    @Override
    public void dropActionChanged(DropTargetDragEvent dtde) {
        System.out.println("Action changed");
    }

    @Override
    public void dragExit(DropTargetEvent dte) {
        System.out.println("Exited");

    }

    @Override
    public void drop(DropTargetDropEvent dtde) {
        System.out.println("Drop detected");

        if (dtde.getTransferable().isDataFlavorSupported(MyLabel.MYLABEL_DATA_FLAVOR)) {
            Transferable t = dtde.getTransferable();

            if (t.isDataFlavorSupported(MyLabel.MYLABEL_DATA_FLAVOR)) {
                try {
                    Object transferData = t.getTransferData(MyLabel.MYLABEL_DATA_FLAVOR);

                    if (transferData instanceof MyLabel) {
                        MyLabel mySourceLabel = (MyLabel) transferData;

                        if (!(mySourceLabel.equals(this))) {
                            dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
                            this.setText(mySourceLabel.getText());
                            mySourceLabel.setText("Empty");
                            System.out.println(mySourceLabel.getOriginal() + " " + this.getOriginal());
                        } else {
                            dtde.rejectDrop();
                            System.out.println("Drop rejected - the same MyLabel");
                        }
                    } else {
                        dtde.rejectDrop();
                    }
                } catch (UnsupportedFlavorException | IOException ex) {
                    dtde.rejectDrop();
                }
            } else {
                dtde.rejectDrop();
            }
        }
    }

    @Override
    public DataFlavor[] getTransferDataFlavors() {
        return SUPPORTED_FLAVORS;
    }

    @Override
    public boolean isDataFlavorSupported(DataFlavor flavor) {
        return flavor.equals(MYLABEL_DATA_FLAVOR) || flavor.equals(DataFlavor.stringFlavor);

    }

    @Override
    public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
        if (flavor.equals(MYLABEL_DATA_FLAVOR)) {
            return this;
        } else if (flavor.equals(DataFlavor.stringFlavor)) {
            return this.getText();
        } else {
            throw new UnsupportedFlavorException(flavor);
        }
    }
}

然后 MyLabelTransferHandler.java :

public class MyLabelTransferHandler extends TransferHandler {

    @Override
    public boolean canImport(TransferHandler.TransferSupport support) {
        return (support.getComponent() instanceof MyLabel) && support.isDataFlavorSupported(MyLabel.MYLABEL_DATA_FLAVOR);
    }

    @Override
    public boolean importData(JComponent src, Transferable transferable) {
        return src instanceof MyLabel;
    }

    @Override
    public int getSourceActions(JComponent c) {
        return DnDConstants.ACTION_COPY;
    }

    @Override
    protected Transferable createTransferable(JComponent c) {
        Transferable t = (MyLabel)c;
        return t;
    }

    @Override
    protected void exportDone(JComponent source, Transferable data, int action) {
        System.out.println("Export done.");
    }
}

最终编辑后的结果是这样的:

一点说明:

protected static final DataFlavor MYLABEL_DATA_FLAVOR = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + "; class=\"" + MyLabel.class.getCanonicalName() + "\"",
             "MyLabel label");

在我的标签中。那是重要的线。这将使 getTransferData() return 成为 MyLabel 的相同实例。如果你愿意这样做:

protected static final DataFlavor MYLABEL_DATA_FLAVOR = new DataFlavor(MyLabel.class, "MyLabel label");

您将无法在覆盖的 drop() 方法中将 mySourceLabel 文本更改为 "Empty",因为您将获得该对象的副本。

还有Why shouldn't you extend JFrame and other components?。并且您可以提供对 "Empty" 文本的检查(如果 getText() returns "Empty",则不要更改目标 MyLabel 中的文本)。