2017-03-02 5 views
0

Ich habe JTable mit einigen Zeilen. Ich möchte beim Verschieben einer Zeile mit der Maus (Drag & Drop) diese Zeile zusammen mit Maus- und Tabellenzeilen verschieben, um neu angeordnet zu werden, wenn sich die Maus bewegt (wie das Verschieben von JTables Spalten). Diese jsfiddle ist genau das, was ich will, aber ich muss es in Java Swing (oder gif Bild unten. Beispiel ist von here, aber ich kann es nicht verstehen).Zeile mit der Maus in JTable verschieben

enter image description here

Mein TransferHandler:

public class TableRowTransferHandler extends TransferHandler { 

    private final DataFlavor localObjectFlavor = new ActivationDataFlavor(Integer.class, "application/x-java-Integer;class=java.lang.Integer", "Integer Row Index"); 
    private JTable table = null; 

    private static final Logger logger = Logger.getLogger(TableRowTransferHandler.class.getName()); 

    public TableRowTransferHandler(JTable table) { 
     this.table = table; 
    } 

    @Override 
    protected Transferable createTransferable(JComponent c) { 
     assert (c == table); 
     return new DataHandler(table.getSelectedRow(), localObjectFlavor.getMimeType()); 
    } 

    @Override 
    public boolean canImport(TransferHandler.TransferSupport info) { 
     boolean b = info.getComponent() == table && info.isDrop() && info.isDataFlavorSupported(localObjectFlavor); 
     table.setCursor(b ? DragSource.DefaultMoveDrop : DragSource.DefaultMoveNoDrop); 
     return b; 
    } 

    @Override 
    public int getSourceActions(JComponent c) { 
     return TransferHandler.COPY_OR_MOVE; 
    } 

    @Override 
    public boolean importData(TransferHandler.TransferSupport info) { 
     JTable target = (JTable) info.getComponent(); 
     JTable.DropLocation dl = (JTable.DropLocation) info.getDropLocation(); 
     int index = dl.getRow(); 
     int max = table.getModel().getRowCount(); 
     if (index < 0 || index > max) { 
      index = max; 
     } 
     target.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 
     try { 
      Integer rowFrom = (Integer) info.getTransferable().getTransferData(localObjectFlavor); 
      if (rowFrom != -1 && rowFrom != index) { 
       ((Reorderable) table.getModel()).reorder(rowFrom, index); 
       if (index > rowFrom) { 
        index--; 
       } 
       target.getSelectionModel().addSelectionInterval(index, index); 
       return true; 
      } 
     } catch (UnsupportedFlavorException | IOException e) { 
      e.printStackTrace(); 
      logger.log(Level.SEVERE, null, e); 
     } 
     return false; 
    } 

    @Override 
    protected void exportDone(JComponent c, Transferable t, int act) { 
     if ((act == TransferHandler.MOVE) || (act == TransferHandler.NONE)) { 
      table.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 
     } 
    } 
} 

, dass eine einfache Einstellungen ist, dass ich zu JTable verwenden:

childrenTable.setDragEnabled(true); 
    childrenTable.setDropMode(DropMode.INSERT); 
    childrenTable.setTransferHandler(new TableRowTransferHandler(childrenTable)); 
    childrenTable.setRowSelectionAllowed(true); 
    childrenTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); 

Im Moment, wenn Sie nur Zeile mit der Maus zwischen den Reihen bewegen haben eine fette Linie (wie in der roten Ellipse unten im Bild). Wenn es unmöglich ist, Zeilen so zu bewegen, dass sie sich so bewegen, möchte ich, dass diese fettgedruckte Zeile in einer ganzen Zeile erscheint (nicht nur in einer Zelle).

enter image description here

Antwort

3

den Ausschnitt aus den Swing-Tutorial auf Drag Lesen und für die Grundlagen fallen.

Hier ist ein alter Code, den ich irgendwo mit einem benutzerdefinierten TransferHandler im Web gefunden eine JTable zu unterstützen:

