How to use Renderer for TableHeader

青春壹個敷衍的年華 提交于 2019-11-27 03:54:13

问题


Even I read and test answers by @kleopatra

  • How do I correctly use customer renderers to paint specific cells in a JTable?

  • particular one table header color java swing

  • about super.getTableCellRendererComponent(...) must be last code line before returns, I'm not able to write correct Renderer by those suggestion, for me works only this way

  • JLabel is added for Borders, HorizontalAlignment and Foreground, especially Background caused me a few non_senses by using Component instead of JLabel, (not important here somehow)

from 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();
            }
        });
    }
}

回答1:


In my experience, it's better to get the DefaultTableCellHeaderRenderer when you overwrite any JTable Renderer. So, instead of messing with the JLabel from the Renderer directly, you grab the Renderer with super(). So, your code should look like this:

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;
    }
});

To try and answer your questions directly:

Question 1:

Q: How do I correctly use customer renderers to paint specific cells in a JTable?

A: Your current code is setting a Renderer on the JTableHeader. To add a Renderer on your table cells would be similar code to what's above, only you'd set it through the Column model:

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;
    }

});

Note about this: JTables are column-based, which means that all the data in a certain column must be the same type (your SSCCE follows this convention). My favorite thing to do is to provide a custom Renderer for each type. For example, whenever I have a Date column, I use this renderer:

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;
    }
}

And I call this code with something similar:

table.getColumn("Date Entered").setCellRenderer(new DateCellRenderer("MMM dd, yyyy"));

Question 2:

Q: particular one table header color java swing

A: Umm.. Your SSCCE seems to have it figured out.

Question 3:

Q: about super.getTableCellRendererComponent(...) must be last code line before returns, I'm not able to write correct Renderer by those suggestion, for me works only this way

A: I'm not sure what you mean "must be last code line before returns." That is not the case, proven by the code snip I gave above

Question 4:

Q: JLabel is added for Borders, HorizontalAlignment and Foreground, especially Background caused me a few non_senses by using Component instead of JLabel, (not important here somehow)

A: Ok... the DefaultTableCellHeaderRenderer is sufficient for all of those, borders, alignment, foreground and background.




回答2:


I had this happen to me in the past and I was convinced it had to do with the Cell Renderer, but the ArraysXxxException kind of Exceptions hunted me because I had forgotten to unselect and stop editing the cell before adding/removing rows. You should try clearSelection() and table.getCellEditor().stopCellEditing(); on your JTable before remove/add and see if that solves your problem.

First, of course, make sure it is editing:

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


来源:https://stackoverflow.com/questions/9851253/how-to-use-renderer-for-tableheader

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!