2017-02-20 11 views
4

JScrollPane 안에 JTable이 있고, 고정 된 수의 테이블 행에 JScrollPane을 맞추기 위해 getPreferredScrollableViewportSize를 재정 의하여 스크롤 막대가 필요할 때 표시되도록합니다. 또한 SO에서 찾은 코드 부분을 사용하여 내용에 맞게 테이블 열의 크기를 조정했습니다.getPreferredScrollableViewportSize를 적절히 오버라이드

내가 가지고있는 문제는, 내가 dinamically 테이블에 더 넓은 행을 추가 할 때, 수평 JScrollBar가 표시되지 않는다는 것입니다. JTable, JViewport 및 JScrollPane이 revalidate(), repaint(), doLayout() 등을 올바르게 호출하도록 강제하는 여러 가지 방법을 시도했지만 성공하지 못했습니다.

물론 JFrame에서 pack() 메서드를 호출 할 수 있지만 전체 스크롤 패널의 너비가 커지고 가로 스크롤 막대가 나타나지 않습니다.

내가 무엇이 누락 되었습니까?

여기에는 MVCE가 있지만 그냥 못생긴 장난감 예제 일 뿐이지 만 원치 않는 동작을 복제하기에 충분해야합니다.

도움 주셔서 감사합니다.

코드 :

import java.awt.*; 
import java.awt.event.ActionEvent; 
import javax.swing.*; 
import javax.swing.border.EmptyBorder; 
import javax.swing.table.*; 
public class Main 
{ 
    public static void main (String [] a) { 
     SwingUtilities.invokeLater (new Runnable() { 
      public void run() { 
       initGUI(); 
      } 
     }); 
    } 
    private static void initGUI() { 
     final DataTable table = new DataTable(); 
     JPanel container = new JPanel (new BorderLayout (0, 20)); 
     container.add (new JScrollPane (table)); 
     container.add (new JButton (new AbstractAction ("Add wider row") { 
      public void actionPerformed (ActionEvent e) { 
       table.addRow(); 
       // some of many useless attempts ... 
       // table.resizeColumnWidth(); 
       // table.revalidate(); 
      } 
     }), BorderLayout.SOUTH); 
     container.setBorder (new EmptyBorder (10, 10, 10, 10)); 
     JFrame frame = new JFrame ("Test"); 
     frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); 
     frame.setResizable (false); 
     frame.setContentPane (container); 
     frame.setLocationRelativeTo (null); 
     frame.pack(); 
     frame.setVisible (true); 
    } 
} 
class DataTable extends JTable 
{ 
    private static final int VISIBLE_ROWS = 5; 

    DataTable() { 
     String [][] data = new String [][] { 
      {"SomeText", "SomeText"}, 
      {"SomeText", "SomeText"}, 
      {"SomeText", "SomeText"}, 
      {"SomeText", "SomeText"}, 
      {"SomeText", "SomeText"}, 
      {"SomeText", "SomeText"} 
     }; 
     setModel (new DefaultTableModel (data, new String [] {"", ""}) { 
      @Override public boolean isCellEditable (int row, int column) { 
       return false; 
      } 
     }); 
     columnModel.setColumnMargin (20); 
     setBorder (null); 
     setFocusable (false); 
     setRowSelectionAllowed (false); 
     setShowGrid (false); 
     setTableHeader (null); 
     resizeColumnWidth(); 
    } 
    public void addRow() { 
     ((DefaultTableModel) getModel()).addRow (new String [] {"SomeLongerText", "SomeLongerText"}); 
    } 
    private int calculateColumnWidth (int column) { 
     TableColumn tableColumn = columnModel.getColumn (column); 
     int width = 0; 
     for (int row=0; row<getRowCount(); row++) width = Math.max (prepareRenderer (getCellRenderer (row, column), row, column).getPreferredSize().width, width); 
     return width + getIntercellSpacing().width; 
    } 
    @Override public Dimension getPreferredScrollableViewportSize() { 
     int columnsWidth = 0; 
     for (int column=0; column<getColumnCount(); column++) columnsWidth += calculateColumnWidth (column); 
     return new Dimension (columnsWidth, VISIBLE_ROWS * getRowHeight()); 
    } 
    protected void resizeColumnWidth() { 
     for (int column=0; column<getColumnCount(); column++) columnModel.getColumn (column).setPreferredWidth (calculateColumnWidth (column)); 
    } 
} 

편집 :

