如何在JTable中检测到列移动操作已完成?我已经将columnModeListener添加到我的列模型中,但问题是每次列移动时都会调用columnMoved方法(按某些像素)。我不想要这种行为。我只想检测列拖动何时完成。
columnModel.addColumnModelListener(new TableColumnModelListener() {
public void columnAdded(TableColumnModelEvent e) {
}
public void columnRemoved(TableColumnModelEvent e) {
}
public void columnMoved(TableColumnModelEvent e) {
//this is called so many times
//I don't want this, but something like column moved finished event
System.out.println("Moved "+e.getFromIndex()+", "+e.getToIndex());
}
public void columnMarginChanged(ChangeEvent e) {
}
public void columnSelectionChanged(ListSelectionEvent e) {
}
});
我希望很清楚我在寻找什么。感谢。
答案 0 :(得分:14)
这就是我最终要做的事情。我知道它很脏,但它适合我正在寻找的东西:
boolean dragComplete = false;
apTable.getTableHeader().addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
if (dragComplete) {
System.out.println("Drag completed");
}
dragComplete = false;
}
});
columnModel.addColumnModelListener(new TableColumnModelListener() {
public void columnAdded(TableColumnModelEvent e) {
}
public void columnRemoved(TableColumnModelEvent e) {
}
public void columnMoved(TableColumnModelEvent e) {
dragComplete = true;
}
public void columnMarginChanged(ChangeEvent e) {
}
public void columnSelectionChanged(ListSelectionEvent e) {
}
});
答案 1 :(得分:4)
这是我用来确定列排序何时发生变化的内部类。请注意,此时用户可能没有松开鼠标,因此拖动可能会继续进行。
private class ColumnUpdateListener implements TableColumnModelListener {
int lastFrom = 0;
int lastTo = 0;
private void verifyChange(int from, int to) {
if (from != lastFrom || to != lastTo) {
lastFrom = from;
lastTo = to;
///////////////////////////////////////
// Column order has changed! Do something here
///////////////////////////////////////
}
}
public void columnMoved(TableColumnModelEvent e) {
verifyChange(e.getFromIndex(), e.getToIndex());
}
public void columnAdded(TableColumnModelEvent e) {
verifyChange(e.getFromIndex(), e.getToIndex());
}
public void columnRemoved(TableColumnModelEvent e) {
verifyChange(e.getFromIndex(), e.getToIndex());
}
public void columnMarginChanged(ChangeEvent e) {}
public void columnSelectionChanged(ListSelectionEvent e) {}
}
这对我有用。
答案 2 :(得分:3)
这可能是一种更好的方法:
table.setTableHeader(new JTableHeader(table.getColumnModel()) {
@Override
public void setDraggedColumn(TableColumn column) {
boolean finished = draggedColumn != null && column == null;
super.setDraggedColumn(column);
if (finished) {
onColumnChange(table); // Handle the event here...
}
}
});
答案 3 :(得分:1)
这对我有用(列移动和边距调整大小):
我扩展表并覆盖columnMoved
和columnMarginChanged
方法如下:
...首先添加一些状态保存变量
private int lastMovementDistance = 0;
private boolean bigMove = false;
private boolean resizeBegan = false;
...
@Override
public void columnMarginChanged(ChangeEvent e) {
super.columnMarginChanged(e);
if (isShowing()){
resizeBegan = true;
}
}
@Override
public void columnMoved(TableColumnModelEvent e) {
super.columnMoved(e);
//this will be set to 0 when the column is dragged
//to where it should begin if released
lastMovementDistance = Math.abs(getTableHeader().getDraggedDistance());
if (e.getFromIndex() != e.getToIndex()){
//note, this does not guarantee that the columns will be eventually
//swapped - the user may move the column back.
//but it prevents us from reacting to movements where
//the user hasn't even moved the column further then its nearby region.
//Works for me, because I don't care if the columns stay the same
//I only need the updates to be infrequent and don't want to miss
//changes to the column order
bigMove = true;
}
}
...然后在我的表的构造函数中我这样做:
public MyTable(){
...
getTableHeader().addMouseListener(new MouseAdapter(){
public void mouseReleased(MouseEvent evt) {
if (bigMove && lastMovementDistance == 0 ){
//react! the tables have possibly switched!
}
else if (resizeBegan){
//react! columns resized
}
resizeBegan = false;
bigMove = false;
}
});
...
}
它有点像黑客,但它对我有用。
答案 4 :(得分:1)
关于你自己的问题ashokgelal的答案很好。我认为只是一点点改进。您的代码也会在单击标题时触发。再使用一个标记,您可以阻止“拖动完成”'当列没有真正改变时触发。 修改后的代码:
g(long)
答案 5 :(得分:0)
如果我理解正确,也许你想看一下鼠标听众。也许是MOUSE_RELEASED事件?
答案 6 :(得分:-1)
所有答案在一个用例中失败:如果表格在填充整个窗口的布局中,则调整窗口大小将调整表格及其列的大小。通过在列标题上查看鼠标事件,我们无法在用户调整窗口大小时收到事件。
我查看了JTable和朋友的源代码,并且始终在JTable.doLayout()调用的子子子函数中调用columnMarginChanged()方法。
然后,我的解决方案是监视触发至少一个columnMarginChanged()的doLayout()调用。
实际上,每个列都会调用columnMarginChanged()。
这是我的解决方案:
private class ResizableJTable extends JTable {
private TableColumnModelListener columnModelListener;
private boolean columnsWereResized;
@Override
public void setColumnModel(TableColumnModel columnModel) {
if (getColumnModel() != null) {
getColumnModel().removeColumnModelListener(columnModelListener);
columnModelListener = null;
}
if (columnModel != null) {
columnModelListener = new TableColumnModelListener() {
public void columnSelectionChanged(ListSelectionEvent e) {
// Nothing to do
}
public void columnRemoved(TableColumnModelEvent e) {
// Nothing to do
}
public void columnMoved(TableColumnModelEvent e) {
// Nothing to do
}
public void columnMarginChanged(ChangeEvent e) {
columnsWereResized = true;
}
public void columnAdded(TableColumnModelEvent e) {
// Nothing to do
}
};
columnModel.addColumnModelListener(columnModelListener);
}
super.setColumnModel(columnModel);
}
@Override
public void doLayout() {
columnsWereResized = false;
super.doLayout();
if (columnsWereResized) {
onColumnsResized();
}
}
/**
* Sub-classes can override this method to
* get the columns-were-resized event.
* By default this method must be empty,
* but here we added debug code.
*/
protected void onColumnsResized() {
int[] columnSizes = getColumnSizes();
String sizes = "";
for (int i : columnSizes) {
sizes += i + " ";
}
System.out.println("COLUMNS RESIZED: [ " + sizes + "]");
}
protected int[] getColumnSizes() {
TableColumnModel columnModel = getTableHeader().getColumnModel();
int columnCount = columnModel.getColumnCount();
int[] columnSizes = new int[columnCount];
for(int i = 0; i < columnCount; i++) {
TableColumn column = columnModel.getColumn(i);
columnSizes[i] = column.getWidth();
}
return columnSizes;
}
}