2012-07-11 19 views
5

Estoy tratando de configurar el código para que el usuario pueda arrastrar desde una JTable a una JList, y personalizar la imagen de arrastre utilizando la función Java 7 setDragImage en TransferHandler. Agarré un ejemplo en el sitio web del tutorial de Java donde enseñan sobre Drag n Drop, y luego agregué un código "setDragImage". Sin embargo, no está funcionando. Consulte el código a continuación y ubique la línea setDragImage() dentro de la función importData. ¿Por qué esto no funciona?setDragImage no funciona - Java 7

/* 
* Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved. 
* 
*/ 

import java.util.*; 
import java.awt.*; 
import java.awt.event.*; 
import java.text.*; 
import java.awt.datatransfer.*; 
import java.awt.image.BufferedImage; 

import javax.swing.*; 
import javax.swing.text.*; 
import javax.swing.tree.*; 
import javax.swing.table.*; 

public class BasicDND extends JPanel implements ActionListener { 
    private static JFrame frame; 
    private JTextArea textArea; 
    private JTextField textField; 
    private JList list; 
    private JTable table; 
    private JTree tree; 
    private JColorChooser colorChooser; 
    private JCheckBox toggleDnD; 

    public BasicDND() { 
     super(new BorderLayout()); 
     JPanel leftPanel = createVerticalBoxPanel(); 
     JPanel rightPanel = createVerticalBoxPanel(); 

     //Create a table model. 
     DefaultTableModel tm = new DefaultTableModel(); 
     tm.addColumn("Column 0"); 
     tm.addColumn("Column 1"); 
     tm.addColumn("Column 2"); 
     tm.addColumn("Column 3"); 
     tm.addRow(new String[]{"Table 00", "Table 01", "Table 02", "Table 03"}); 
     tm.addRow(new String[]{"Table 10", "Table 11", "Table 12", "Table 13"}); 
     tm.addRow(new String[]{"Table 20", "Table 21", "Table 22", "Table 23"}); 
     tm.addRow(new String[]{"Table 30", "Table 31", "Table 32", "Table 33"}); 

     //LEFT COLUMN 
     //Use the table model to create a table. 
     table = new JTable(tm); 
     leftPanel.add(createPanelForComponent(table, "JTable")); 

     //Create a color chooser. 
     colorChooser = new JColorChooser(); 
     leftPanel.add(createPanelForComponent(colorChooser, "JColorChooser")); 

     //RIGHT COLUMN 
     //Create a textfield. 
     textField = new JTextField(30); 
     textField.setText("Favorite foods:\nPizza, Moussaka, Pot roast"); 
     rightPanel.add(createPanelForComponent(textField, "JTextField")); 

     //Create a scrolled text area. 
     textArea = new JTextArea(5, 30); 
     textArea.setText("Favorite shows:\nBuffy, Alias, Angel"); 
     JScrollPane scrollPane = new JScrollPane(textArea); 
     rightPanel.add(createPanelForComponent(scrollPane, "JTextArea")); 

     //Create a list model and a list. 
     DefaultListModel listModel = new DefaultListModel(); 
     listModel.addElement("Martha Washington"); 
     listModel.addElement("Abigail Adams"); 
     listModel.addElement("Martha Randolph"); 
     listModel.addElement("Dolley Madison"); 
     listModel.addElement("Elizabeth Monroe"); 
     listModel.addElement("Louisa Adams"); 
     listModel.addElement("Emily Donelson"); 
     list = new JList(listModel); 
     list.setVisibleRowCount(-1); 
     list.getSelectionModel().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); 

