Pregunta

¿Cómo se configura una JTable para poder arrastrar una fila a un índice diferente en la tabla? Por ejemplo, si tengo 5 filas y quiero arrastrar la cuarta fila a la segunda posición?

¿Fue útil?

Solución

Consulte la sección arrastrar y soltar de El tutorial de Java. Hay algunos ejemplos sobre cómo implementar esto para JTable .

Otros consejos

Lo siguiente permite reorganizar JTable de una sola fila arrastrada:

  table.setDragEnabled(true);
  table.setDropMode(DropMode.INSERT_ROWS);
  table.setTransferHandler(new TableRowTransferHandler(table)); 

Su TableModel debe implementar lo siguiente para permitir el reordenamiento:

public interface Reorderable {
   public void reorder(int fromIndex, int toIndex);
}

Esta clase TransferHandler maneja el arrastre & amp; soltar y llama a reordenar () en su TableModel cuando se completa el gesto.

/**
 * Handles drag & drop row reordering
 */
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;

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

   @Override
   protected Transferable createTransferable(JComponent c) {
      assert (c == table);
      return new DataHandler(new Integer(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 (Exception e) {
         e.printStackTrace();
      }
      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));
      }
   }

}

tal vez algo. así:

    table.addMouseMotionListener(new MouseMotionListener() {
    public void mouseDragged(MouseEvent e) {
        e.consume();
        JComponent c = (JComponent) e.getSource();
        TransferHandler handler = c.getTransferHandler();
        handler.exportAsDrag(c, e, TransferHandler.MOVE);
    }

    public void mouseMoved(MouseEvent e) {
    }
});

Solo para los registros y el reordenamiento de varias filas:

usar en algún lugar ...

 JTable table = t_objects;
    table.setDragEnabled(true);
    table.setDropMode(DropMode.INSERT_ROWS);
    table.setTransferHandler(new TableRowTransferHandler(table));

Esta es la clase principal en la respuesta anterior, la modifiqué para que coincida con las necesidades de múltiples filas DnD. Todo lo que hice fue usar la primera fila seleccionada, luego calcular las filas sobre el lugar de colocación. Se eliminaron los elementos seleccionados y se mantienen en una lista de objetos (objeto de matriz de filas). luego insértelos nuevamente en la fila calculada. y finalmente seleccione las filas eliminadas / arrastradas para completar el proceso.

public class TableRowTransferHandler extends TransferHandler {

    private final DataFlavor localObjectFlavor = new DataFlavor(Integer.class, "Integer Row Index");
    private JTable table = null;

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

    @Override
    protected Transferable createTransferable(JComponent c) {
        assert (c == table);
        return new DataHandler(new Integer(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) {

                int[] rows = table.getSelectedRows();
                int dist = 0;
                for (int row : rows) {
                    if (index > row) {
                        dist++;
                    }
                }
                index -= dist;

                //**TableUtil** is a simple class that just copy, remove and select rows.

                ArrayList<Object> list = TableUtil.getSelectedList(table);
                TableUtil.removeSelected(table);
                ArrayList<Integer> sels = new ArrayList<Integer>();
                for (Object obj : list) {
                    sels.add(index);
                    TableUtil.addRowAt(table, obj, index++);
                }
                TableUtil.selectMultipleRow(table, sels);


                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

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

Me gustan las modificaciones de Soley, pero su código se basa en una biblioteca externa, y no estoy seguro de dónde lo obtuvo, así que lo reescribí para que no necesite la clase TableUtil ...

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

                int[] rows = table.getSelectedRows();
                int iter = 0;
                for (int row : rows) {
                    if (index > row) {
                        index--;
                        ((Reorderable) table.getModel()).reorder(row - iter, index);
                    }

                    else {
                        ((Reorderable) table.getModel()).reorder(row, index);
                    }
                    index++;
                    iter++;
                }

                target.getSelectionModel().addSelectionInterval(index, index);

                return true;
            }

      } catch (Exception e) {
            String error = e.getMessage();
            JOptionPane.showMessageDialog(null, error, "Error", JOptionPane.ERROR_MESSAGE);
      }
      return false;
   }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top