import javax.swing.*; 
import javax.swing.border.*; 
import javax.swing.table.*; 
import java.awt.*; 
import java.awt.datatransfer.*; 
import java.awt.event.*; 
import java.io.IOException; 
public class DnD_Demo extends JFrame { 
    public DnD_Demo() { 
     setTitle("DnD Demo (Version 3)"); 
     JTextArea tips = new JTextArea("1. Select a row in Table A. " + 
       "Press the row again and drag. \n  " + 
       "As you drag the cursor icon over Table B, the row that is currently under the cursor highlights " + 
       "- the new data will be inserted after the selected row. \n  " + 
       "Drop the row onto Table B. Note that the row has been removed from Table A, " + 
       "and now appears in Table B. \n" + 
       "2. Select two rows from Table A and drop onto Table B. " + 
       "Now there are two new rows in Table B. "); 
     tips.setEditable(false); 
     tips.setBackground(new Color(255,255,204)); 
     tips.setBorder(new LineBorder(Color.orange,5)); 
     getContentPane().add(tips,BorderLayout.NORTH); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     JPanel panel = new JPanel(new GridLayout(2,1)); 
     panel.add(createTable("Table A")); 
     panel.add(createTable("Table B")); 
     getContentPane().add(panel,BorderLayout.CENTER); 
     pack(); 
    } 
    private JPanel createTable(String tableId) { 
     DefaultTableModel model = new DefaultTableModel(); 
     model.addColumn("Column 0"); 
     model.addColumn("Column 1"); 
     model.addColumn("Column 2"); 
     model.addColumn("Column 3"); 
     model.addRow(new String[]{tableId+" 00", tableId+" 01", tableId+" 02", tableId+" 03"}); 
     model.addRow(new String[]{tableId+" 10", tableId+" 11", tableId+" 12", tableId+" 13"}); 
     model.addRow(new String[]{tableId+" 20", tableId+" 21", tableId+" 22", tableId+" 23"}); 
     model.addRow(new String[]{tableId+" 30", tableId+" 31", tableId+" 32", tableId+" 33"}); 
     JTable table = new JTable(model); 
     table.getTableHeader().setReorderingAllowed(false); 
     table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); 
     JScrollPane scrollPane = new JScrollPane(table); 
     scrollPane.setPreferredSize(new Dimension(400,100)); 
     table.setDragEnabled(true); 
     table.setTransferHandler(new TableTransferHandler()); 
     JPanel panel = new JPanel(); 
     panel.add(scrollPane); 
     panel.setBorder(BorderFactory.createTitledBorder(tableId)); 
     return panel; 
    } 
    public static void main(String[] args) { 
     new DnD_Demo().setVisible(true); 
    } 

    abstract class StringTransferHandler extends TransferHandler { 
     protected abstract String exportString(JComponent c); 
     protected abstract void importString(JComponent c, String str); 
     protected abstract void cleanup(JComponent c, boolean remove); 
     protected Transferable createTransferable(JComponent c) { 
      return new StringSelection(exportString(c)); 
     } 
     public int getSourceActions(JComponent c) { 
      return COPY_OR_MOVE; 
     } 
     public boolean importData(JComponent c, Transferable t) { 
      if (canImport(c, t.getTransferDataFlavors())) { 
       try { 
        String str = (String)t.getTransferData(DataFlavor.stringFlavor); 
        importString(c, str); 
        return true; 
       } catch (UnsupportedFlavorException ufe) { 
       } catch (IOException ioe) { 
       } 
      } 
      return false; 
     } 
     protected void exportDone(JComponent c, Transferable data, int action) { 
      cleanup(c, action == MOVE); 
     } 
     public boolean canImport(JComponent c, DataFlavor[] flavors) { 
      for (int i = 0; i < flavors.length; i++) { 
       if (DataFlavor.stringFlavor.equals(flavors[i])) { 
        return true; 
       } 
      } 
      return false; 
     } 
    } 
    class TableTransferHandler extends StringTransferHandler { 
     public JTable target; 
     public int[] rows = null; 
     public int addIndex = -1; //Location where items were added 
     public int addCount = 0; //Number of items added. 
     protected String exportString(JComponent c) { 
      JTable table = (JTable)c; 
      rows = table.getSelectedRows(); 
      int colCount = table.getColumnCount(); 
      StringBuffer buff = new StringBuffer(); 
      for (int i = 0; i < rows.length; i++) { 
       for (int j = 0; j < colCount; j++) { 
        Object val = table.getValueAt(rows[i], j); 
        buff.append(val == null ? "" : val.toString()); 
        if (j != colCount - 1) { 
         buff.append(","); 
        } 
       } 
       if (i != rows.length - 1) { 
        buff.append("\n"); 
       } 
      } 
      return buff.toString(); 
     } 
     protected void importString(JComponent c, String str) { 
      target = (JTable)c; 
      DefaultTableModel model = (DefaultTableModel)target.getModel(); 
      int index = target.getSelectedRow(); 
      //Prevent the user from dropping data back on itself. 
      //For example, if the user is moving rows #4,#5,#6 and #7 and 
      //attempts to insert the rows after row #5, this would 
      //be problematic when removing the original rows. 
      //So this is not allowed. 
      if (rows != null && index >= rows[0] - 1 && 
        index <= rows[rows.length - 1]) { 
       rows = null; 
       return; 
      } 
      int max = model.getRowCount(); 
      if (index < 0) { 
       index = max; 
      } else { 
       index++; 
       if (index > max) { 
        index = max; 
       } 
      } 
      addIndex = index; 
      String[] values = str.split("\n"); 
      addCount = values.length; 
      int colCount = target.getColumnCount(); 
      for (int i = 0; i < values.length ; i++) { 
       model.insertRow(index++, values[i].split(",")); 
      } 
      //If we are moving items around in the same table, we 
      //need to adjust the rows accordingly, since those 
      //after the insertion point have moved. 
      if (rows!= null && addCount > 0) { 
       for (int i = 0; i < rows.length; i++) { 
        if (rows[i] > addIndex) { 
         rows[i] += addCount; 
        } 
       } 
      } 
     } 
     protected void cleanup(JComponent c, boolean remove) { 
      JTable source = (JTable)c; 
      if (remove && rows != null) { 
       DefaultTableModel model = 
         (DefaultTableModel)source.getModel(); 
       for (int i = rows.length - 1; i >= 0; i--) { 
        model.removeRow(rows[i]); 
       } 
      } 
      rows = null; 
      addCount = 0; 
      addIndex = -1; 
     } 
    } 
} 
2

