2011-05-11 62 views
4

如果您将JTable设置为table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION),然后单击拖动尚未选定的行,则会开始选择多行。我们不希望这种行为。我们需要它,所以如果你点击一个节点,即使它没有被选中,它也会开始拖拽它。如何使JTable单击取消选择拖动而不是选择

我们确实需要启用多重选择模式,因此将其设置为单选(这会导致我们想要的行为)不是一种选择。

更新:在这一点上,似乎这将需要某种类型的丑陋的黑客,因为逻辑是一个私有方法BasicTableUI $ Handler.canStartDrag

回答

3

我发现了一个可能的解决方案。您可以包围鼠标侦听器,以便在canStartDrag调用期间可以说谎对isCellSelected的调用。

JTable的子类(或在我的情况下,JXTreeTable)。在构造函数中调用这个:

private void setupSelectionDragHack() 
{ 
    // Bracket the other mouse listeners so we may inject our lie 
    final MouseListener[] ls = getMouseListeners(); 
    for (final MouseListener l : ls) 
    { 
     removeMouseListener(l); 
    } 
    addMouseListener(new MouseAdapter() 
    { 
     @Override 
     public void mousePressed(final MouseEvent e) 
     { 
      // NOTE: it might not be necessary to check the row, but... I figure it's safer maybe? 
      mousingRow = rowAtPoint(e.getPoint()); 
      mousingInProgress = true; 
     } 
    }); 
    for (final MouseListener l : ls) 
    { 
     addMouseListener(l); 
    } 
    addMouseListener(new MouseAdapter() 
    { 
     @Override 
     public void mousePressed(final MouseEvent e) 
     { 
      mousingInProgress = false; 
     } 
    }); 
} 

然后你需要这样的:

@Override 
public boolean isCellSelected(final int row, final int column) 
{ 
    if (mousingInProgress && row == mousingRow) 
    { 
     // Only lie to the canStartDrag caller. We tell the truth to everyone else. 
     final StackTraceElement[] elms = Thread.currentThread().getStackTrace(); 
     for (int i = 0; i < 3; i++) 
     { 
      if (elms[i].getMethodName().equals("canStartDrag")) 
      { 
       return mousingInProgress; 
      } 
     } 
    } 
    return super.isCellSelected(row, column); 
} 

这是一个在许多方面的丑陋的黑客攻击,但是......现在它似乎工作。

1

这是一个错误:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6349223

,正如你已经假定,它需要一些丑陋的黑客。这里有一个(不是来自我,而是从老孙论坛用户Aephyr它没有生存迁移到OTN)

table = new JTable() { 
     // fix for http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6349223 
     // requirement is the option to turn off drag-selection if dragEnabled 
     // fix posted in sun dev forum by Aephyr 
     // http://forums.sun.com/thread.jspa?threadID=5436355&tstart=0 
     private boolean pressed; 

     @Override 
     protected void processMouseEvent(MouseEvent e) { 
       pressed = e.getID() == MouseEvent.MOUSE_PRESSED; 
       if (pressed && !e.isShiftDown() && !e.isControlDown()) 
         clearSelection(); 
       try { 
         super.processMouseEvent(e); 
       } finally { 
         pressed = false; 
       } 
     } 

     @Override 
     public boolean isCellSelected(int row, int col) { 
       return pressed ? true : super.isCellSelected(row, col); 
     } 

    }; 
+0

当我刚才尝试这个时,我无法选择多个项目。点击拖动时,选择会消失。 – mentics 2011-05-17 22:08:59

1

类似克列奥帕特拉的回答,但这似乎处理与前一个的几个问题 - 您可以通过按住Ctrl键同时添加和删除多个选项中的项目,并且可以成功拖动多选组。我只用NetBeans的ETable/Outline测试过,但应该使用常规的JTable。

table = new JTable() { 
    private boolean inPress = false; 

    @Override protected void processMouseEvent(MouseEvent e) { 
     inPress = e.getID() == MouseEvent.MOUSE_PRESSED && e.getButton() == MouseEvent.BUTTON1 && !e.isShiftDown() && !e.isControlDown(); 
     try { 
      super.processMouseEvent(e); 
     } finally { 
      inPress = false; 
     } 
    } 

    @Override public boolean isCellSelected(int row, int col) { 
     boolean selected = super.isCellSelected(row, col); 
     if (inPress) { 
      if (!selected) 
       clearSelection(); 
      return true; 
     } 

     return selected; 
    } 
}; 
3

不幸的是没有其他答案为我工作。

所以我做了我自己的黑客/修复的问题(我有同样的问题在这里张贴替他人):

public class SFixTable extends JTable { 
private static final long serialVersionUID = 1082882838948078289L; 

boolean pressed = false; 
int currSRow = -100; 

public SFixTable(TableModel dm) { 
    super(dm); 
} 

public SFixTable() { 
    super(); 
} 

public SFixTable(Vector<?> rowData, Vector<?> columnNames) { 
    super(rowData, columnNames); 
} 

@Override 
protected void processMouseEvent(MouseEvent e) { 
    int row = rowAtPoint(e.getPoint()); 
    int col = columnAtPoint(e.getPoint()); 
    if (SwingUtilities.isLeftMouseButton(e) && !e.isShiftDown() && !e.isControlDown()) { 
     boolean isDragRelease = (e.getID() == MouseEvent.MOUSE_RELEASED) && row != currSRow; 
     boolean isStartClick = (e.getID() == MouseEvent.MOUSE_PRESSED); 

     if (row >= 0 && col >= 0) { 
      if (isStartClick) { 
       super.changeSelection(row, col, false, false); 
      } else if (isDragRelease) { 
       super.changeSelection(currSRow, col, false, false); 
      } 
     } 
     pressed = (e.getID() == MouseEvent.MOUSE_PRESSED); 
     if (pressed) { 
      currSRow = row; 
     } else { 
      currSRow = -100; 
     } 
    } 

    super.processMouseEvent(e); 
} 

@Override 
public boolean isCellSelected(int row, int col) { 
    return (pressed)? (row == currSRow) : super.isCellSelected(row, col); 
} 

} 
1

如果你正在寻找的是要拖动非选择行一个single选择JTable,将表的选择模型设置为SINGLE_SELECTION模式是不够的,您还必须设置列模型的选择模式。

JTable table = new JTable(); 
table.getSelectionModel() 
    .setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 
table.getColumnModel().getSelectionModel() 
    .setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 
相关问题