java JTable 中的页脚行
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/978865/
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
Footer row in a JTable
提问by Luke Quinane
What is the best way to put a footer row into a JTable? Does anyone have any sample code to do this?
将页脚行放入 JTable 的最佳方法是什么?有没有人有任何示例代码来做到这一点?
The only approach I've thought of so far is to put a special row into the table model that always get sorted to the bottom.
到目前为止,我想到的唯一方法是将一个特殊行放入表模型中,该行总是排序到底部。
Here is what I ended up with:
这是我最终的结果:
JTable mainTable = new JTable(mainTableModel);
JTable footerTable = new JTable(footerModel);
footerTable.setColumnModel(mainTable.getColumnModel());
// Disable selection in the footer. Otherwise you can select the footer row
// along with a row in the table and that can look quite strange.
footerTable.setRowSelectionAllowed(false);
footerTable.setColumnSelectionAllowed(false);
JPanel tablePanel = new JPanel();
BoxLayout boxLayout = new BoxLayout(tablePanel, BoxLayout.Y_AXIS);
tablePanel.setLayout(boxLayout);
tablePanel.add(mainTable.getTableHeader()); // This seems like a bit of a WTF
tablePanel.add(mainTable);
tablePanel.add(footerTable);
Sorting works fine but selecting the footer row is a bit strange.
排序工作正常,但选择页脚行有点奇怪。
回答by objects
Try using a second JTable that uses the same column model as your data table and add your footer data to that table. Add the second (footer) table under your original table.
尝试使用与数据表使用相同列模型的第二个 JTable,并将页脚数据添加到该表中。在原始表格下添加第二个(页脚)表格。
JTable footer = new JTable(model, table.getColumnModel());
panel.add(BorderLayout.CENTER, table);
panel.add(BorderLayout.SOUTH, footer);
回答by Umi
Looks like this projecthas a component called JideScrollPane which advertises support for a row footer. I haven't tried it myself, but it sounds like it does exactly what you want! The website also has a demo app where you can see it in action and it that looks pretty good.
看起来这个项目有一个名为 JideScrollPane 的组件,它宣传对行页脚的支持。我自己还没有尝试过,但听起来它完全符合您的要求!该网站还有一个演示应用程序,您可以在其中看到它的运行情况,而且看起来还不错。
Note that it seems a lot of the their stuff you have to pay for, but their JideScrollPane looks to be free and open source.
请注意,似乎您必须为他们的很多东西付费,但他们的 JideScrollPane 看起来是免费和开源的。
回答by Jens
Using 2 tables below each-other is a good approach.
使用彼此下方的 2 个表是一个好方法。
If you want to be able to resize/move/remove the colums, key is NOT to reuse the same columnModel between the tables. Have a listener do the resizing. See example:
如果您希望能够调整/移动/删除列的大小,关键是不要在表之间重用相同的 columnModel。让听众做调整大小。见示例:
package snippet;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.TableColumnModelEvent;
import javax.swing.event.TableColumnModelListener;
import javax.swing.table.TableColumnModel;
public class FixedRow2Tables extends JFrame {
private static final long serialVersionUID = 4676303089799270571L;
Object[][] data;
Object[] column;
JTable footerTable, table;
public FixedRow2Tables() {
super("Fixed Row Example");
Object[][] mainData = new Object[][] { { "a", "", "", "", "", "" },
{ "", "b", "", "", "", "" }, { "", "", "c", "", "", "" },
{ "", "", "", "d", "", "" }, { "", "", "", "", "e", "" },
{ "", "", "", "", "", "f" } };
Object[][] summaryData = { { "fixed1", "", "", "", "", "" },
{ "fixed2", "", "", "", "", "" } };
column = new Object[] { "A", "B", "C", "D", "E", "F" };
table = new JTable(mainData, column);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
footerTable = new JTable(summaryData, column);
footerTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
footerTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
footerTable.setTableHeader(null);
// footerTable.setColumnModel(table.getColumnModel());
table.getColumnModel().addColumnModelListener(
new TableColumnModelListener() {
@Override
public void columnSelectionChanged(ListSelectionEvent e) {
}
@Override
public void columnRemoved(TableColumnModelEvent e) {
}
@Override
public void columnMoved(TableColumnModelEvent e) {
}
@Override
public void columnMarginChanged(ChangeEvent e) {
final TableColumnModel tableColumnModel = table
.getColumnModel();
TableColumnModel footerColumnModel = footerTable
.getColumnModel();
for (int i = 0; i < tableColumnModel.getColumnCount(); i++) {
int w = tableColumnModel.getColumn(i).getWidth();
footerColumnModel.getColumn(i).setMinWidth(w);
footerColumnModel.getColumn(i).setMaxWidth(w);
// footerColumnModel.getColumn(i).setPreferredWidth(w);
}
footerTable.doLayout();
footerTable.repaint();
repaint();
}
@Override
public void columnAdded(TableColumnModelEvent e) {
}
});
JScrollPane scroll = new JScrollPane(table);
scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scroll.setPreferredSize(new Dimension(400, 100));
getContentPane().add(scroll, BorderLayout.CENTER);
getContentPane().add(footerTable, BorderLayout.SOUTH);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
FixedRow2Tables frame = new FixedRow2Tables();
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.pack();
frame.setVisible(true);
}
});
}
}
回答by johnny
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
import javax.swing.table.*;
class Application extends JFrame
{
public Application()
{
this.setBounds(100,100,500,200);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
String data[][] = {{"a1","b1","c1"},{"a2","b2","c2"},{"a3","b3","c3"}};
String columnNames[] = {"a","b","c"};
JTable jtable = new JTable(new DefaultTableModel(data,columnNames));
JScrollPane jscrollPane = new JScrollPane(jtable,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
jscrollPane.setBorder(new CompoundBorder(new MatteBorder(0,0,1,0,Color.gray),new EmptyBorder(0,0,0,0)));
this.add(jscrollPane,BorderLayout.CENTER);
JTable jtable_footer = new JTable(new DefaultTableModel(3,columnNames.length),jtable.getColumnModel());
SyncListener syncListener = new SyncListener(jtable,jtable_footer);
this.add(jtable_footer,BorderLayout.SOUTH);
}
public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
Application application = new Application();
application.setVisible(true);
}
});
}
}
class SyncListener implements TableColumnModelListener
{
JTable jtable_data;
JTable jtable_footer;
public SyncListener(JTable main, JTable footer)
{
jtable_data = main;
jtable_footer = footer;
DefaultTableColumnModel dtcm = (DefaultTableColumnModel)jtable_data.getColumnModel();
dtcm.removeColumnModelListener(dtcm.getColumnModelListeners()[1]);
dtcm.addColumnModelListener(this);
}
public void columnMarginChanged(ChangeEvent changeEvent)
{
for (int column = 0; column < jtable_data.getColumnCount(); column++)
{
jtable_footer.getColumnModel().getColumn(column).setWidth(jtable_data.getColumnModel().getColumn(column).getWidth());
}
jtable_footer.repaint();
}
public void columnAdded(TableColumnModelEvent e){}
public void columnMoved(TableColumnModelEvent e){}
public void columnRemoved(TableColumnModelEvent e){}
public void columnSelectionChanged(ListSelectionEvent e){}
}
回答by javamonkey79
The only time I have done this I just added a row in the model like so:
我唯一一次这样做时,我只是在模型中添加了一行,如下所示:
@Override
public int getRowCount() {
return _tableContents.size() + 1;
}
_tableContents is of course the actual data behind my model. You'll have to be aware of the extra row in the model of course (in such calls as setValueAt(...))
_tableContents 当然是我的模型背后的实际数据。当然,您必须注意模型中的额外行(在诸如 setValueAt(...) 之类的调用中)
Good luck.
祝你好运。
回答by Cogsy
You could try implementing your own TableCellRendererthat replaces the rendered content of the last visible row with your footer. However this wouldn't be fixed at the bottom of the table, it will likely shift up and down as you scroll.
您可以尝试实现自己的TableCellRenderer,用您的页脚替换最后可见行的呈现内容。但是,这不会固定在表格底部,它可能会随着您滚动而上下移动。
回答by ninesided
I guess the best approach (but certainly not the easiest) would be to take a look at the source code for the JTableHeaderComponent, see how it works and then create your own JTableFooterComponent. You can re-use the JTableHeaderUI Delegate for the footer, I think the main differences would be in the getHeaderRect()method, where it determines the bounds of a given column header tile.
我想最好的方法(但肯定不是最简单的)是查看JTableHeader组件的源代码,看看它是如何工作的,然后创建自己的JTableFooter组件。您可以将JTableHeaderUI Delegate重新用于页脚,我认为主要区别在于getHeaderRect()方法,它确定给定列标题磁贴的边界。
回答by Dinesh Bhat
Here is another solution mentioned in the java bug database
这里是java bug数据库中提到的另一个解决方案
A solution that works for me is painting a border for the viewport (your JTable must be inside a JScrollPane) ....
对我有用的解决方案是为视口绘制边框(您的 JTable 必须在 JScrollPane 内)....

