1. 当我选中JTabel的某一行时,拖动这个行的时候,整行数据都一起拖动,随便都可以拖到某一行中间。
2. 还有就是,几行一起拖动,当我给定一范围,假定是3行,以选中某一行为起始点,一行为结束点,这几行能整个拖动
怎么实现呢?

解决方案 »

  1.   

    这个需要自己写TransferHandler和Transferable,
    现在我没时间了,晚上回来如果还没有人回答的话,再跟你说吧。
      

  2.   

    谢谢 qusic 和 virginkj,尤其是virginkj的每次帮忙。
      

  3.   

    忽忽 不用谢 我说过了嘛 我也是新手 接触JAVA才8个月 十足的刚入门 大家共同进步嘛
      

  4.   

    正解:
    http://java.sun.com/docs/books/tutorial/uiswing/misc/dnd.html
    这个里面有你想要的效果的例子 自己找找看吧
      

  5.   

    如果你愿意用框架的话,用Ext里面的Table,它以经实现了你所说的效果
      

  6.   

    我是Swing 的JTable,不是web的!
      

  7.   

    我写的一个小程序里面有个功能和你说的很像,现在把相关功能的类发出来:
    下面是Transferable类:package org.qusic.java.BatchRename.datatransfer;import java.awt.datatransfer.DataFlavor;
    import java.awt.datatransfer.Transferable;
    import java.awt.datatransfer.UnsupportedFlavorException;
    import java.io.File;
    import java.io.IOException;
    import java.util.Vector;
    public class FileTableTransferable implements Transferable {
    //这个Transferable所支持的数据类型
    private static final DataFlavor[] flavors = { 
    DataFlavor.javaFileListFlavor, 
    new DataFlavor(int[].class, "X-test/test; class=<int[]>; foo=bar") };

    //因为我用到了两种数据,所以有两个data,一个是File,用来拖动文件的

    private Vector<File> dataList = null; //一个是int数组,这个就是你要的了,这个数组里面保存的就是要拖动的行号
    private int[] data = null;

    //File的构造方法
    public FileTableTransferable( File... data) {
    dataList = new Vector<File>();
    for( int i = 0; i < data.length; i++) {
    dataList.add( data[i] );
    }
    dataList.trimToSize();
    }

    //这个就是行号的构造方法了,提供一个开始行和结束行,也就是选择的开始和结束索引
    public FileTableTransferable(int start, int end) {
    data = new int[] {start, end};
    }

    //这个方法就是在别的地方要获取数据的方法了,根据不同的flavor来返回不同的数据
    @Override
    public Object getTransferData( DataFlavor flavor ) throws UnsupportedFlavorException, IOException {
    if(flavors[0].equals( flavor )) {
    return dataList;
    }
    if( flavors[1].equals( flavor )) {
    return data;
    }
    throw new UnsupportedFlavorException( flavor );
    } @Override
    public DataFlavor[] getTransferDataFlavors() {
    return flavors;
    } @Override
    public boolean isDataFlavorSupported( DataFlavor flavor ) {
    if( dataList != null ) {
    return flavors[0].equals( flavor );
    }else {
    return flavors[1].equals( flavor );
    }
    }}
    下面就是TransferHandler类了:package org.qusic.java.BatchRename.datatransfer;import java.awt.Component;
    import java.awt.datatransfer.DataFlavor;
    import java.awt.datatransfer.Transferable;
    import java.io.File;
    import java.util.List;import javax.swing.JComponent;
    import javax.swing.JOptionPane;
    import javax.swing.JTable;
    import javax.swing.TransferHandler;import org.qusic.java.BatchRename.ui.FileTable;
    public class FileTableTransferHander extends TransferHandler {
    private static final DataFlavor[] flavors = { 
    DataFlavor.javaFileListFlavor, 
    new DataFlavor(int[].class, "X-test/test; class=<int[]>; foo=bar") };

    private Object source = null;

    @Override
    public boolean canImport( TransferSupport support ) {
    if( support.isDataFlavorSupported( flavors[0] )) {
    return true;
    }
    if( support.isDataFlavorSupported( flavors[1] ) && source == support.getComponent()) {
    return true;
    }
    return false;
    } //这里时就初始化Transferable的地方了,就是获得表格选择的RowIndex
    @Override
    protected Transferable createTransferable( JComponent c ) {
    if(!(c instanceof FileTable) ) {
    return null;
    }
    FileTable ft = (FileTable)c;
    int[] indexes = ft.getSelectedRows();
    if( indexes.length == 0) return null;
    source = ft;
    return new FileTableTransferable(indexes[0],indexes[indexes.length - 1]);
    } @Override
    protected void exportDone( JComponent source, Transferable data, int action ) {
    source = null;
    } //导入数据的方法,根据不同的Transferable调用不同的方法来做,具体在下面
    @Override
    public boolean importData( TransferSupport support ) {
    Component c = support.getComponent();
    if(!(c instanceof FileTable)) {
    return false;
    }
    FileTable ft = (FileTable)c;
    Transferable t = support.getTransferable();
    try {
    if( support.isDataFlavorSupported( flavors[0] )) {
    List<?> data = (List<?>)t.getTransferData(flavors[0]);
    if( data != null ) {
    importFiles(ft, data.toArray( new File[data.size()] ));
    return true;
    }
    }
    if( support.isDataFlavorSupported( flavors[1] ) && source == c) {
    int[] data = (int[]) t.getTransferData( flavors[1] );
    if( data != null ) {
    moveRows(ft, data);
    return true;
    }
    }
    }catch(Exception e) {
    e.printStackTrace();
    }
    return false;
    } @Override
    public int getSourceActions( JComponent c ) {
    return COPY_OR_MOVE;
    }

    //导入文件列表
    private void importFiles(FileTable ft, File[] files) {
    boolean b = ft.insertRows( getDropRow(ft), files );
    if( !b ) {
    JOptionPane.showMessageDialog(ft, 
    "<html>有一个或多个文件没有添加,可能是如下原因:<br>" +
    "<ul><li>列表中已经存在这个文件</li><li>目录不能被导入到列表中</li>");
    }
    }

    //这个就是移动表格行了
    private void moveRows(FileTable ft, int[] data) {
    //moveRow这个方法是实际上是调用TableModel的方法,我会在下面把代码贴出来
    ft.moveRow( data[0], data[data.length - 1], getDropRow(ft) );
    }

    //获得目标表格的放置行
    private int getDropRow(FileTable ft) {
    JTable.DropLocation dl = ft.getDropLocation();
    int i = dl.getRow();
    return i == -1 ? ft.getRowCount() : i;
    }
    }
    下面是moveRow的方法,实际上是从JDK的源代码里拷贝出来的,
    gcd和rotate是实际操作代码,moveRow是包装一下,在移动过后要更新一下表格视图的。 public void moveRow( int start, int end, int to ) {
    int shift = to - start;
    int first, last;
    if ( shift < 0 ) {
    first = to;
    last = end;
    }
    else {
    first = start;
    last = to + end - start;
    }
    rotate( dataVector, first, last + 1, shift );
    //这个就是更新视图的方法
    updateNewNames( first, last + 1);
    //fireTableRowsUpdated( first, last );
    } private static int gcd( int i, int j ) {
    return (j == 0) ? i : gcd( j, i % j );
    } private static void rotate( Vector<Vector<Object>> dataVector2, int a, int b, int shift ) {
    int size = b - a;
    int r = size - shift;
    int g = gcd( size, r );
    for ( int i = 0; i < g; i++ ) {
    int to = i;
    Vector<Object> tmp = dataVector2.elementAt( a + to );
    for ( int from = (to + r) % size; from != i; from = (to + r) % size ) {
    dataVector2.setElementAt( dataVector2.elementAt( a + from ), a + to );
    to = from;
    }
    dataVector2.setElementAt( tmp, a + to );
    }
    }
      

  8.   

    不要急,慢慢看,或者你先看看API中关于这两个类的介绍,
    看看每个方法的说明。
      

  9.   

    问下哦。这两个方法确实还不会用,也还没弄清楚怎么用到JTbale。我刚刚把这两段代码拿出来了。想测试一下。。
    但是FileTable 这个指哪个Table呢,因为报错。
      

  10.   

    FileTable不是什么Table,是我写的一个自定义的Table,只要中要的不是是哪个Table的问题,
    是找到moveRow方法,然后调用的问题,你也可以获得到TableModel,直接调用TableModel的moveRow方法,
    前提是你的TablModel或者Table支持moveRow方法,也就是这个方法你必须写好。
      

  11.   

    问题解决,通过设置UI,通过继承 BasicTableUI类,自己去实现鼠标拖动列。。在JTable那边直接设置JTable.setUI()设置进去就可以了。
    import java.awt.Graphics;
    import java.awt.Rectangle;
    import java.awt.event.MouseEvent;import javax.swing.JComponent;
    import javax.swing.event.MouseInputListener;
    import javax.swing.plaf.basic.BasicTableUI;
    import javax.swing.table.TableModel;public class DragDropRowTableUI extends BasicTableUI {

    private boolean draggingRow = false;
    private int startDragPoint;
    private int dyOffset;

        protected MouseInputListener createMouseInputListener() {
            return new DragDropRowMouseInputHandler();
        }
        
        public void paint(Graphics g, JComponent c) {
         super.paint(g, c);
        
         if (draggingRow) {
         g.setColor(table.getParent().getBackground());
    Rectangle cellRect = table.getCellRect(table.getSelectedRow(), 0, false);
         g.copyArea(cellRect.x, cellRect.y, table.getWidth(), table.getRowHeight(), cellRect.x, dyOffset);
        
         if (dyOffset < 0) {
         g.fillRect(cellRect.x, cellRect.y + (table.getRowHeight() + dyOffset), table.getWidth(), (dyOffset * -1));
         } else {
         g.fillRect(cellRect.x, cellRect.y, table.getWidth(), dyOffset);
         }
         }
        }
        
        class DragDropRowMouseInputHandler extends MouseInputHandler {
        
            public void mousePressed(MouseEvent e) {
             super.mousePressed(e);
             startDragPoint = (int)e.getPoint().getY();    
            }
            
            public void mouseDragged(MouseEvent e) {  
             int fromRow = table.getSelectedRow();
            
             if (fromRow >= 0) {
             draggingRow = true;
             int rowHeight = table.getRowHeight();
             int middleOfSelectedRow = (rowHeight * fromRow) + (rowHeight / 2);
            
             int toRow = -1;
             int yMousePoint = (int)e.getPoint().getY();
                     
             if (yMousePoint < (middleOfSelectedRow - rowHeight)) {
             // Move row up
             toRow = fromRow - 1;
             } else if (yMousePoint > (middleOfSelectedRow + rowHeight)) {
             // Move row down
             toRow = fromRow + 1;
             }
            
             if (toRow >= 0 && toRow < table.getRowCount()) {
             TableModel model = table.getModel();
            
         for (int i = 0; i < model.getColumnCount(); i++) {
         Object fromValue = model.getValueAt(fromRow, i);
         Object toValue = model.getValueAt(toRow, i);
        
         model.setValueAt(toValue, fromRow, i);
         model.setValueAt(fromValue, toRow, i);
         }
         table.setRowSelectionInterval(toRow, toRow);
         startDragPoint = yMousePoint;
             }
            
             dyOffset = (startDragPoint - yMousePoint) * -1;
             table.repaint();
             }
            }
            
            public void mouseReleased(MouseEvent e){
             super.mouseReleased(e);
             draggingRow = false;
             table.repaint();
            }
        }
    } 这个是它实现的类。直接在JTable里面调用这个类就OK .
    table.setUI(new DragDropRowTableUI());这段时间谢谢各位的帮忙非常感谢