덕분에 내가 원하는 자동 조절 모드를 설정하고 resizeColumnWidth 방법을 행이 추가 될 때마다 리콜 문제를 해결, @camickr합니다. 이미 개별적으로 시도했다, 난 지금은 잘 작동 전, 업데이트 된 코드 아래에 게시, 내가 모두 :)

Hovewer을 사용하지 않은 믿을 수 없어 :

import java.awt.*; 
import java.awt.event.ActionEvent; 
import javax.swing.*; 
import javax.swing.border.EmptyBorder; 
import javax.swing.table.*; 
public class Main 
{ 
    public static void main (String [] a) { 
     SwingUtilities.invokeLater (new Runnable() { 
      public void run() { 
       initGUI(); 
      } 
     }); 
    } 
    private static void initGUI() { 
     final DataTable table = new DataTable(); 
     JPanel container = new JPanel (new BorderLayout (0, 20)); 
     container.add (new JScrollPane (table)); 
     container.add (new JButton (new AbstractAction ("Add wider row") { 
      public void actionPerformed (ActionEvent e) { 
       table.addRow(); 
      } 
     }), BorderLayout.SOUTH); 
     container.setBorder (new EmptyBorder (10, 10, 10, 10)); 
     JFrame frame = new JFrame ("Test"); 
     frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); 
     frame.setResizable (false); 
     frame.setContentPane (container); 
     frame.setLocationRelativeTo (null); 
     frame.pack(); 
     frame.setVisible (true); 
    } 
} 
class DataTable extends JTable 
{ 
    private static final int VISIBLE_ROWS = 5; 

    DataTable() { 
     String [][] data = new String [][] { 
      {"SomeText", "SomeText"}, 
      {"SomeText", "SomeText"}, 
      {"SomeText", "SomeText"}, 
      {"SomeText", "SomeText"}, 
      {"SomeText", "SomeText"}, 
      {"SomeText", "SomeText"} 
     }; 
     setModel (new DefaultTableModel (data, new String [] {"", ""}) { 
      @Override public boolean isCellEditable (int row, int column) { 
       return false; 
      } 
     }); 
     columnModel.setColumnMargin (20); 
     setAutoResizeMode (AUTO_RESIZE_OFF); 
     setBorder (null); 
     setFocusable (false); 
     setRowSelectionAllowed (false); 
     setShowGrid (false); 
     setTableHeader (null); 
     resizeColumnWidth(); 
    } 
    public void addRow() { 
     ((DefaultTableModel) getModel()).addRow (new String [] {"SomeLongerText", "SomeLongerText"}); 
     resizeColumnWidth(); 
    } 
    private int calculateColumnWidth (int column) { 
     TableColumn tableColumn = columnModel.getColumn (column); 
     int width = 0; 
     for (int row=0; row<getRowCount(); row++) width = Math.max (prepareRenderer (getCellRenderer (row, column), row, column).getPreferredSize().width, width); 
     return width + getIntercellSpacing().width; 
    } 
    @Override public Dimension getPreferredScrollableViewportSize() { 
     int columnsWidth = 0; 
     for (int column=0; column<getColumnCount(); column++) columnsWidth += calculateColumnWidth (column); 
     return new Dimension (columnsWidth, VISIBLE_ROWS * getRowHeight()); 
    } 
    protected void resizeColumnWidth() { 
     for (int column=0; column<getColumnCount(); column++) columnModel.getColumn (column).setPreferredWidth (calculateColumnWidth (column)); 
    } 
} 
+1

질문에 MCVE를 게시 해 주셔서 감사합니다. (+1) 그리고 또한 당연히 camickr에. –

답변

4

때 dinamically 더 넓은 행을 테이블에 추가하면 가로 JScrollBar가 표시되지 않습니다.

setAutoResizeMode(JTable.AUTO_RESIZE_OFF); 

모든 열이 자신의 preffered 크기로 표시됩니다

수평 스크롤은 당신이 사용할 때 발생합니다. 뷰포트보다 작을 수있는 경우 빈 공간이 표시되거나 커질 수 있습니다.이 경우 스크롤 막대가 표시됩니다.

스크롤 막대가 나타나려면 ActionListenerresizeColumnWidth() 메서드를 호출해야합니다.

TableModel에서 데이터를 추가/변경하면 동적 열 크기 계산을 지원하는 Table Column Adjuster을 확인할 수도 있습니다.

+0

도움을 주셔서 감사합니다. 문제가 해결되었습니다. – Ansharja

+0

정확한 코드로 내 질문을 편집했습니다. 이미 setAutoResizeMode()와 resizeColumnWidth를 separatly로 사용했다는 사실은 꽤 재미 있습니다. 다시 감사합니다! – Ansharja