在JTable中用鼠标移动行 [英] Move row with mouse in JTable

查看:43
本文介绍了在JTable中用鼠标移动行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些行的JTable.我想当用鼠标(拖放)移动一行时,该行与鼠标和表行一起移动,以便在鼠标移动(例如移动JTable的列)时重新排序. 这个 jsfiddle 正是我想要的,但是我必须在java swing(或gif)中执行下图示例来自此处,但我无法了解).

I have JTable with some rows. I want when move one row with mouse(drag and drop) that row to move together with mouse and table rows to be reorder when mouse move(like moving JTable's columns). This jsfiddle is exactly what i want but i have to do it in java swing(or gif image below. Example is from here but I can't understand it).

我的TransferHandler:

My 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));
        }
    }
}

这是我用于JTable的简单设置:

That is a simple settings that i use to JTable:

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

在用鼠标在行之间移动行时,只有一条粗线(如下面图像中的红色椭圆所示).如果不可能使行像这样移动,我希望这条粗线显示在整行中(不仅在一个单元格中).

At the moment when you move row with mouse between rows only have one bold line(Like this in red ellipse below in image). If it is impossible to do rows to move like this, i want this bold line to appear to whole row (not only in one cell).

推荐答案

我认为JList的项目交换/dropmodedemo.html"rel =" nofollow noreferrer> Swing教程也将有所帮助.

I think that ListTransferHandler.java for item swapping of JList in the Swing tutorial will be also helpful.

这是我为JTable修改ListTransferHandler的示例:

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;
  }
}

这篇关于在JTable中用鼠标移动行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