Столбец перемещено [закончено] событие в JTable - PullRequest
11 голосов
/ 29 января 2010

Как мне определить, что действие перемещения столбца завершено в 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) {
            }
        });

Надеюсь, понятно, что я ищу. Спасибо.

Ответы [ 7 ]

14 голосов
/ 29 января 2010

Я так и сделал. Я знаю, что это грязно, но это подходит для того, что я ищу:

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) {
            }
        });
4 голосов
/ 29 января 2010

Вот внутренний класс, который я использую, чтобы определить, когда изменился порядок столбцов. Обратите внимание, что пользователь, возможно, не отпустил мышь в этой точке, поэтому перетаскивание может продолжаться дальше.

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) {}

}

Это хорошо сработало для меня.

3 голосов
/ 09 июня 2010

Это может быть лучше:

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...
        }
      }
    });
1 голос
/ 08 декабря 2015

Хороший ответ на свой вопрос Ашокгелал .Просто небольшое улучшение, я думаю.Ваш код также срабатывает при одном клике на заголовке.Используя еще один флаг, вы можете предотвратить триггер dragComplete, когда столбец действительно не изменился.Модифицированный код:

    boolean mDraggingColumn = false;
    boolean mColumnCHangedIndex = false;

    tblObjects.getTableHeader().addMouseListener(new MouseAdapter() {
        @Override
        public void mouseReleased(MouseEvent e) {
            if (mDraggingColumn && mColumnCHangedIndex) {
                System.out.println("Column changed");
            }
            mDraggingColumn = false;
            mColumnCHangedIndex = false;
        }
    });
    tblObjects.getColumnModel().addColumnModelListener(new TableColumnModelListener() {
        @Override
        public void columnAdded(TableColumnModelEvent e) {}
        @Override
        public void columnRemoved(TableColumnModelEvent e) {}
        @Override
        public void columnMoved(TableColumnModelEvent e) {
            mDraggingColumn = true;
            if (e.getFromIndex() != e.getToIndex()) {
                mColumnCHangedIndex = true;
            }
        }
        @Override
        public void columnMarginChanged(ChangeEvent e) {}
        @Override
        public void columnSelectionChanged(ListSelectionEvent e) {}
    });
1 голос
/ 28 июня 2013

Это то, что у меня работает (как движения колонок, так и изменение размеров полей):

Я расширяю таблицу и отменяю 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;
 } 
 });
  ...
}

Это вроде как взломать, но это работает для меня.

0 голосов
/ 01 июля 2013

Все ответы терпят неудачу в одном случае использования: если таблица находится в макете, заполняющем все окно, то изменение размера окна приведет к изменению размера таблицы и, следовательно, ее столбцов. Наблюдая за событиями мыши в заголовках столбцов, мы не получаем событие, когда пользователь изменяет размер окна.

Я посмотрел на исходный код JTable & friends, и метод columnMarginChanged () всегда вызывается в функции sub-sub-sub ...-, вызываемой JTable.doLayout ().

Тогда мое решение состоит в том, чтобы отслеживать вызовы doLayout (), которые инициируют хотя бы один columnMarginChanged ().

Фактически, 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;
    }
}
0 голосов
/ 29 января 2010

Если я вас правильно понимаю, возможно, вы захотите взглянуть на слушателей мыши. Может быть, событие MOUSE_RELEASED?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...