如何防止 JTable 中的单个列被重新排序?
我有一个 JTable,我需要能够对列进行重新排序。 但是我希望第一列无法重新排序。 我使用以下命令来启用重新排序:
table.getTableHeader().setReorderingAllowed(true);
现在可以对列进行重新排序,包括我不想要的第一列。 有什么办法可以锁定第一列吗?
我见过一些使用两个表的解决方案,第一列位于单独的表中,但也许有更好/更简单的方法。
I have a JTable
and I need to be able to reorder the columns. However I want the first column to not be able to be re-ordered. I used the following to enable reordering:
table.getTableHeader().setReorderingAllowed(true);
The columns can now be reordered including the first column which I don't want. Is there any way to lock the first column?
I have seen some solutions that use two tables with the first column being in a separate table, but maybe there's a better/simpler way.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
这是我用来防止第一列被重新排序的解决方案
干杯,
This is the solution that I used to prevent the 1st column from being re-ordered
Cheers,
近四年过去了,仍然看不到最佳解决方案。
防止拖动第一列(以及第一列上的其他列)的另一种次优方法是在 uidelegate 安装的 mouseInputListener 可以处理 mouseEvents 之前拦截它们(类似于最近的质量检查)。
协作者
定义 MouseInputListener:
在 LAF、fi 切换后仍可使用:
Nearly 4 years later, there's still no optimal solution in sight anywhere.
Yet another suboptimal approach to prevent dragging of the first column (and other columns over the first) is to intercept the mouseEvents before the mouseInputListener installed by the uidelegate can handle them (similar to a recent QA).
The collaborators
The custom MouseInputListener:
Usage which survives switching of LAF, f.i.:
我认为您需要重写
TableColumnModelListener
中的columnMoved()
方法。TableColumnModelEvent
类有一个getFromIndex()
方法,您应该能够查看该方法以确定它是否是您的固定列,然后您应该能够取消该事件。希望有帮助。 A
I think that you need to override the
columnMoved()
method inTableColumnModelListener
. theTableColumnModelEvent
class has agetFromIndex()
method that you should be able to look at to determine if it's your fixed column, and then you should be able to cancel the event.Hope that helps. A
首先,您需要定义一种更好、更简单的方法。 您不喜欢 2 表方法的哪些方面?
您不能使用 TableColumnModelListener,因为该事件是在列已移动“之后”触发的。
拖动列的代码可以在BasicTableHeaderUI 中找到。 因此,您可以尝试覆盖那里的代码,但随后您需要对所有 LAF 执行此操作。
上面的代码在 mousePressed 事件上调用 JTableHeader.getReorderingAllowed() 来确定是否允许列重新排序。 我想您可以重写 JTableHeader 中的该方法,并可能使用 MouseInfo 类来获取当前鼠标位置,以确定它是否位于第一列上方,然后返回 false。 但现在您还需要创建一个使用自定义表头的自定义 JTable。
当然,通过上述任一建议,您也许可以防止第一列被移动。 但不要忘记,您还需要防止第二列插入到第一列之前。 我不认为这个问题有一个简短的答案。
固定列表 是我的版本用两个表来实现。 好点吗? 我不知道,但它很简单,因为只需一行代码即可使用它。
First you need to define a better and simpler way. What don't you like about the 2 table approach?
You can't use a TableColumnModelListener, because the event is fired "after" the column has already been moved.
The code for dragging the column is found in the BasicTableHeaderUI. So you could try overriding the code there, but then you would need to do it for all LAFs.
The above code invokes JTableHeader.getReorderingAllowed() on a mousePressed event to determine if column reordering is allowed. I guess you could override that method in the JTableHeader and perhaps use the MouseInfo class to get the current mouse location to determine if it was over the first column and then return false. But then now you would also need to create a custom JTable that uses the custom table header.
Of course with either of the above suggestions you might be able to prevent the first column from being moved. But don't forget you also need to prevent the 2nd column from being inserted before the first column. I don't believe there is a short simple answer to the question.
Fixed Column Table is my version of how this would be imlemented with two tables. Is it better? I don't know, but it is simple since its only a single line of code to use it.
我有同样的问题,我正在搜索它。 到目前为止,我找到了两种方法。
TableColumn
需要一个新属性,例如“resizingAllowed”,它需要“reorderingAllowed”。由此,修改发生在
BasicTableHeaderUI
中:已经存在:
它也需要:(
请注意,如果您不希望第一列仅不移动,则可以不更改 TableColumns :)
之后
,在
MouseInputListener
中需要修改两个地方:mousePressed
中,调用canMove()
而不是header。 getReorderingAllowed()。 这确保了不应该移动的列不会被移动。
但这还不够,我们需要防止在拖动另一列时固定不动的列被移动。 当
mouseDragged
获取“newColumnIndex”时,您还需要更改它:if (0 < newColumnIndex && newColumnIndex < cm.getColumnCount())
您需要添加条件是否可以移动这个新索引,例如使用“canMove()”方法。 这样,当您将一列拖到这个不可移动的列时,您仍然会拖动它,但不会交换它们。
请注意,此方法需要您显式设置用于 JTable 的 JTableHeader 的 UI,这并不是很理想。 但这是最适合的,因为它在它应该处理的地方处理问题。
首先,要阻止拖动第一列,我们需要 JTableHeader 的子类,并使用此重写方法:
这将阻止用户拖动第一列。 但就像前面描述的那样,这只是问题的一部分,我们需要防止另一个拖动的列与第一个列交换。
到目前为止,我还没有正确的方法。 我尝试通过子类化 TableColumnModel 并覆盖
moveColumn()
方法:但这不起作用,因为 UI 无论如何都会更新
mouseDragged
方法中的鼠标位置,您将从拖动的列跳转到另一个地方。所以我仍在寻找,想知道是否有人对这部分有建议。
I had the same issue, and I was searching about it. So far I found two ways of doing that.
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 :
It would need too :
(Note that if you don't want the first column only to not move, you can do without changing the TableColumns :
)
After, two places to modify in the
MouseInputListener
:mousePressed
, calling thecanMove()
instead of theheader.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.
First, to block dragging the first column, we need a subclass from JTableHeader, with this overridden method :
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 :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.
起初,我使用了 Gnoupi 的最后建议,即对 TableColumnModel 进行子类化并覆盖 moveColumn,但仍然存在一些烦人的跳转。
这是“我的”完全工作且经过测试的解决方案,没有令人讨厌的跳跃,它主要依赖于 StanislavKo 和 kleopatra 的建议。 我添加了一个更复杂的机制来在释放鼠标按钮时恢复不需要的移动:
请注意,接受最新的有效移动而不是完全恢复列拖动。
freezeColumnModelIndex 是表模型中“冻结”列的索引。
invalidTableColumnMoveFromIndex 是检测到最新非法移动时从其移动位置开始的列的索引。
invalidTableColumnMoveToIndex 是检测到最新非法移动时移动到的列的索引。
mouseDragged 中的代码足以防止冻结列被拖动,其余代码可以防止另一列被拖动到冻结列。
它在 Microsoft Windows 下工作,因为我扩展了 WindowsTableHeaderUI,而是使用反射 API 设置表头 UI 的鼠标输入侦听器,调用 uninstallerListeners() 并最终调用 header.addMouseListener(mouseInputListener) 和 header.addMouseMotionListener(mouseInputListener)为了跨平台驱动我的解决方案,而不对每个表头 UI 的类名称做出任何假设。
我承认它可能比克利奥帕特拉的解决方案稍微弱一些。 我感谢大家的帮助,我真的很感激,我很高兴看到协作工作正常进行:)
At first, I used the very last Gnoupi's suggestion consisting in subclassing the TableColumnModel and overriding moveColumn but there were still some annoying jumps.
This is "my" fully working and tested solution with no nasty jump, it mainly relies on StanislavKo and kleopatra's suggestions. I added a more complicated mechanism to revert the unwanted move when releasing the mouse button :
Note that the latest valid move is accepted instead of completely reverting the column drag.
frozenColumnModelIndex is the index of the "frozen" column in the table model.
illegalTableColumnMoveFromIndex is the index of the column from where it was moved when the latest illegal move was detected.
illegalTableColumnMoveToIndex is the index of the column to where it was moved when the latest illegal move was detected.
The code inside mouseDragged is enough to prevent the frozen column from being dragged, the rest allows to prevent another column from being dragged to the frozen column.
It works as is under Microsoft Windows as I extend WindowsTableHeaderUI but rather use the reflection API to set the mouse input listener of the table header UI, call uninstallerListeners() and finally call header.addMouseListener(mouseInputListener) and header.addMouseMotionListener(mouseInputListener) in order to drive my solution cross-platform without making any assumption on the name of the class for each table header UI.
I admit it might be a bit less robust than kleopatra's solution. I thank you all for your help, I'm really grateful and I'm really happy to see that collaborative work just works :)
我使用了“‘让我们尝试用我们实际拥有的东西来阻止正常行为’方法”的方法。 Gnoupi表示他没有解决问题的第二部分。 以下是仅适用于 Windows XP L&F 的解决方案:
WindowsTableHeaderUI
。 查看源代码。getTableHeader().setUI(new TreeTableWindowsTableHeaderUI());
感谢 Gnoupi 的努力。
I have used the "The 'Let's try to block the normal behavior with what we actually have' method" approach. Gnoupi said that he did not solve the second part of the problem. Here is the solution for just Windows XP L&F:
WindowsTableHeaderUI
. Take a look at the source code.getTableHeader().setUI(new TreeTableWindowsTableHeaderUI());
Thanks to Gnoupi for the efforts.
移动完成后我会把柱子放回去。 所以类似的事情。
I will just put the column back after the move is complete. So something like.