我在JScrollPane中有一個JTable,並且我重寫了getPreferredScrollableViewportSize以便將JScrollPane適合固定數量的錶行,從而允許在需要時顯示滾動條。 我還使用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));
}
}
編輯:
感謝@camickr,我解決了這個問題,設置所需的自動調整模式,每加一排一次回顧resizeColumnWidth方法。 我已經分開審訊他們,我不能相信我沒有使用這兩個:)
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));
}
}
感謝您發佈MCVE與您的問題。 (+1),當然也適用於camickr。 –