Java JTable检测列由用户重新调整大小

时间:2012-01-06 02:28:57

标签: java swing jtable listener

我有一个JTable使用TableColumnModelListener()来检测列何时重新调整大小,并且我想要在columnMarginChanged()方法中执行一些代码。

如何确定列是由用户重新调整大小还是由于其他代码?

我想我必须从ChangeEvent.getSource()开始,但我不知道从哪里开始。

谢谢。

3 个答案:

答案 0 :(得分:7)

我可以给你一个可能的方法。我试图解决同样的问题,因为我想将有关列宽的信息序列化到磁盘,以便下次在我的应用程序中打开表时,我可以适当地恢复列宽。这是:

第1步 - 覆盖您的JTable并为其添加布尔属性

class MyTable extends JTable {

    private boolean isColumnWidthChanged;
    public boolean getColumnWidthChanged() {
        return isColumnWidthChanged;
    }

    public void setColumnWidthChanged(boolean widthChanged) {
        isColumnWidthChanged = widthChanged;
    }

}

第2步 - 将TableColumnModelListener()添加到表

private class TableColumnWidthListener implements TableColumnModelListener
{
    @Override
    public void columnMarginChanged(ChangeEvent e)
    {
        /* columnMarginChanged is called continuously as the column width is changed
           by dragging. Therefore, execute code below ONLY if we are not already
           aware of the column width having changed */
        if(!tableObj.hasColumnWidthChanged())
        {
            /* the condition  below will NOT be true if
               the column width is being changed by code. */
            if(tableObj.getTableHeader.getResizingColumn() != null)
            {
                // User must have dragged column and changed width
                tableObj.setColumnWidthChanged(true);
            }
        }
    }

    @Override
    public void columnMoved(TableColumnModelEvent e) { }

    @Override
    public void columnAdded(TableColumnModelEvent e) { }

    @Override
    public void columnRemoved(TableColumnModelEvent e) { }

    @Override
    public void columnSelectionChanged(ListSelectionEvent e) { }
}

步骤3 - 将鼠标监听器添加到表格标题

private class TableHeaderMouseListener extends MouseAdapter
{
    @Override
    public void mouseReleased(MouseEvent e)
    {
        /* On mouse release, check if column width has changed */
        if(tableObj.getColumnWidthChanged())
        {
            // Do whatever you need to do here

            // Reset the flag on the table.
            tableObj.setColumnWidthChanged(false);
        }
    }
}

注意:在我的应用程序中,TableHeaderMouseListener和TableColumnWidthListener类是我的主应用程序类的私有内部类。我的主要应用程序类保持对正在观察的表的引用。因此,这些内部类可以访问表实例。显然,根据您的设置,您需要执行适当的操作以使表实例可用于这些其他类。希望这有帮助!

答案 1 :(得分:4)

通常,您希望收到已完成列拖动或已完成列调整大小的通知。 E.g。

interface SGridModel {
    public void columnMoved(int oldLocation, int newLocation);
    public void columnResized(int column, int newWidth);
}        

这不是很好,但它会做你想要的:

class SColumnListener extends MouseAdapter implements TableColumnModelListener {

    private final Logger log = Logger.getLogger(getClass());
    private final SGridModel model;

    private int oldIndex = -1;
    private int newIndex = -1;
    private boolean dragging = false;

    private boolean resizing = false;
    private int resizingColumn = -1;
    private int oldWidth = -1;

    SColumnListener(SGridModel model){
        this.model = model;
    }

    @Override
    public void mousePressed(MouseEvent e) {
        // capture start of resize
        if(e.getSource() instanceof JTableHeader) {
            TableColumn tc = ((JTableHeader)e.getSource()).getResizingColumn();
            if(tc != null) {
                resizing = true;
                resizingColumn = tc.getModelIndex();
                oldWidth = tc.getPreferredWidth();
            } else {
                resizingColumn = -1;
                oldWidth = -1;
            }
        }   
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        // column moved
        if(dragging && oldIndex != newIndex) {
            model.columnMoved(oldIndex, newIndex);
            log.info("column moved: " +oldIndex+" -> "+newIndex);
        }
        dragging = false;
        oldIndex = -1;
        newIndex = -1;


        // column resized
        if(resizing) {
            if(e.getSource() instanceof JTableHeader) {
                TableColumn tc = ((JTableHeader)e.getSource()).getColumnModel().getColumn(resizingColumn);
                if(tc != null) {
                    int newWidth = tc.getPreferredWidth();
                    if(newWidth != oldWidth) {
                        model.columnResized(resizingColumn, newWidth);
                        log.info("column resized: " +resizingColumn+" -> "+newWidth);
                    }
                }
            }   
        }
        resizing = false;
        resizingColumn = -1;
        oldWidth = -1;
    }

    @Override
    public void columnAdded(TableColumnModelEvent e) {      
    }

    @Override
    public void columnRemoved(TableColumnModelEvent e) {        
    }

    @Override
    public void columnMoved(TableColumnModelEvent e) {
        // capture dragging
        dragging = true;
        if(oldIndex == -1){
            oldIndex = e.getFromIndex();
        }

        newIndex = e.getToIndex();  
    }

    @Override
    public void columnMarginChanged(ChangeEvent e) {
    }

    @Override
    public void columnSelectionChanged(ListSelectionEvent e) {
    }
}

将其添加到表中,如下所示:

table.getColumnModel().addColumnModelListener(cl);
table.getTableHeader().addMouseListener(cl);

答案 2 :(得分:0)

更简单的解决方案可能只是监听鼠标释放事件(在此用户交互中仅发生一次)并检查列大小是否同时发生变化?我使用下面的代码来监听列重新排序和大小更改。

getTableHeader().addMouseListener( new MouseAdapter() {
    public void mouseReleased(MouseEvent arg0)
    {
      String colNamesAndSizes = "";
      for( int i=0;i<getColumnModel().getColumnCount();i++ ) {

        if( i>0 ) colNamesAndSizes += ",";
        TableColumn column = getColumnModel().getColumn(i);
        colNamesAndSizes += column.getHeaderValue();
        colNamesAndSizes += ":";
        colNamesAndSizes += column.getWidth();
      }
      // check if changed, if yes, persist...
   }});