     list.setTransferHandler(new TransferHandler() { 

      public Image getDragImage() { 
       return null; 
      } 

      @Override 
      public boolean canImport(TransferHandler.TransferSupport info) { 
       // we only import Strings 
       if (!info.isDataFlavorSupported(DataFlavor.stringFlavor)) { 
        return false; 
       } 

       JList.DropLocation dl = (JList.DropLocation)info.getDropLocation(); 
       if (dl.getIndex() == -1) { 
        return false; 
       } 
       return true; 
      } 

      public BufferedImage makeImageFromString(String s) { 
       int width = 100; 
       int height = 40; 
       BufferedImage br = new BufferedImage(width,height,BufferedImage.TYPE_INT_ARGB); 
       Graphics g = br.getGraphics(); 
       g.drawString(s, 0, 0); 
       //g.fillRect(0, 0, width, height); 
       System.out.println("made image from " + s); 
       return br; 
      } 

      @Override 
      public boolean importData(TransferHandler.TransferSupport info) { 
       if (!info.isDrop()) { 
        return false; 
       } 

       // Check for String flavor 
       if (!info.isDataFlavorSupported(DataFlavor.stringFlavor)) { 
        displayDropLocation("List doesn't accept a drop of this type."); 
        return false; 
       } 

       JList.DropLocation dl = (JList.DropLocation)info.getDropLocation(); 
       DefaultListModel listModel = (DefaultListModel)list.getModel(); 
       int index = dl.getIndex(); 
       boolean insert = dl.isInsert(); 
       // Get the current string under the drop. 
       String value = (String)listModel.getElementAt(index); 

       // Get the string that is being dropped. 
       Transferable t = info.getTransferable(); 
       String data; 
       try { 
        data = (String)t.getTransferData(DataFlavor.stringFlavor); 
       } 
       catch (Exception e) { return false; } 

       //HERE IS THE CODE TO SET THE DRAG IMAGE 
       this.setDragImage(makeImageFromString(data)); 

       // Display a dialog with the drop information. 
       String dropValue = "\"" + data + "\" dropped "; 
       if (dl.isInsert()) { 
        if (dl.getIndex() == 0) { 
         displayDropLocation(dropValue + "at beginning of list"); 
        } else if (dl.getIndex() >= list.getModel().getSize()) { 
         displayDropLocation(dropValue + "at end of list"); 
        } else { 
         String value1 = (String)list.getModel().getElementAt(dl.getIndex() - 1); 
         String value2 = (String)list.getModel().getElementAt(dl.getIndex()); 
         displayDropLocation(dropValue + "between \"" + value1 + "\" and \"" + value2 + "\""); 
        } 
       } else { 
        displayDropLocation(dropValue + "on top of " + "\"" + value + "\""); 
       } 

     /** This is commented out for the basicdemo.html tutorial page. 
       ** If you add this code snippet back and delete the 
       ** "return false;" line, the list will accept drops 
       ** of type string. 
       // Perform the actual import. 
       if (insert) { 
        listModel.add(index, data); 
       } else { 
        listModel.set(index, data); 
       } 
       return true; 
     */ 
     return false; 
      } 

      @Override 
      public int getSourceActions(JComponent c) { 
       return COPY; 
      } 

      @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); 

     JScrollPane listView = new JScrollPane(list); 
     listView.setPreferredSize(new Dimension(300, 100)); 
     rightPanel.add(createPanelForComponent(listView, "JList")); 

     //Create a tree. 
     DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("Mia Familia"); 
     DefaultMutableTreeNode sharon = new DefaultMutableTreeNode("Sharon"); 
     rootNode.add(sharon); 
     DefaultMutableTreeNode maya = new DefaultMutableTreeNode("Maya"); 
     sharon.add(maya); 
     DefaultMutableTreeNode anya = new DefaultMutableTreeNode("Anya"); 
     sharon.add(anya); 
     sharon.add(new DefaultMutableTreeNode("Bongo")); 
     maya.add(new DefaultMutableTreeNode("Muffin")); 
     anya.add(new DefaultMutableTreeNode("Winky")); 
     DefaultTreeModel model = new DefaultTreeModel(rootNode); 
     tree = new JTree(model); 
     tree.getSelectionModel().setSelectionMode 
       (TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION); 
     JScrollPane treeView = new JScrollPane(tree); 
     treeView.setPreferredSize(new Dimension(300, 100)); 
     rightPanel.add(createPanelForComponent(treeView, "JTree")); 

     //Create the toggle button. 
     toggleDnD = new JCheckBox("Turn on Drag and Drop"); 
     toggleDnD.setActionCommand("toggleDnD"); 
     toggleDnD.addActionListener(this); 

     JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, 
               leftPanel, rightPanel); 
     splitPane.setOneTouchExpandable(true); 