Ich denke, dass ListTransferHandler.java für Artikel Swapping von JList im Swing tutorial wird auch hilfreich sein. Hier

ist ein Beispiel, das ich ListTransferHandler für JTable geändert:

import java.awt.*; 
import java.awt.datatransfer.*; 
import java.awt.dnd.*; 
import java.awt.event.*; 
import java.io.IOException; 
import java.util.*; 
import java.util.List; 
import javax.activation.*; 
import javax.swing.*; 
import javax.swing.table.*; 

public final class TableRowsDnDTest { 
    private final TransferHandler handler = new TableRowTransferHandler(); 
    private final String[] columnNames = {"String", "Integer", "Boolean"}; 
    private final Object[][] data = { 
    {"AAA", 12, true}, {"aaa", 1, false}, 
    {"BBB", 13, true}, {"bbb", 2, false}, 
    {"CCC", 15, true}, {"ccc", 3, false}, 
    {"DDD", 17, true}, {"ddd", 4, false}, 
    {"EEE", 18, true}, {"eee", 5, false}, 
    {"FFF", 19, true}, {"fff", 6, false}, 
    {"GGG", 92, true}, {"ggg", 0, false} 
    }; 
    private final TableModel model = new DefaultTableModel(data, columnNames) { 
    @Override public Class<?> getColumnClass(int column) { 
     switch (column) { 
     case 0: 
     return String.class; 
     case 1: 
     return Number.class; 
     case 2: 
     return Boolean.class; 
     default: 
     return super.getColumnClass(column); 
     } 
    } 
    }; 
    private final JTable table = new JTable(model); 

    public JComponent makeUI() { 
    table.getSelectionModel().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); 
    table.setTransferHandler(handler); 
    table.setDropMode(DropMode.INSERT_ROWS); 
    table.setDragEnabled(true); 
    table.setFillsViewportHeight(true); 
    //table.setAutoCreateRowSorter(true); //XXX 

    //Disable row Cut, Copy, Paste 
    ActionMap map = table.getActionMap(); 
    Action dummy = new AbstractAction() { 
     @Override public void actionPerformed(ActionEvent e) { /* Dummy action */ } 
    }; 
    map.put(TransferHandler.getCutAction().getValue(Action.NAME), dummy); 
    map.put(TransferHandler.getCopyAction().getValue(Action.NAME), dummy); 
    map.put(TransferHandler.getPasteAction().getValue(Action.NAME), dummy); 

    JPanel p = new JPanel(new BorderLayout()); 
    p.add(new JScrollPane(table)); 
    p.setBorder(BorderFactory.createTitledBorder("Drag & Drop JTable")); 
    return p; 
    } 
    public static void main(String... args) { 
    EventQueue.invokeLater(() -> { 
     JFrame f = new JFrame(); 
     f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
     f.getContentPane().add(new TableRowsDnDTest().makeUI()); 
     f.setSize(320, 240); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    }); 
    } 
} 

