我遇到了一个以前已经讨论过的问题:获取一个包含JTable的JScrollPane来显示我想要的水平滚动条。HERE是我尝试关注的一个帖子,但由于某种原因,它似乎不适合我的情况(我想这是因为我设置了一个固定宽度的列)。
这是一个SSCCE:
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
@SuppressWarnings("serial")
public class TableScrollTest extends JFrame
{
public TableScrollTest() {
DefaultTableModel model = new DefaultTableModel(new Object[]{"key", "value"},0);
model.addRow(new Object[]{"short", "blah"});
model.addRow(new Object[]{"long", "blah blah blah blah blah blah blah"});
JTable table = new JTable(model) {
public boolean getScrollableTracksViewportWidth() {
return getPreferredSize().width < getParent().getWidth();
}
};
table.getColumn("key").setPreferredWidth(60);
table.getColumn("key").setMinWidth(60);
table.getColumn("key").setMaxWidth(60);
table.setAutoResizeMode( JTable.AUTO_RESIZE_OFF );
JScrollPane scrollPane = new JScrollPane( table );
getContentPane().add( scrollPane );
}
public static void main(String[] args) {
TableScrollTest frame = new TableScrollTest();
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.pack();
frame.setSize(200, 200);
frame.setResizable(false);
frame.setVisible(true);
}
}简而言之,我有一个包含两列的表,用于显示键/值对。存放表的容器是固定宽度的,表的第一列也是固定宽度的(因为我知道所有键名的长度)。第二列将包含不同字符串长度的值。只有当存在的值太长,无法适应分配给列的宽度时,才应显示水平滚动条。

