I had the same issue, and I was searching about it. So far I found two ways of doing that.
- The "if I was rewriting it myself" method : Modifying the base classes from Java.
TableColumn
would need a new property, like the "resizingAllowed", it would need the "reorderingAllowed".
From this, the modifications take place in BasicTableHeaderUI
:
There is already :
private static boolean canResize(TableColumn column,
JTableHeader header) {
return (column != null) && header.getResizingAllowed()
&& column.getResizable();
}
It would need too :
private static boolean canMove(TableColumn column,
JTableHeader header) {
return (column != null) && header.getReorderingAllowed()
&& column.getReorderable();
}
(Note that if you don't want the first column only to not move, you can do without changing the TableColumns :
private static boolean canMove(TableColumn column,
JTableHeader header) {
return (column != null) && header.getReorderingAllowed()
&& header.getColumnModel().getColumnIndex(column.getIdentifier()) != 0;
}
)
After, two places to modify in the MouseInputListener
:
- in the
mousePressed
, calling the canMove()
instead of the header.getReorderingAllowed()
. This ensures that a column which shouldn't be moved, won't be.
But this is not enough, we need to prevent the immobile columns from being moved during dragging another one. You need to change the mouseDragged
, too, when it is getting the "newColumnIndex" :
if (0 < newColumnIndex && newColumnIndex < cm.getColumnCount())
You need to add the condition if this new index can be moved, for example using the "canMove()" method. This way, when you will drag a column to this immobile one, you will still drag it, but it won't swap them.
Note that this method would require you to explicitly set the UI for the JTableHeader used for your JTable, which is not really ideal. But this is the most adapted though, as it deals with the problem on the place it is supposed to.
- The "Let's try to block the normal behavior with what we actually have" method : Not modifying the UI, this method focus on the JTableHeader to block the commands made by the UI.
First, to block dragging the first column, we need a subclass from JTableHeader, with this overridden method :
@Override
public void setDraggedColumn(TableColumn pAColumn)
{
int lIndex = -1;
if (pAColumn != null)
lIndex = getColumnModel().getColumnIndex(pAColumn.getIdentifier());
if (lIndex != 0)
super.setDraggedColumn(pAColumn);
}
This will prevent a user from dragging the first column. But like described earlier, this is only one part of the problem, we need to prevent another dragged column from swapping with this first one.
So far, I don't have a correct method for this. I tried by subclassing the TableColumnModel, and overriding the moveColumn()
method :
@Override
public void moveColumn(int pColumnIndex, int pNewIndex)
{
//Move only if the first column is not concerned
if (pColumnIndex =! 0 && pNewIndex != 0)
super.moveColumn(pColumnIndex, pNewIndex);
}
But this won't work, as the UI will update anyway the mouse position in the mouseDragged
method, you will have a jump from your dragged column to another place.
So I'm still searching, and wonder if someone has propositions concerning this part.