Java 按百分比设置JTable的列宽
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19012691/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Set Column Width of JTable by Percentage
提问by Tom Tucker
I need to assign a fixed width to a few columns of a JTable
and then an equal width to all the other columns.
我需要为 a 的几列分配一个固定宽度JTable
,然后为所有其他列分配一个相等的宽度。
Suppose a JTable
has 5 columns. The first column should have a width of 100 and the second one a width of 150. If the remaining width of the JTable
is 600 after setting the width of the two columns, I'd like to evenly split it among the other three columns.
假设 aJTable
有 5 列。第一列的宽度应该是100,第二列的宽度应该是150。如果JTable
设置了两列的宽度后剩下的宽度是600,我想将它平均分配给其他三列。
The problem is table.getParent().getSize().width
is often 0, even if it is added to the JFrame
and visible, so I can't use it as a basis.
问题是table.getParent().getSize().width
经常是0,即使加到JFrame
和可见,也不能作为依据。
How do I go about doing this?
我该怎么做?
回答by dic19
I think you need to use table.getPreferredSize()
instead. Try this code snippet:
我认为你需要使用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();
}
});
}
}
As you'll see, Name
column will have a width of 100, Category
will have a width of 150, Color
column will fit at 70% of remanent width and Ranking
will fit at last 30%.
如您所见,Name
列的宽度为 100,Category
宽度为 150,Color
列将适合剩余宽度的 70% 并Ranking
适合最后 30%。
Update
更新
Based on this comment:
基于此评论:
Thanks, but this will not work if the JFrame's size is set explicitly larger than the JTable...
谢谢,但是如果 JFrame 的大小设置为显式大于 JTable,这将不起作用...
Solution could be play with setMinWidth
and setMaxWidth
methods to fix static columns width, or you can implement your own TableColumnModelListener. In the example above replace setPreferredWith
lines as follows and try set frame's preferred size as you wish:
解决方案可以使用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);
}
});
回答by camickr
I need to assign a fixed width to a few columns of a JTable and then an equal width to all the other columns.
我需要为 JTable 的几列分配一个固定宽度,然后为所有其他列分配一个相等的宽度。
Let the table's resize mode do the work for you. Set the resize mode to all columns and set the min/max values of the fixed columns:
让表格的调整大小模式为您完成工作。将调整大小模式设置为所有列并设置固定列的最小值/最大值:
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();
}
});
}
}
回答by bluchip.gr
I had to dynamically set my table columns width for a project that had to display correctly on different screen resolution DPI settings. The idea for my solution came from dic19s answer.
我必须为必须在不同屏幕分辨率 DPI 设置下正确显示的项目动态设置表格列宽。我的解决方案的想法来自 dic19s answer。
Basically I got the preferred size of the JPanel where the JSrollPane of the JTable was placed and work great. Please see below
基本上我得到了 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));
Hope this helps somebody
希望这可以帮助某人
Thanks
谢谢
回答by Carlos Parraga
public MyJFrame() {
initComponents();
resizeColumns();
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
resizeColumns();
}
});
}
//SUMS 1
float[] columnWidthPercentage = {0.2f, 0.55f, 0.1f, 0.05f, 0.05f, 0.05f};
private void resizeColumns() {
// Use TableColumnModel.getTotalColumnWidth() if your table is included in a JScrollPane
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);
}
}
回答by René Link
It think it would be easier to use (and re-use) relative component resizing if we encapsulate it in an own class. Since I also was confronted with the same issue, I would like to post my code here.
如果我们将其封装在自己的类中,它认为使用(和重用)相对组件调整大小会更容易。由于我也遇到了同样的问题,我想在这里发布我的代码。
From a client perspective I would like to do something like this
从客户的角度来看,我想做这样的事情
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);
So I first defined the ComponentResize
interface and implement a TableColumnResize
所以我首先定义了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);
}
}
The ComponentResize
interface decouples the way a component's size is set from the concrete APIs. E.g. a TableColumn
's width can be set via setPreferredWidth(int)
while a JComponent
's size can be set by setPreferredWidth(Dimension)
该ComponentResize
接口将组件大小的设置方式与具体的 API 分离。例如 aTableColumn
的宽度可以通过设置setPreferredWidth(int)
而 aJComponent
的大小可以通过setPreferredWidth(Dimension)
Than I implemented the RelativeWidthResizer
that encapsulates the relative width calculation logic.
比我实现的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);
}
}
}