因为上面的第二个值的长度很长,所以滚动条应该是可见的。然而,事实并非如此,我尝试过的所有事情都只是成功地让它总是可见,这并不是我想要的……我只想让它在"long“值存在的情况下可见。似乎在表格构造函数中被覆盖的getScrollableTracksViewportWidth()方法检查表格的首选宽度是多少……所以我需要让表格根据第二列的内容选择一个更大的宽度。但我被难住了。
有什么想法吗?
发布于 2013-02-22 09:34:55
这是一个hackey解决方案
基本上,它所做的就是根据所有行的值来计算所有列的“首选”宽度。
它考虑了对模型的更改以及对父容器的更改。
完成后,它会检查“首选”宽度是大于还是小于可用空间,并相应地设置trackViewportWidth变量。
您可以添加对固定列的检查(我没有费心),这将使过程“稍微”快一些,但当您向表中添加更多的列和行时,这将受到影响,因为每次更新都需要遍历整个模型。
您可以放入某种类型的缓存,但就在那时,我会考虑固定宽度的列;)
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.JFrame;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JViewport;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.TableColumnModelEvent;
import javax.swing.event.TableColumnModelListener;
import javax.swing.event.TableModelEvent;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class TableScrollTest extends JFrame {
public TableScrollTest() {
DefaultTableModel model = new DefaultTableModel(new Object[]{"key", "value"}, 0);
model.addRow(new Object[]{"short", "blah"});
model.addRow(new Object[]{"long", "blah blah blah blah blah blah blah"});
JTable table = new JTable(model) {
private boolean trackViewportWidth = false;
private boolean inited = false;
private boolean ignoreUpdates = false;
@Override
protected void initializeLocalVars() {
super.initializeLocalVars();
inited = true;
updateColumnWidth();
}
@Override
public void addNotify() {
super.addNotify();
updateColumnWidth();
getParent().addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
invalidate();
}
});
}
@Override
public void doLayout() {
super.doLayout();
if (!ignoreUpdates) {
updateColumnWidth();
}
ignoreUpdates = false;
}
protected void updateColumnWidth() {
if (getParent() != null) {
int width = 0;
for (int col = 0; col < getColumnCount(); col++) {
int colWidth = 0;
for (int row = 0; row < getRowCount(); row++) {
int prefWidth = getCellRenderer(row, col).
getTableCellRendererComponent(this, getValueAt(row, col), false, false, row, col).
getPreferredSize().width;
colWidth = Math.max(colWidth, prefWidth + getIntercellSpacing().width);
}
TableColumn tc = getColumnModel().getColumn(convertColumnIndexToModel(col));
tc.setPreferredWidth(colWidth);
width += colWidth;
}
Container parent = getParent();
if (parent instanceof JViewport) {
parent = parent.getParent();
}
trackViewportWidth = width < parent.getWidth();
}
}
@Override
public void tableChanged(TableModelEvent e) {
super.tableChanged(e);
if (inited) {
updateColumnWidth();
}
}
public boolean getScrollableTracksViewportWidth() {
return trackViewportWidth;
}
@Override
protected TableColumnModel createDefaultColumnModel() {
TableColumnModel model = super.createDefaultColumnModel();
model.addColumnModelListener(new TableColumnModelListener() {
@Override
public void columnAdded(TableColumnModelEvent e) {
}
@Override
public void columnRemoved(TableColumnModelEvent e) {
}
@Override
public void columnMoved(TableColumnModelEvent e) {
if (!ignoreUpdates) {
ignoreUpdates = true;
updateColumnWidth();
}
}
@Override
public void columnMarginChanged(ChangeEvent e) {
if (!ignoreUpdates) {
ignoreUpdates = true;
updateColumnWidth();
}
}
@Override
public void columnSelectionChanged(ListSelectionEvent e) {
}
});
return model;
}
};
table.getColumn("key").setPreferredWidth(60);
// table.getColumn("key").setMinWidth(60);
// table.getColumn("key").setMaxWidth(60);
// table.setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN);
JScrollPane scrollPane = new JScrollPane(table);
getContentPane().add(scrollPane);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
TableScrollTest frame = new TableScrollTest();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.pack();
frame.setSize(200, 200);
frame.setResizable(true);
frame.setVisible(true);
}
});
}
}发布于 2013-02-22 09:28:26
看起来我的目标是强制单元格渲染器自动使单元格适合长字符串
这不是渲染器的工作。必须手动设置列的宽度。
有关此操作的一种方法,请参阅Table Column Adjuster。
发布于 2013-02-22 09:34:55
如果有更聪明的帖子,我不一定会接受这个答案,但这是我根据目前发表的评论和THIS帖子自己想出的一个解决方案。唯一的问题是,我想出的宽度总是太短~1像素(在一些外观上,它是ok的),所以我在末尾的width += 5附近添加了这一行,这似乎使它工作正常,但对我来说它感觉很粗糙。欢迎对此方法的任何意见。
import java.awt.Component;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
@SuppressWarnings("serial")
public class TableScrollTest extends JFrame {
public TableScrollTest() {
DefaultTableModel model = new DefaultTableModel(new Object[]{"key", "value"},0);
model.addRow(new Object[]{"short", "blah"});
model.addRow(new Object[]{"long", "blah blah blah blah blah blah blah"});
JTable table = new JTable(model);
table.getColumn("key").setPreferredWidth(60);
table.getColumn("key").setMinWidth(60);
table.getColumn("key").setMaxWidth(60);
table.setAutoResizeMode( JTable.AUTO_RESIZE_OFF );
int width = 0;
for (int row = 0; row < table.getRowCount(); row++) {
TableCellRenderer renderer = table.getCellRenderer(row, 1);
Component comp = table.prepareRenderer(renderer, row, 1);
width = Math.max (comp.getPreferredSize().width, width);
}
width += 5;
table.getColumn("value").setPreferredWidth(width);
table.getColumn("value").setMinWidth(width);
table.getColumn("value").setMaxWidth(width);
JScrollPane scrollPane = new JScrollPane( table );
getContentPane().add( scrollPane );
}
public static void main(String[] args) {
TableScrollTest frame = new TableScrollTest();
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.pack();
frame.setSize(200, 200);
frame.setResizable(false);
frame.setVisible(true);
}
}https://stackoverflow.com/questions/15014950
复制相似问题