     add(splitPane, BorderLayout.CENTER); 
     add(toggleDnD, BorderLayout.PAGE_END); 
     setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 
    } 

    protected JPanel createVerticalBoxPanel() { 
     JPanel p = new JPanel(); 
     p.setLayout(new BoxLayout(p, BoxLayout.PAGE_AXIS)); 
     p.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 
     return p; 
    } 

    public JPanel createPanelForComponent(JComponent comp, 
              String title) { 
     JPanel panel = new JPanel(new BorderLayout()); 
     panel.add(comp, BorderLayout.CENTER); 
     if (title != null) { 
      panel.setBorder(BorderFactory.createTitledBorder(title)); 
     } 
     return panel; 
    } 

    private void displayDropLocation(final String string) { 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       JOptionPane.showMessageDialog(null, string); 
      } 
     }); 
    } 

    public void actionPerformed(ActionEvent e) { 
     if ("toggleDnD".equals(e.getActionCommand())) { 
      boolean toggle = toggleDnD.isSelected(); 
      textArea.setDragEnabled(toggle); 
      textField.setDragEnabled(toggle); 
      list.setDragEnabled(toggle); 
      table.setDragEnabled(toggle); 
      tree.setDragEnabled(toggle); 
      colorChooser.setDragEnabled(toggle); 
     } 
    } 

    /** 
    * Create the GUI and show it. For thread safety, 
    * this method should be invoked from the 
    * event-dispatching thread. 
    */ 
    private static void createAndShowGUI() { 
     //Create and set up the window. 
     frame = new JFrame("BasicDnD"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     //Create and set up the content pane. 
     JComponent newContentPane = new BasicDND(); 
     newContentPane.setOpaque(true); //content panes must be opaque 
     frame.setContentPane(newContentPane); 

     //Display the window. 
     frame.pack(); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     //Schedule a job for the event-dispatching thread: 
     //creating and showing this application's GUI. 
     javax.swing.SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       //Turn off metal's use of bold fonts 
      UIManager.put("swing.boldMetal", Boolean.FALSE); 
       createAndShowGUI(); 
      } 
     }); 
    } 
} 
+0

No sé acerca de Java 7, pero esto se ha roto en las ventanas desde que se introdujo – MadProgrammer

+0

duplicado posible de [arrastrar y soltar en Java - Pintura algo más que una frontera] (http://stackoverflow.com/questions/11424859/drag-and-drop-in-java-painting-more-than-just-a-border) – trashgod

+0

¿Puedes citar el ejemplo? El método 'setDragImage()' no está definido. No veo el enfoque 'paintComponent()' sugerido anteriormente. – trashgod

Respuesta

5
  1. Como dice kleopatra, retire getDragImage() {return null; }
  2. Mover TransferHandler # setDragImage (...) a partir importData (...) a (...) getSourceActions
  3. Fije su 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; 
} 

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


Añadir SSCCE: Cómo utilizar el método TransferHandler # setDragImage (...).

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

jaja ... que realmente era un hábil escritor de doc .: _La imagen tiene que estar preparado para renderizar en el momento de la llamada. La imagen se almacena por referencia debido a algunas razones de rendimiento. Todavía me estoy rascando la cabeza en cuanto a su significado ;-) – kleopatra

+0

¿Has probado esto? no parece hacer el truco :( – CodeGuy

+0

en realidad si ejecuta el código original desde http://docs.oracle.com/javase/tutorial/uiswing/examples/dnd/BasicDnDProject/src/dnd/BasicDnD.java, No obtengo NINGUNA imagen de borde que aparece cuando lo arrastro. Si ejecuto el archivo jnlp que este código usa http://docs.oracle.com/javase/tutorial/uiswing/examples/dnd/index.html, entonces Obtengo el borde cuando lo arrastro. ¿Puedes probar esto? – CodeGuy

Cuestiones relacionadas