如何为 TableHeader 使用渲染器
Posted
技术标签:
【中文标题】如何为 TableHeader 使用渲染器【英文标题】:How to use Renderer for TableHeader 【发布时间】:2012-04-08 17:23:18 【问题描述】:即使我阅读和测试@kleopatra 的答案
How do I correctly use customer renderers to paint specific cells in a JTable?
particular one table header color java swing
关于super.getTableCellRendererComponent(...)
必须是返回前的最后一行代码,我无法根据这些建议编写正确的渲染器,对我来说只能这样工作
JLabel
被添加到 Borders、HorizontalAlignment 和 Foreground,尤其是 Background 通过使用 Component 而不是 JLabel
让我有些胡思乱想,(这里不重要)
来自SSCCE
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
public class SelectedTableHeader
private JFrame frame = new JFrame("Table Demo");
private JTableHeader header;
private Object selectedColumn = null;
private String[] columnNames = "String", "Integer", "Float", "Double", "Locale & Double", "Boolean";
private Object[][] data =
"aaa", new Integer(12), new Float(12.15), new Double(100.05), new Double(12.05), true,
"bbb", new Integer(5), new Float(7.154), new Double(6.1555), new Double(417.55), false,
"CCC", new Integer(92), new Float(0.1135), new Double(3.1455), new Double(11.05), true,
"ddd", new Integer(12), new Float(31.15), new Double(10.05), new Double(23.05), true,
"eee", new Integer(5), new Float(5.154), new Double(16.1555), new Double(17.55), false,
"fff", new Integer(92), new Float(4.1135), new Double(31.1455), new Double(3.05), true;
private TableModel model = new DefaultTableModel(data, columnNames)
private static final long serialVersionUID = 1L;
@Override
public Class<?> getColumnClass(int column)
return getValueAt(0, column).getClass();
;
private JTable table = new JTable(model);
public SelectedTableHeader()
header = table.getTableHeader();
header.addMouseListener(new MouseAdapter()
@Override
public void mouseClicked(MouseEvent e)
JTableHeader h = (JTableHeader) e.getSource();
int i = h.columnAtPoint(e.getPoint());
Object o = h.getColumnModel().getColumn(i).getHeaderValue();
if (i < 0)
selectedColumn = null;
return;
selectedColumn = o;
h.requestFocusInWindow();
);
final TableCellRenderer hr = table.getTableHeader().getDefaultRenderer();
header.setDefaultRenderer(new TableCellRenderer()
private JLabel lbl;
@Override
public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
if (selectedColumn == value)
lbl = (JLabel) hr.getTableCellRendererComponent(table, value, true, true, row, column);
lbl.setBorder(BorderFactory.createCompoundBorder(lbl.getBorder(), BorderFactory.createLineBorder(Color.red, 1)));
lbl.setHorizontalAlignment(SwingConstants.LEFT);
else
lbl = (JLabel) hr.getTableCellRendererComponent(table, value, false, false, row, column);
lbl.setBorder(BorderFactory.createCompoundBorder(lbl.getBorder(), BorderFactory.createEmptyBorder(0, 5, 0, 0)));
lbl.setHorizontalAlignment(SwingConstants.CENTER);
if (column == 0)
lbl.setForeground(Color.red);
else
lbl.setForeground(header.getForeground());
/*return (value == selectedColumn) ? hr.getTableCellRendererComponent(
table, value, true, true, row, column) : hr.getTableCellRendererComponent(
table, value, false, false, row, column);*/
return lbl;
);
table.setRowHeight(20);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scroll = new JScrollPane(table);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(scroll);
frame.pack();
frame.setLocation(150, 150);
frame.setVisible(true);
public static void main(String[] args)
EventQueue.invokeLater(new Runnable()
@Override
public void run()
SelectedTableHeader selectedTableHeader = new SelectedTableHeader();
);
【问题讨论】:
您遇到了什么问题? SSCCE 对我来说很好。 @Jakub Zaverka 也许 Render 没有问题,真的是我有 ArraysXxxException 的问题,通过实现 Renderer by (@kleopatra) EDIT 删除了 use_less RowSorter 你是什么意思,ArraysXxxException?像 ArrayIndexOutOfBoundsException 一样吗? @mKorbel:也适合我。我认为 kleopatra 的回答指的是DefaultTableCellRenderer
中的一个实现细节;相比之下,您对 TableCellRenderer
的自定义实现以不同的方式解决了该问题。
【参考方案1】:
根据我的经验,当您覆盖任何JTable
Renderer
时,最好获得DefaultTableCellHeaderRenderer
。因此,不要直接从Renderer
中弄乱JLabel
,而是使用super()
来获取Renderer
。因此,您的代码应如下所示:
header.setDefaultRenderer(new DefaultTableCellHeaderRenderer()
@Override
public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
DefaultTableCellHeaderRenderer rendererComponent = (DefaultTableCellHeaderRenderer)super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (selectedColumn == value)
rendererComponent.setBorder(BorderFactory.createCompoundBorder(rendererComponent.getBorder(), BorderFactory.createLineBorder(Color.red, 1)));
rendererComponent.setHorizontalAlignment(SwingConstants.LEFT);
else
rendererComponent.setBorder(BorderFactory.createCompoundBorder(rendererComponent.getBorder(), BorderFactory.createEmptyBorder(0, 5, 0, 0)));
rendererComponent.setHorizontalAlignment(SwingConstants.CENTER);
if (column == 0)
rendererComponent.setForeground(Color.red);
else
rendererComponent.setForeground(header.getForeground());
return rendererComponent;
);
尝试直接回答您的问题:
问题 1:
问:如何正确使用客户渲染器来绘制 JTable 中的特定单元格?
答:您当前的代码是在JTableHeader
上设置Renderer
。在表格单元格上添加渲染器与上面的代码类似,只是您需要通过 Column 模型进行设置:
table.getColumnModel().getColumn(0).setCellRenderer(new DefaultTableCellRenderer()
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
DefaultTableCellRenderer renderer = (DefaultTableCellRenderer)super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
// Set your code to render your component.
return renderer;
);
注意:JTables
是基于列的,这意味着某一列中的所有数据必须是相同的类型(您的 SSCCE 遵循此约定)。我最喜欢做的是为每种类型提供一个自定义的Renderer
。例如,每当我有一个Date
列时,我都会使用这个渲染器:
import java.awt.Component;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import org.joda.time.LocalDate;
/**
*
* @author Ryan
*/
public class DateCellRenderer extends DefaultTableCellRenderer
String pattern;
public DateCellRenderer(String pattern)
this.pattern = pattern;
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
DefaultTableCellRenderer renderer = (DefaultTableCellRenderer)super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (value != null && value instanceof LocalDate)
renderer.setText(((LocalDate)value).toString(pattern));
else
throw new IllegalArgumentException("Only supported Object type is LocalDate.");
return renderer;
我用类似的东西来称呼这段代码:
table.getColumn("Date Entered").setCellRenderer(new DateCellRenderer("MMM dd, yyyy"));
问题 2:
问:java swing 特定的一个表头颜色
A:嗯..您的 SSCCE 似乎已经弄清楚了。
问题 3:
问:关于 super.getTableCellRendererComponent(...) 必须是返回前的最后一行代码,我无法通过这些建议编写正确的 Renderer,对我来说只能这样工作
答:我不确定您的意思是“必须是返回前的最后一行代码”。事实并非如此,我上面给出的代码片段证明了这一点
问题 4:
问:为 Borders、HorizontalAlignment 和 Foreground 添加了 JLabel,尤其是 Background 通过使用 Component 而不是 JLabel 让我有些胡思乱想,(此处不重要)
A:好的...DefaultTableCellHeaderRenderer
足以满足所有这些要求,包括边框、对齐方式、前景和背景。
【讨论】:
【参考方案2】:我过去曾遇到过这种情况,我确信这与 Cell Renderer 有关,但 ArraysXxxException
类型的异常困扰着我,因为我忘记了取消选择并停止编辑 添加/删除行之前的单元格。在删除/添加之前,您应该在 JTable
上尝试 clearSelection()
和 table.getCellEditor().stopCellEditing();
,看看是否能解决您的问题。
首先,当然,确保它正在编辑:
if (table.isEditing())
table.getCellEditor().stopCellEditing();
【讨论】:
以上是关于如何为 TableHeader 使用渲染器的主要内容,如果未能解决你的问题,请参考以下文章