【问题标题】:Can we use prepareRenderer component and custom cell Renderer together?可以同时使用 prepareRenderer 组件和自定义单元格渲染器吗?
【发布时间】:2016-08-07 05:15:57
【问题描述】:

我正在尝试将 prepareRenderer 组件与自定义单元格渲染器一起使用。这个想法是使用 prepareRenderer 绘制整行,并使用客户单元格渲染器进行基于单元格值的自定义。

prepareRenderer 通过突出显示整行按预期工作,但自定义单元格渲染器突出显示的单元格不显示颜色,除非选中。自定义单元格渲染似乎仅适用于单元格选择(突出显示包含 1 但仅在选择时的单元格)。

关于如何使两者齐头并进的任何想法?

下面的代码重现问题。

[![import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;
import java.awt.*;

public class SortTableWithColors_ extends JFrame {
    public static void main(String\[\] args) {
        SortTableWithColors_ frame = new SortTableWithColors_();
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }

    public SortTableWithColors_() {
        Object\[\] columnNames = {"B", "C"};
        Object\[\]\[\] data = {{new Integer(1), new Integer(4)},
                {new Integer(2), new Integer(5)},
                {new Integer(3), new Integer(3)},
                {new Integer(4), new Integer(1)}};
        // table model
        DefaultTableModel model = new DefaultTableModel(data, columnNames);

        // set table model in Jtable
//        JTable table = new JTable(model);
        NewJTable table = new NewJTable(model);
        table.setAutoCreateRowSorter(true);
        getContentPane().add(new JScrollPane(table));

        // Tell the table what to use to render our columns
        for (int i = 0; i < 2; i++) {
            table.getColumnModel().getColumn(i).setCellRenderer(new NewRenderer());
        }
    }

    // Custom Renderer
    public class NewRenderer extends DefaultTableCellRenderer {
        @Override
        public Component getTableCellRendererComponent
                (JTable table, Object value, boolean isSelected,
                 boolean hasFocus, int row, int column) {
            JLabel cell = (JLabel) super.getTableCellRendererComponent
                    (table, value, isSelected, hasFocus, row, column);

            int rowModel = (int) table.convertRowIndexToModel(row);
            int colModel = (int) table.convertColumnIndexToModel(column);
            int rowView = (int) table.convertRowIndexToView(row);
            int colView = (int) table.convertColumnIndexToView(column);

            // set color
//            cell.setBackground(new Color(0xFFFFFF));
//            cell.setForeground(new Color(0x000000));

            //set selection colors
            if (isSelected) {
                cell.setBackground(new Color(0x4AC3FF));
                cell.setForeground(new Color(0x000000)); // AM
            }
            // Selective cell colouring based on value

            // paint cells
            int val = (int) value;
            if (val == 1) {
                cell.setBackground(Color.GREEN);
            }
            return cell;
        }
    }

    public class NewJTable extends JTable {
        public NewJTable(TableModel model) {
            super(model);
        }

        public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
            Component c = super.prepareRenderer(renderer, row, column);
            //  Color row based on a cell value
            if (!isRowSelected(row)) {
                c.setBackground(getBackground());
                int modelRow = convertRowIndexToModel(row);
                int val = (int) getModel().getValueAt(modelRow, 0);
                if (val == 3) {
                    c.setBackground(Color.YELLOW);
                }
            }
            return c;

        }
    }
}]

【问题讨论】:

  • 理论上是的,但是您可能会发现您必须不断地进行修改,因为 prepareRenderer 会根据其拥有的数据更改 TableCellRenderer 想要的内容
  • 对于这个主题的小小吐槽,你可以看看this,它不是一个“完美”的解决方案,但它是朝着更好的方向迈出的一步,有一些很好的副作用;)
  • 这很有帮助,值得深思。我喜欢使用 Jviewport 进行渲染的想法。

标签: java swing awt


【解决方案1】:

不要试图同时做两件事。您需要在逻辑上将渲染分解为两个步骤。

渲染器代码在准备渲染器代码之前执行。所以:

  1. 首先您需要让渲染器按照您希望的方式工作。

  2. 然后,通过突出显示包含值 3 的行来覆盖默认渲染。

在渲染器中更改背景的关键在于,在进行任何自定义之前,您必须始终将其重置为默认值。

所以在渲染代码中你需要注释掉的行:

// set color (ie. restore the default values)
cell.setBackground(new Color(0xFFFFFF));
cell.setForeground(new Color(0x000000));

然后在prepareRenderer中你不需要重置背景,只有在满足你的条件时才改变它:

// get rid of this, the default has already been set. 
// this code should only provide the override
//c.setBackground(getBackground());

注意:仅当您在所有将背景重置为默认值的列上都有自定义渲染器时,这才有效。因为我们需要注释掉上面的语句,所以现在重置背景是每个渲染器的责任。

【讨论】:

  • @amit,这没有回答你的问题吗?
  • @camickr。是的,它确实。抱歉延迟回复。我按照 MadProgrammer 的建议实现了 Jviewport 路由。但请同意您的乐于助人的 cmets。
猜你喜欢
  • 2012-08-05
  • 2020-06-11
  • 1970-01-01
  • 2012-10-14
  • 2011-10-02
  • 2020-09-27
  • 1970-01-01
  • 2015-01-01
  • 2020-02-01
相关资源
最近更新 更多