2011-05-11 56 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); 
相關問題