2017-02-20 2 views
4

JScrollPaneの中にJTableがあり、必要なときにスクロールバーが表示されるように、JScrollPaneを固定した数のテーブル行に合わせるためにgetPreferredScrollableViewportSizeをオーバーライドしています。 また、SOにあるコードの一部を使用して、テーブルの列の内容に合わせてサイズを変更しました。getPreferredScrollableViewportSizeを適切にオーバーライドします。

問題は、テーブルに幅広の行を追加すると、水平の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)); 
    } 
} 

編集:

@camickrのおかげで、私は、所望の自動サイズ変更モードを設定し、resizeColumnWidth方法に行が追加されるたびに思い出し、問題を解決しました。

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)、またもちろんカミカに。 –

答えて

4

私:私はすでにそれらを個別に試してみました、私は両方を使用していませんでした:)

Hovewer信じることができない、私は更新されたコード、今それがうまく機能の下に投稿しました 動的にテーブルに幅の広い行を追加すると、水平のJScrollBarは表示されません。

setAutoResizeMode(JTable.AUTO_RESIZE_OFF); 

すべての列は、その兼ね備えサイズで表示されます。

水平スクロールバーにのみ、使用するときに発生します。ビューポートよりも小さい場合は、空白が表示されます。大きい場合は、スクロールバーが表示されます。

スクロールバーが表示されるように、ActionListenerresizeColumnWidth()メソッドを呼び出す必要があります。

TableModelでデータが追加/変更されると、動的列サイズの計算をサポートするTable Column Adjusterをチェックアウトすることもできます。

+0

あなたのおかげで、私の問題を解決しました。 – Ansharja

+0

正しいコードで質問を編集しました。私はすでにsetAutoResizeMode()とresizeColumnWidthを分離して使用していましたが、それらをtogheterにするのは面白いです。ありがとうございました! – Ansharja

関連する問題