Как использовать Renderer для TableHeader - PullRequest
14 голосов
/ 24 марта 2012

Даже если я читаю и проверяю ответы @kleopatra

enter image description here

enter image description here

enter image description here

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

Ответы [ 2 ]

4 голосов
/ 11 августа 2013

По моему опыту, лучше получить DefaultTableCellHeaderRenderer при перезаписи любого JTable Renderer. Таким образом, вместо того, чтобы связываться с JLabel из Renderer напрямую, вы берете Renderer с super(). Итак, ваш код должен выглядеть так:

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?

A: Ваш текущий код устанавливает Renderer на 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:

Q: определенный цвет заголовка таблицы java swing

A: Ммм ... Кажется, ваш SSCCE понял это.

Вопрос 3:

Q: о super.getTableCellRendererComponent (...) должна быть последняя строка кода перед возвратом, я не могу написать правильный Renderer по этим советам, для меня работает только так

A: Я не уверен, что вы имеете в виду "должна быть последняя строка кода перед возвратом". Это не тот случай, что подтверждается приведенным выше фрагментом кода

Вопрос 4:

Q: JLabel добавлен для Borders, HorizontalAlignment и Foreground, особенно Background заставил меня несколько non_senses при использовании Component вместо JLabel, (здесь как-то не важно)

A: Хорошо ... DefaultTableCellHeaderRenderer достаточно для всех этих границ, выравнивания, переднего и заднего плана.

0 голосов
/ 31 мая 2013

В прошлом это случалось со мной, и я был убежден, что это связано с рендерером ячеек, но на меня охотились исключения типа "1001", потому что я забыл отменить выбор и прекратить редактирование ячейка перед добавлением / удалением строк.Вы должны попробовать clearSelection() и table.getCellEditor().stopCellEditing(); на вашем JTable перед удалением / добавлением и посмотреть, решит ли это вашу проблему.

Сначала, конечно, убедитесь, что он редактирует:

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