我需要根据标题中的文字获得合适的表格大小。它包含捷克名称的缩写,例如:“Po”,“Út”,“St”,atc。但不是显示这三个点。
我有这段代码:
width
,height
- 所有最小行/列大小的最大值
allWidth
,allHeight
- 应该是整个表格的总宽度,高度
//GET DIMENSION
int width = 0;
int height = 0;
int allWidth, allHeight;
for (int col = 0; col < table.getColumnCount(); col++) {
TableColumn tableColumn = table.getTableHeader().getColumnModel().getColumn(col);
TableCellRenderer renderer = tableColumn.getHeaderRenderer();
if (renderer == null) {
renderer = table.getTableHeader().getDefaultRenderer();
}
Component component = renderer.getTableCellRendererComponent(table,
tableColumn.getHeaderValue(), false, false, -1, col);
width = Math.max(component.getPreferredSize().width, width);
table.getColumnModel().getColumn(col).setPreferredWidth(width);
}
allWidth = table.getColumnCount() * width;
for (int row = 0; row < table.getRowCount(); row++) {
TableCellRenderer renderer = table.getCellRenderer(row, 0);
Component comp = table.prepareRenderer(renderer, row, 0);
height = Math.max(comp.getMinimumSize().height, height);
}
allHeight = table.getRowCount() * height;
//HERE I SET WIDTHS AND HEIGHTS
table.setRowHeight(height);
table.setMinimumSize(new Dimension(allWidth, allHeight));
scrollPane.setMinimumSize(new Dimension(allWidth, allHeight));
我正在使用GridBagLayout进行此设置,我认为这没问题:
this.setBorder(BorderFactory.createTitledBorder("Calendar"));
gbc.fill = GridBagConstraints.NONE;
gbc.gridx = 0;
gbc.gridy = 1; //position x=0, y=0 is for JSpinners, months and years
gbc.weighty = 0;
gbc.weightx = 0;
add(scrollPane,gbc);//add table in a custom Calendar component
此外,我改变了外观和感觉,这导致了这三个点。否则,名称会正确显示。
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {
}
这就是我初始化JTable和JScrollPane的方式,我觉得这样也可以。
setTable(new JTable());
getTable().setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
getTable().setAutoscrolls(false);
getTable().getTableHeader().setResizingAllowed(false);
getTable().getTableHeader().setReorderingAllowed(false);
getTable().setColumnSelectionAllowed(true);
getTable().setRowSelectionAllowed(true);
getTable().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
tableModel = new CalendarTableModel(); //my class extended from AbstractTableModel
getTable().setModel(tableModel);
scrollPane = new JScrollPane(table,JScrollPane.VERTICAL_SCROLLBAR_NEVER,JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setAutoscrolls(false);
问题:
如果我没有使用gbc设置scrollPane来调整自身大小,除非我手动计算并设置table
和scrollPane
的最小大小,否则它将获得最小可能的大小。 (左图)
allHeight = (1+table.getRowCount()+pady) * height; //plus one line of header
allWidth = table.getColumnCount() * width;
我在右边看到了照片。
这是一个简单的完整可编译类,用于演示此问题:
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
public class Main {
public static void main(String[] args) {
new Main().start();
}
private void start() {
JFrame f = new JFrame();
f.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
initTable();
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {
}
JPanel calendar = new JPanel();
calendar.setLayout(new GridBagLayout());
calendar.setBorder(BorderFactory.createTitledBorder("Calendar"));
gbc.fill = GridBagConstraints.NONE;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weighty = 0;
gbc.weightx = 0;
calendar.add(scrollPane, gbc);
f.add(calendar,gbc);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
JTable table;
JScrollPane scrollPane;
CalendarTableModel tableModel;
private void initTable() {
setTable(new JTable());
getTable().setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
getTable().setAutoscrolls(false);
getTable().getTableHeader().setResizingAllowed(false);
getTable().getTableHeader().setReorderingAllowed(false);
getTable().setColumnSelectionAllowed(true);
getTable().setRowSelectionAllowed(true);
getTable().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
tableModel = new CalendarTableModel(); //my class extended from AbstractTableModel
getTable().setModel(tableModel);
scrollPane = new JScrollPane(table, JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setAutoscrolls(false);
//GET DIMENSION
int width = 0;
int height = 0;
int allWidth, allHeight;
int padx = 2,pady = 2;
for (int col = 0; col < table.getColumnCount(); col++) {
TableColumn tableColumn = table.getTableHeader().getColumnModel().getColumn(col);
TableCellRenderer renderer = tableColumn.getHeaderRenderer();
if (renderer == null) {
renderer = table.getTableHeader().getDefaultRenderer();
}
Component component = renderer.getTableCellRendererComponent(table,
tableColumn.getHeaderValue(), false, false, -1, col);
width = Math.max(component.getPreferredSize().width, width);
table.getColumnModel().getColumn(col).setPreferredWidth(width);
}
allWidth = (table.getColumnCount()+padx) * width;
for (int row = 0; row < table.getRowCount(); row++) {
TableCellRenderer renderer = table.getCellRenderer(row, 0);
Component comp = table.prepareRenderer(renderer, row, 0);
height = Math.max(comp.getMinimumSize().height, height);
}
allHeight = (1+table.getRowCount()+pady) * height;
//HERE I SET WIDTHS AND HEIGHTS
table.setRowHeight(height);
table.setMinimumSize(new Dimension(allWidth, allHeight));
scrollPane.setMinimumSize(new Dimension(allWidth, allHeight));
}
private void setTable(JTable jTable) {
this.table = jTable;
}
private JTable getTable() {
return this.table;
}
private class CalendarTableModel extends AbstractTableModel {
private String[] daysData = {"Po", "Út", "St", "Čt", "Pá", "So", "Ne"};
private int[][] values;
public CalendarTableModel() {
values = new int[7][6];
for (int i = 0; i < 6; i++) {
for (int j = 0; j < 7; j++) {
values[j][i] = 7;
}
}
}
@Override
public int getRowCount() {
return 6;
}
@Override
public int getColumnCount() {
return 7;
}
@Override
public String getColumnName(int column) {
return daysData[column];
}
@Override
public Object getValueAt(int row, int column) {
return this.values[column][row];
}
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
}
}
答案 0 :(得分:6)
你可以得到这个
通过
f.pack()
之前 f.setVisible(true);
所需的widht应为22/23像素x,但component.getPreferredSize(
)或SwingUtilities#computeStringWidth(FontMetrics fm, String str)
仅返回17/18且仅table.getIntercellSpacing().width
只有一个像素,用于Po - Ne
请注意,实际的解决方法可以基于TableColumnAdjuster by @camickr
来自代码
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.text.JTextComponent;
public class Main {
public static void main(String[] args) {
new Main().start();
}
private void start() {
JFrame f = new JFrame();
f.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
initTable();
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {
}
JPanel calendar = new JPanel();
calendar.setLayout(new GridBagLayout());
calendar.setBorder(BorderFactory.createTitledBorder("Calendar"));
gbc.fill = GridBagConstraints.NONE;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weighty = 0;
gbc.weightx = 0;
calendar.add(scrollPane, gbc);
f.add(calendar, gbc);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack();
f.setVisible(true);
}
JTable table;
JScrollPane scrollPane;
CalendarTableModel tableModel;
private void initTable() {
setTable(new JTable());
getTable().setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
getTable().setAutoscrolls(false);
getTable().getTableHeader().setResizingAllowed(false);
getTable().getTableHeader().setReorderingAllowed(false);
getTable().setColumnSelectionAllowed(true);
getTable().setRowSelectionAllowed(true);
getTable().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
tableModel = new CalendarTableModel(); //my class extended from AbstractTableModel
getTable().setModel(tableModel);
scrollPane = new JScrollPane(table, JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setAutoscrolls(false);
TableColumnModel columnModel = table.getColumnModel();
for (int col = 0; col < table.getColumnCount(); col++) {
int maxWidth = 0;
for (int row = 0; row < table.getRowCount(); row++) {
TableCellRenderer rend = table.getCellRenderer(row, col);
Object value = table.getValueAt(row, col);
Component comp = rend.getTableCellRendererComponent(table, value, false, false, row, col);
maxWidth = Math.max(comp.getPreferredSize().width, maxWidth);
}
TableColumn column = columnModel.getColumn(col);
TableCellRenderer headerRenderer = column.getHeaderRenderer();
if (headerRenderer == null) {
headerRenderer = table.getTableHeader().getDefaultRenderer();
}
Object headerValue = column.getHeaderValue();
Component headerComp = headerRenderer.getTableCellRendererComponent(table, headerValue, false, false, 0, col);
maxWidth = Math.max(maxWidth, headerComp.getPreferredSize().width);
// note some extra padding
column.setPreferredWidth(maxWidth + 6);//IntercellSpacing * 2 + 2 * 2 pixel instead of taking this value from Borders
}
DefaultTableCellRenderer stringRenderer = (DefaultTableCellRenderer) table.getDefaultRenderer(String.class);
stringRenderer.setHorizontalAlignment(SwingConstants.CENTER);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
}
private void setTable(JTable jTable) {
this.table = jTable;
}
private JTable getTable() {
return this.table;
}
private class CalendarTableModel extends AbstractTableModel {
private String[] daysData = {"Pondelok", "Út", "St", "Čt", "Pá", "Sobota", "Ne"};
private int[][] values;
public CalendarTableModel() {
values = new int[7][6];
for (int i = 0; i < 6; i++) {
for (int j = 0; j < 7; j++) {
values[j][i] = 30;
}
}
}
@Override
public int getRowCount() {
return 6;
}
@Override
public int getColumnCount() {
return 7;
}
@Override
public String getColumnName(int column) {
return daysData[column];
}
@Override
public Object getValueAt(int row, int column) {
return this.values[column][row];
}
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
}
}
答案 1 :(得分:2)
这是一个很棒的代码,可以自动调整JTable中的标题和单元格内容:
jTable1.setAutoResizeMode(JTable.AUTO_RESIZE_OFF );
for (int column = 0; column < jTable1.getColumnCount(); column++){
TableColumn tableColumn = jTable1.getColumnModel().getColumn(column);
int preferredWidth = tableColumn.getMinWidth();
int maxWidth = 0;
TableCellRenderer rend = jTable1.getTableHeader().getDefaultRenderer();
TableCellRenderer rendCol = tableColumn.getHeaderRenderer();
if (rendCol == null) rendCol = rend;
Component header = rendCol.getTableCellRendererComponent(jTable1, tableColumn.getHeaderValue(), false, false, 0, column);
maxWidth = header.getPreferredSize().width;
System.out.println("maxWidth :"+maxWidth);
for (int row = 0; row < jTable1.getRowCount(); row++){
TableCellRenderer cellRenderer = jTable1.getCellRenderer(row, column);
Component c = jTable1.prepareRenderer(cellRenderer, row, column);
int width = c.getPreferredSize().width + jTable1.getIntercellSpacing().width;
preferredWidth = Math.max(preferredWidth, width);
System.out.println("preferredWidth :"+preferredWidth);
System.out.println("Width :"+width);
// We've exceeded the maximum width, no need to check other rows
if (preferredWidth <= maxWidth){
preferredWidth = maxWidth;
break;
}
}
tableColumn.setPreferredWidth(preferredWidth);
}
答案 2 :(得分:1)
我来解决方案: - )
在计算合适的列宽之前,我不得不改变外观。当我反过来这样做时,计算已经过时了。
所以我只需要像这样设置正确的宽度:
table.getColumnModel().getColumn(col).setPreferredWidth(width);
然后像这样更改viewPort的大小,因为表的首选大小现在是正确的。
table.setPreferredScrollableViewportSize(table.getPreferredSize());
谢谢! ;)