如何使用Renderer for TableHeader

甚至我也阅读并测试了@kleopatra的答案

  • 如何正确使用客户渲染器绘制JTable中的特定单元格?

  • 特别是一个表头颜色java swing

  • 关于super.getTableCellRendererComponent(...)必须是返回之前的最后一行代码行,我无法通过这些建议编写正确的渲染器,因为我只能这样工作

  • 为Borders,Horizo​​ntalAlignment和Foreground添加了JLabel ,特别是后台通过使用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(); } }); } } 

根据我的经验,最好在覆盖任何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 JTableHeader 。 要在表格单元格上添加渲染器,代码与上面的代码类似,只需通过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(…)必须是返回之前的最后一行代码行,我无法通过这些建议编写正确的渲染器,因为我只能这样工作

答:我不确定你的意思“必须在退货之前的最后一行代码行。” 情况并非如此,我在上面给出的代码片段certificate了这一点

问题4:

问:为Borders,Horizo​​ntalAlignment和Foreground添加了JLabel,特别是后台通过使用Component而不是JLabel引起了一些非句子,(这里不重要)

答:好的…… DefaultTableCellHeaderRenderer足以满足所有这些,边框,对齐,前景和背景。

我过去曾经遇到过这种情况,我确信它与Cell Renderer有关,但ArraysXxxException类型的Exceptions却因为忘记取消选择并在添加/删除行之前停止编辑单元格而ArraysXxxException了我。 你应该尝试clearSelection()table.getCellEditor().stopCellEditing(); 在删除/添加之前在JTable查看是否能解决您的问题。

首先,当然,确保它正在编辑:

 if (table.isEditing()) { table.getCellEditor().stopCellEditing(); }