我需要为JTable
的几列指定固定宽度,然后对所有其他列指定相等的宽度。按百分比设置JTable的列宽
假设JTable
有5列。第一列的宽度应为100,第二列的宽度应为150.如果在设置两列的宽度后JTable
的剩余宽度为600,则我希望将其平均分配到其他三列中。
问题是table.getParent().getSize().width
通常是0,即使它被添加到JFrame
并且可见,所以我不能用它作为基础。
我如何去这样做呢?
我需要为JTable
的几列指定固定宽度,然后对所有其他列指定相等的宽度。按百分比设置JTable的列宽
假设JTable
有5列。第一列的宽度应为100,第二列的宽度应为150.如果在设置两列的宽度后JTable
的剩余宽度为600,则我希望将其平均分配到其他三列中。
问题是table.getParent().getSize().width
通常是0,即使它被添加到JFrame
并且可见,所以我不能用它作为基础。
我如何去这样做呢?
我想你需要用table.getPreferredSize()
来代替。试试这个代码片段:
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
public class Tests {
private void initGUI(){
Object[] tableHeader = new Object[]{"Name", "Category", "Color","Ranking"};
DefaultTableModel dftm = new DefaultTableModel(tableHeader, 0);
dftm.addRow(new Object[]{"Watermelon","Fruit","Green and red",3});
dftm.addRow(new Object[]{"Tomato","Vegetable","Red",5});
dftm.addRow(new Object[]{"Carrot","Vegetable","Orange",2});
JTable table = new JTable(dftm);
JScrollPane scrollPane = new JScrollPane();
scrollPane.setViewportView(table);
Dimension tableSize = table.getPreferredSize();
table.getColumn("Name").setPreferredWidth(100);
table.getColumn("Category").setPreferredWidth(150);
table.getColumn("Color").setPreferredWidth(Math.round((tableSize.width - 250)* 0.70f));
table.getColumn("Ranking").setPreferredWidth(Math.round((tableSize.width - 250)* 0.30f));
JFrame frame = new JFrame("Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(scrollPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Tests().initGUI();
}
});
}
}
正如你所看到的,Name
列将具有100宽度,Category
将有150的宽度,Color
列将在合适宽度剩余的70%和Ranking
将适合的最后30%。
更新
基于此评论:
谢谢,但如果Jframe的大小设置得比JTable中明确 较大,这将不起作用......
解决方法可以使用setMinWidth
和setMaxWidth
方法修复静态列宽,也可以实现自己的TableColumnModelListener。在上面的例子中代替setPreferredWith
线如下,并尝试设置帧的优选尺寸为您希望:
final JTable table = new JTable(dftm);
table.getColumnModel().addColumnModelListener(new TableColumnModelListener() {
@Override
public void columnAdded(TableColumnModelEvent e) {
table.columnAdded(e);
}
@Override
public void columnRemoved(TableColumnModelEvent e) {
table.columnRemoved(e);
}
@Override
public void columnMoved(TableColumnModelEvent e) {
table.columnMoved(e);
}
@Override
public void columnMarginChanged(ChangeEvent e) {
Dimension tableSize = table.getSize();
table.getColumn("Name").setWidth(100);
table.getColumn("Category").setWidth(150);
table.getColumn("Color").setWidth(Math.round((tableSize.width - 250)* 0.70f));
table.getColumn("Ranking").setWidth(Math.round((tableSize.width - 250)* 0.30f));
}
@Override
public void columnSelectionChanged(ListSelectionEvent e) {
table.columnSelectionChanged(e);
}
});
我需要一个固定的宽度相等的宽度分配给一个JTable的几列,然后向所有的其他栏目。
让表格的调整大小模式为您做好工作。设置的调整模式,所有列,并设置固定列的最小值/最大值:
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
public class TableLayout extends JPanel
{
public TableLayout()
{
setLayout(new BorderLayout());
JTable table = new JTable(5, 7);
add(new JScrollPane(table));
table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
TableColumn columnA = table.getColumn("A");
columnA.setMinWidth(100);
columnA.setMaxWidth(100);
TableColumn columnC = table.getColumn("C");
columnC.setMinWidth(50);
columnC.setMaxWidth(50);
}
private static void createAndShowUI()
{
JFrame frame = new JFrame("TableLayout");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TableLayout());
frame.setSize(600, 200);
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
+1:当调整模式为AUTO_RESIZE_ALL_COLUMNS时,'column.setPreferredWidth()'不起作用,所以必须使用'setMin/MaxWidth()'。 – Matthieu
我不得不动态设置我的表中的列宽为一个项目,必须在不同的屏幕分辨率DPI设置正确显示。我的解决方案的想法来自dic19s的答案。
基本上我得到了JPanel的首选大小,JTable的JSrollPane被放置并工作得很好。请参考下面
Dimension tableSize = tableScrollPanePanel.getPreferredSize();
table.getColumnModel().getColumn(0).setPreferredWidth(Math.round(tableSize.width*0.35f));
table.getColumnModel().getColumn(1).setPreferredWidth(Math.round(tableSize.width*0.215f));
table.getColumnModel().getColumn(2).setPreferredWidth(Math.round(tableSize.width*0.20f));
table.getColumnModel().getColumn(3).setPreferredWidth(Math.round(tableSize.width*0.10f));
table.getColumnModel().getColumn(4).setPreferredWidth(Math.round(tableSize.width*0.10f));
希望这有助于有人
感谢
public MyJFrame() {
initComponents();
resizeColumns();
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
resizeColumns();
}
});
}
//SUMS 100%
float[] columnWidthPercentage = {20.0f, 55.0f, 10.0f, 5.0f, 5.0f, 5.0f};
private void resizeColumns() {
int tW = jTable1.getWidth();
TableColumn column;
TableColumnModel jTableColumnModel = jTable1.getColumnModel();
int cantCols = jTableColumnModel.getColumnCount();
for (int i = 0; i < cantCols; i++) {
column = jTableColumnModel.getColumn(i);
int pWidth = Math.round(columnWidthPercentage[i] * tW);
column.setPreferredWidth(pWidth);
}
}
这是我见过的最好的答案:) – 2015-08-17 07:11:05
请注意,您可以使用['TableColumnModel.getTotalColumnWidth()'](https://docs.oracle.com/javase/7/docs/api/javax/swing/table /TableColumnModel.html#getTotalColumnWidth()),以防您的表包含在“JScrollPane”中(通常是这种情况)。 – Matthieu
晚了一点,但columnWidthPercentage应该加起来1.0,否则你的桌子会变得非常快 –
它认为这将是更容易使用(和再利用)相对组分调整,如果我们在自己的封装它类。由于我也面临同样的问题,我想在这里发布我的代码。
从客户端的角度来看,我想这样做
TableColumnModel columnModel = jTable.getColumnModel();
TableColumn firstColumn = columnModel.getColumn(0);
TableColumn secondColumn = columnModel.getColumn(1);
ComponentResize<TableColumn> columnResize = new TableColumnResize();
RelativeWidthResizer<TableColumn> relativeWidthResizer = new RelativeWidthResizer<TableColumn>(columnResize);
relativeWidthResizer.setRelativeWidth(firstColumn, 0.8);
relativeWidthResizer.setRelativeWidth(secondColumn, 0.2);
jTable.addComponentListener(relativeWidthResizer);
所以我首先定义了ComponentResize
接口和实现TableColumnResize
public interface ComponentResize<T> {
public void setWidth(T component, int width);
}
public class TableColumnResize implements ComponentResize<TableColumn> {
public void setWidth(TableColumn component, int width) {
component.setPreferredWidth(width);
}
}
的ComponentResize
接口解耦组件大小的方式是从具体的API中设置的。例如。一个TableColumn
的宽度可以通过setPreferredWidth(int)
被设置而JComponent
的尺寸可以通过setPreferredWidth(Dimension)
比我实现封装的相对宽度计算逻辑的RelativeWidthResizer
进行设置。
public class RelativeWidthResizer<T> extends ComponentAdapter {
private Map<T, Double> relativeWidths = new HashMap<T, Double>();
private ComponentResize<T> componentResize;
public RelativeWidthResizer(ComponentResize<T> componentResize) {
this.componentResize = componentResize;
}
public void setRelativeWidth(T component, double relativeWidth) {
if (relativeWidth < 0.0) {
throw new IllegalArgumentException(
"Relative width must be greater or equal to 0.0");
}
if (relativeWidth > 1.0) {
throw new IllegalArgumentException(
"Relative width must be less or equal to 1.0");
}
double totalRelativeWidth = 0.0;
for (Double relativeComponentWidth : relativeWidths.values()) {
totalRelativeWidth += relativeComponentWidth.doubleValue();
}
double availableRelativeWidth = 1.0d - (totalRelativeWidth + relativeWidth);
boolean totalPercentageExceeded = availableRelativeWidth < 0;
if (totalPercentageExceeded) {
double remainingRelativeWidth = 1.0d - totalRelativeWidth;
String message = MessageFormat.format(
"Can't set component's relative width to {0}."
+ " {1} relative width remaining", relativeWidth,
remainingRelativeWidth);
throw new IllegalArgumentException(message);
}
relativeWidths.put(component, relativeWidth);
}
@Override
public void componentResized(ComponentEvent e) {
Component component = e.getComponent();
apply(component);
}
public void apply(Component baseComponent) {
Dimension size = baseComponent.getSize();
int maxWidth = (int) size.getWidth();
int remaining = maxWidth;
Set<Entry<T, Double>> entrySet = relativeWidths.entrySet();
Iterator<Entry<T, Double>> entrySetIter = entrySet.iterator();
while (entrySetIter.hasNext()) {
Entry<T, Double> componentEntry = entrySetIter.next();
T componentToResize = componentEntry.getKey();
Double relativeWidth = componentEntry.getValue();
int width = (int) (maxWidth * relativeWidth.doubleValue());
remaining -= width;
boolean lastComponent = !entrySetIter.hasNext();
if (lastComponent && remaining > 0) {
width += remaining;
}
componentResize.setWidth(componentToResize, width);
}
}
}
如果一个答案适用于你,接受它。 – Astrobleme