setDragImage not working - Java 7

后端 未结 2 2091
没有蜡笔的小新
没有蜡笔的小新 2021-01-13 00:56

I\'m trying to set up code so that the user can drag from a JTable to a JList, and customize the drag image by using the Java 7 function setDragImage in TransferHandler. I g

相关标签:
2条回答
  • 2021-01-13 01:42
    1. As kleopatra says, remove getDragImage() { return null; }
    2. Move TransferHandler#setDragImage(...) from importData(...) to getSourceActions(...)
    3. Fix your makeImageFromString(...)

    //As kleopatra says,
    //public Image getDragImage() {
    //    return null;
    //}
    public boolean importData(TransferHandler.TransferSupport info) {
        //...
        //HERE IS THE CODE TO SET THE DRAG IMAGE
        //XXX: this.setDragImage(makeImageFromString(data));
        //...
    }
    @Override public int getSourceActions(JComponent c) {
      System.out.println("getSourceActions");
      this.setDragImage(makeImageFromString(c));
      return COPY;
    }
    
    FontRenderContext frc = new FontRenderContext(null, true, true);
    JPanel p = new JPanel();
    public BufferedImage makeImageFromString(JComponent c) {
      int width = 100;
      int height = 40;
      BufferedImage br = new BufferedImage(width,height,BufferedImage.TYPE_INT_ARGB);
      Graphics g = br.getGraphics();
      g.setColor(Color.RED);
      g.fillRect(0, 0, width, height);
    
    //*
      JList l = (JList)c;
      ListCellRenderer r = l.getCellRenderer();
      Component comp = r.getListCellRendererComponent(
          l, l.getSelectedValue(), l.getSelectedIndex(), false, false);
      SwingUtilities.paintComponent(g, comp, p, 0, 0, width, height);
    /*/
      String s = "aaaa";
      Rectangle rect = c.getFont().getStringBounds(s, frc).getBounds();
      int tx = (width  - rect.width)/2  - rect.x;
      int ty = (height - rect.height)/2 - rect.y;
      g.setColor(Color.BLACK);
      g.drawString(s, tx, ty);
      System.out.println("made image from " + s);
    //*/
      g.dispose();
      return br;
    }
    

    Note: TransferHandler#setDragImage(java.awt.Image) (Java Platform SE 7 )


    Add SSCCE: How to use TransferHandler#setDragImage(...) method.

    enter image description here

    import java.util.*;
    import java.awt.*;
    import java.awt.image.*;
    import java.awt.datatransfer.*;
    import javax.swing.*;
    public class BasicDnD {
      private JList list;
      public JList makeList() {
        DefaultListModel<String> m = new DefaultListModel<>();
        m.addElement("Martha Washington");
        m.addElement("Abigail Adams");
        m.addElement("Martha Randolph");
        list = new JList<String>(m);
        list.setTransferHandler(new TransferHandler() {
          @Override public boolean canImport(TransferHandler.TransferSupport info) {
            if (!info.isDataFlavorSupported(DataFlavor.stringFlavor)) {
              return false;
            }
            JList.DropLocation dl = (JList.DropLocation)info.getDropLocation();
            if (dl.getIndex() == -1) {
              return false;
            }
            return true;
          }
          @Override public int getSourceActions(JComponent c) {
            setDragImage(makeImageFromString(c));
            return COPY;
          }
          private final JPanel p = new JPanel();
          private BufferedImage br;
          private int width, height;
          private BufferedImage makeImageFromString(JComponent src) {
            JList l = (JList)src;
            int idx = l.getSelectedIndex();
            Rectangle rect = list.getCellBounds(idx,idx);
            if(rect==null) return null;
            if(br==null || rect.width!=width || rect.height!=height) {
              width  = rect.width;
              height = rect.height;
              br = new BufferedImage(width,height,BufferedImage.TYPE_INT_ARGB);
            }
            Component c = l.getCellRenderer().getListCellRendererComponent(
                l, l.getSelectedValue(), idx, false, false);
            Graphics g = br.getGraphics();
            g.clearRect(0,0,width,height);
            SwingUtilities.paintComponent(g, c, p, 0, 0, width, height);
            g.dispose();
            return br;
          }
          @Override protected Transferable createTransferable(JComponent c) {
            JList list = (JList)c;
            Object[] values = list.getSelectedValues();
            StringBuffer buff = new StringBuffer();
            for (int i = 0; i < values.length; i++) {
              Object val = values[i];
              buff.append(val == null ? "" : val.toString());
              if (i != values.length - 1) {
                buff.append("\n");
              }
            }
            return new StringSelection(buff.toString());
          }
        });
        list.setDropMode(DropMode.ON_OR_INSERT);
        list.setDragEnabled(true);
        return list;
      }
      public JComponent makeUI() {
        JPanel panel = new JPanel(new GridLayout(2,1));
        JTextArea textArea = new JTextArea("Drag here from JList!");
        panel.add(new JScrollPane(textArea));
        panel.add(new JScrollPane(makeList()));
        return panel;
      }
      private static void createAndShowGUI() {
        JFrame f = new JFrame("BasicDnD");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setContentPane(new BasicDnD().makeUI());
        f.setSize(320, 320);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
      }
      public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
          @Override public void run() { createAndShowGUI(); }
        });
      }
    }
    
    0 讨论(0)
  • 2021-01-13 01:42

    In order to have a TransferHandler display a custom image (when a drag occurs), you must create a subclass of TransferHandler with the following functions overridden by it:

    1. public int getSourceActions(JComponent) - it must return the actions supported by the source (the JComponent from which the drag initiated), if the action requested by the drag when initiated (see 5) doesnt match, it will not work.
    2. public Transferable createTransferable(JComponent c) - the TransferHandler must return a Transferable object, if null is returned, the drag will not be initiated.
    3. public Image getDragImage() needs to reutn the wanted image, or setDragImage() should be called on an instance of the custom TransferHandler

    To start the drag, override/extend a MouseMotionListener with:

    public void mouseDragged(MouseEvent e){ JComponent jc = (JComponent)e.getSource(); jc.getTransferHandler().exportAsDrag(jc, e,TransferHandler.COPY); }

    And also set the JComponent TransferHandler and MouseMotionListener with:

    myJComponent.setTransferHandler(new myCustomTransferHandler());
    myJComponent.addMouseMotionListener(new myCustomMouseMotionListener());
    

    A complete working example:

    package test;
    
    import javax.swing.*;
    import java.awt.*;
    import java.awt.datatransfer.*;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseMotionListener;
    import javax.imageio.ImageIO;
    
    public class DragTest{
    Image dragImage;
    
    public static void main(String[] args){
        new DragTest();
    }
    
    public DragTest(){
        try{
            dragImage = javax.imageio.ImageIO.read( new java.net.URL(
                    "https://www.icon2s.com/wp-content/uploads/2013/07/black-white-metro-file-icon.png"));
            //dragImage = ImageIO.read(new java.io.File("icon.png")); //can be used to read image from file
        }catch(java.io.IOException e1){
            e1.printStackTrace();
            return;
        }
        dragImage = dragImage.getScaledInstance(64, 64, Image.SCALE_DEFAULT); //scaling the image
        JFrame frame = new JFrame();
        frame.setLayout(null);
        frame.setSize(500,500); frame.setLocationRelativeTo(null); //size and location
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        MyJComponent myJC = new MyJComponent();
        myJC.setBounds(50,50,100,100);
        myJC.addMouseMotionListener(new MouseMotionListener(){
            @Override
            public void mouseDragged(MouseEvent e){
                JComponent src = (JComponent)e.getSource();
                src.getTransferHandler().exportAsDrag(src, e, TransferHandler.COPY); //try to export with the copy action - TransferHandler should support copy 
            }
            @Override
            public void mouseMoved(MouseEvent e){}
        });
        myJC.setTransferHandler(new TransferHandler(){
            @Override public Image getDragImage(){ return(dragImage);}
            @Override public int getSourceActions(JComponent c){
                return(COPY_OR_MOVE); //supporting both copy and move
            }
            @Override public Transferable createTransferable(JComponent c){
                return(new Transferable(){
                    @Override
                    public boolean isDataFlavorSupported(DataFlavor flavor){
                        return false;
                    }
                    @Override
                    public DataFlavor[] getTransferDataFlavors(){
                        return null;
                    }
                    @Override
                    public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, java.io.IOException {
                        return null;
                    }
                });
            }
        });
        frame.add(myJC);
        frame.setVisible(true);
    }
    
    private class MyJComponent extends JComponent{
        @Override
        public void paintComponent(Graphics g){
            g.setColor(Color.RED);
            g.fillRect(0, 0, getWidth(), getHeight());
        }
    }
    }
    
    0 讨论(0)
提交回复
热议问题