//Demo - BasicDnD (Drag and Drop and Data Transfer) https://docs.oracle.com/javase/tutorial/uiswing/dnd/basicdemo.html 
//Demo - DropDemo (Drag and Drop and Data Transfer) https://docs.oracle.com/javase/tutorial/uiswing/dnd/dropmodedemo.html 
//@see https://docs.oracle.com/javase/tutorial/uiswing/examples/dnd/DropDemoProject/src/dnd/ListTransferHandler.java 
//@see https://github.com/aterai/java-swing-tips/blob/master/DnDReorderTable/src/java/example/TableRowsDnDTest.java 
class TableRowTransferHandler extends TransferHandler { 
    private final DataFlavor localObjectFlavor; 
    private int[] indices; 
    private int addIndex = -1; //Location where items were added 
    private int addCount; //Number of items added. 

    protected TableRowTransferHandler() { 
    super(); 
    localObjectFlavor = new ActivationDataFlavor(Object[].class, DataFlavor.javaJVMLocalObjectMimeType, "Array of items"); 
    } 
    @Override protected Transferable createTransferable(JComponent c) { 
    JTable table = (JTable) c; 
    DefaultTableModel model = (DefaultTableModel) table.getModel(); 
    List<Object> list = new ArrayList<>(); 
    indices = table.getSelectedRows(); 
    for (int i : indices) { 
     list.add(model.getDataVector().get(i)); 
    } 
    Object[] transferedObjects = list.toArray(); 
    return new DataHandler(transferedObjects, localObjectFlavor.getMimeType()); 
    } 
    @Override public boolean canImport(TransferHandler.TransferSupport info) { 
    JTable table = (JTable) info.getComponent(); 
    boolean isDropable = info.isDrop() && info.isDataFlavorSupported(localObjectFlavor); 
    table.setCursor(isDropable ? DragSource.DefaultMoveDrop : DragSource.DefaultMoveNoDrop); 
    return isDropable; 
    } 
    @Override public int getSourceActions(JComponent c) { 
    return TransferHandler.MOVE; 
    } 
    @Override public boolean importData(TransferHandler.TransferSupport info) { 
    if (!canImport(info)) { 
     return false; 
    } 
    TransferHandler.DropLocation tdl = info.getDropLocation(); 
    if (!(tdl instanceof JTable.DropLocation)) { 
     return false; 
    } 
    JTable.DropLocation dl = (JTable.DropLocation) tdl; 
    JTable target = (JTable) info.getComponent(); 
    DefaultTableModel model = (DefaultTableModel) target.getModel(); 
    int index = dl.getRow(); 
    int max = model.getRowCount(); 
    if (index < 0 || index > max) { 
     index = max; 
    } 
    addIndex = index; 
    target.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 
    try { 
     Object[] values = (Object[]) info.getTransferable().getTransferData(localObjectFlavor); 
     addCount = values.length; 
     for (int i = 0; i < values.length; i++) { 
     int idx = index++; 
     model.insertRow(idx, (Vector) values[i]); 
     target.getSelectionModel().addSelectionInterval(idx, idx); 
     } 
     return true; 
    } catch (UnsupportedFlavorException | IOException ex) { 
     ex.printStackTrace(); 
    } 
    return false; 
    } 
    @Override protected void exportDone(JComponent c, Transferable data, int action) { 
    cleanup(c, action == TransferHandler.MOVE); 
    } 

    //If the remove argument is true, the drop has been 
    //successful and it's time to remove the selected items 
    //from the list. If the remove argument is false, it 
    //was a Copy operation and the original list is left 
    //intact. 
    protected void cleanup(JComponent c, boolean remove) { 
    if (remove && indices != null) { 
     c.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 
     DefaultTableModel model = (DefaultTableModel)((JTable) c).getModel(); 
     //If we are moving items around in the same list, we 
     //need to adjust the indices accordingly, since those 
     //after the insertion point have moved. 
     if (addCount > 0) { 
     for (int i = 0; i < indices.length; i++) { 
      if (indices[i] >= addIndex) { 
      indices[i] += addCount; 
      } 
     } 
     } 
     for (int i = indices.length - 1; i >= 0; i--) { 
     model.removeRow(indices[i]); 
     } 
    } 
    indices = null; 
    addCount = 0; 
    addIndex = -1; 
    } 
} 
Verwandte Themen