2012-01-06 3 views
9

TableColumnModelListener()을 사용하여 열의 크기가 변경된 것을 감지하고 columnMarginChanged() 메서드에서 실행하려는 일부 코드가있는 JTable이 있습니다.자바 JTable 감지 사용자가 열 크기 조정

사용자가 다른 열의 결과로 열의 크기를 조정했는지 어떻게 결정합니까?

나는 ChangeEvent.getSource()으로 시작해야한다고 생각하지만 거기서 어디로 가야할지 모르겠습니다.

감사합니다.

+0

변경하지 않는 한, 소스는 항상 'fireColumnMarginChanged()'를 통해 테이블의 'DefaultTableColumnModel'이됩니다. 어떤 문제를 해결하려고합니까? – trashgod

+0

절대 안됩니다. @ trashgod의 질문을 반복하십시오 : 왜? – kleopatra

+0

열 크기를 변경하는 코드의 경우 변경하기 전에 항상 수신기를 비활성화 또는 제거하고 변경 한 다음 반응을 나타내거나 수신기를 다시 추가 할 수 있습니다. – Robin

답변

7

하나의 가능한 접근 방식을 제공 할 수 있습니다. 같은 문제를 해결하려고했는데, 열 너비에 대한 정보를 디스크에 직렬화하여 다음에 응용 프로그램에서 테이블을 열면 열 너비를 적절히 복원 할 수있었습니다. 여기 간다 :

1 단계 - 당신의 JTable을 무시하고

class MyTable extends JTable { 

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

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

} 

2 단계 그것에 부울 속성을 추가 - (A 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 클래스는 내 기본 응용 프로그램 클래스의 개인 내부 클래스입니다. 내 주요 응용 프로그램 클래스는 관찰되는 테이블의 참조를 유지합니다. 따라서 이러한 내부 클래스는 테이블 인스턴스에 액세스 할 수있었습니다. 분명히, 설정에 따라 테이블 인스턴스를 다른 클래스에서 사용할 수 있도록 적절한 작업을 수행해야합니다. 희망이 도움이!

+0

(아직 요구 사항을 얻지 못했습니다 - 너비를 항상 간단하게 저장하는 것이 좋겠습니까?) - 마커 : 커서를 사용하는 대신 매우주의해야합니다 :-) 헤더를 사용하십시오 resizingColumn : 그것입니다!= 사용자가 크기를 조정하는 중에 만 null입니다. 그것은 JXTableHeader가 패킹을 지원하고 크기를 조정할 때조차도 정렬을 트리거하는 성가신 핵심 버그를 수정하는 방법입니다. – kleopatra

+1

한 가지 방법은 애플리케이션이 종료 될 때 모든 열 너비를 간단히 직렬화하는 것입니다 (어쩌면 windowClosing 메소드를 통해). WindowListener)를 호출합니다. 이것이이 질문을 게시 한 사람에게 올바른 접근법 일 수 있습니다. 열 너비를 점진적으로 serialize해야하는 이유는 행/열이 작성/삭제 될 때마다 내 JTable이 파괴되고 처음부터 재생성되기 때문입니다. (이것은 이상하게 들릴지 모르겠지만 공개 포럼에서 공개 할 수없는 이유가 있습니다.) 따라서 원래의 너비를 되 찾는 방법은 점진적으로 순차적으로 나열하는 것입니다. – eternaln00b

+0

아마도 좀 더 자세히 설명해 드릴 수 있습니다. :) 아시다시피, 내 JTable은보다 정교한 백엔드의 입력 양식입니다. 사용자가 애플리케이션의 JTable을 변경하면 특정 작업이 백그라운드에서 사용자를 위해 자동 생성됩니다. 그래서 제 JTable은 본질적으로 마법사입니다. 테이블이 백그라운드에서 자동 생성 된 것을 정확히 반영하도록하려면 자동 생성 된 오브젝트를 구문 분석하고 테이블을 다시 작성해야합니다. 이 작업을 수행하지 않으면 프로그래밍 오류로 인해 테이블과 자동 생성 개체가 분기되기 시작하고 더 이상 진실이 없음을 알 수 있습니다. – eternaln00b

4

일반적으로 완료된 열 끌기 또는 완료된 열 크기 조정을 알리 길 원합니다. 예 :

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); 
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... 
    }});