自定义 TableCellRenderer 与 prepareRenderer 或如何解决行突出显示问题?

Custom TableCellRenderer vs. prepareRenderer or how to fix row highlighting issue?

简而言之:

这是关于什么的

我有一个带有模型的 JTable,它显示从 SAP 系统获取的数据。 我的目标是在特定列中仅显示模型中的部分数据。例如模型的行有 Object["a","b"] 但用户只应该看到 a

所以我在 Whosebug 上阅读了很多主题以及很多关于如何使用自定义 tablecellrenderer 和编辑器等的教程,但我无法解决我的问题,即单元格我注册渲染器的地方在选择时不会突出显示。 描述了一个可能的解决方案 HERE 但这对我不起作用。

这是我的自定义渲染器:

public class SapChangeNumberCellRenderer extends DefaultTableCellRenderer{

private static final long serialVersionUID = -2649719064483586819L;

private SapChangeNumberTable table;
private int valuesSize;

public final static String ASM_AMOUNT = LanguageServer.getString("71", "Baugruppen");

public SapChangeNumberCellRenderer(SapChangeNumberTable table) {
    super();
    this.table = table;
}


@Override
public Component getTableCellRendererComponent(final JTable table, final Object value, final boolean isSelected,
        final boolean hasFocus,
        final int row, final int column) {

    // components & Layout
    JPanel panel = new JPanel(new BorderLayout());
    JButton buttonDots = new JButton("...");
    JLabel text = new JLabel();

    List<String> values = (List<String>) value;
    valuesSize = values.size();
    if (valuesSize > 0) {
        // set values
        buttonDots.setPreferredSize(new Dimension(14, 14));
        text.setText(values.get(0));
    } else {
        text.setText("");
    }

    if (valuesSize > 1) {
        // button to open dialog only if we have more than 1 item
        panel.add(buttonDots, BorderLayout.EAST);
    }

    panel.add(text, BorderLayout.WEST);
    panel.setOpaque(true);
    return panel;
}

@Override
public String getToolTipText(MouseEvent e) {
    String toolTip = String.valueOf(valuesSize) + Initializer.SPACE + ASM_AMOUNT;

    return toolTip;
}

public SapChangeNumberTable getTable() {
    return table;
}
}

正如您所看到的,根据值的列表大小,我操纵将从该方法返回的组件。 setOpaque(true) 方法并没有达到我的目标。

这是相应的 JTabel(注意:BaseTable 只是 JTable 的包装器,带有一些我需要的好东西……这里没什么特别的)

public class SapChangeNumberTable extends BaseTable {

/** the model */
private SapChangeNumberTableModel model = new SapChangeNumberTableModel();

/** parent frame */
private SapPanel parent = null;

public SapChangeNumberTable(SapPanel parent) {
    this.parent = parent;
    this.init();
}

/**
 * init the table
 */
private void init() {

    // set model (not filled yet)
    this.setModel(model);

    // set renderer
    setRendererAndEditor();

    // add search filter row, enabling sorting is included
    this.addFilterSearchRowPanel();
    // single selection
    this.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
    // hide
    this.hideColumns();
    this.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
}

/**
 * sets the default table cell renderer
 */
private void setRendererAndEditor() {
    getColumnModel().getColumn(convertColumnIndexToView(SapChangeNumberTableModel.COL_ID_SPM_ASM_NUMBER))
            .setCellRenderer(new SapChangeNumberCellRenderer(this));
    getColumnModel().getColumn(convertColumnIndexToView(SapChangeNumberTableModel.COL_ID_SPM_ASM_NUMBER))
            .setCellEditor(new SapChangeNumberAsmRefTableCellEditor(this));
}

@Override
public void setStatusBarDataCount(boolean value) {
}

@Override
public void hideColumns() {
}

@Override
public int getColModelSortIndex() {
    return 0;
}

@Override
public void load() {
}

@Override
public SapChangeNumberTableModel getModel() {
    return model;
}

public boolean isChanging() {
    return model.isFilling();
}

public SapFactoryChange getRow(int row) {
    return model.getSapFactoryChange(row);
}

@Override
public void clear() {
    model.clear();
}

@Override
public Component prepareRenderer(TableCellRenderer renderer, int rowIndex, int vColIndex) {
    Component comp = super.prepareRenderer(renderer, rowIndex, vColIndex);

    if (vColIndex == SapChangeNumberTableModel.COL_ID_SPM_ASM_NUMBER) {
         //what the hack to do here to manipulate the comp ? I can't add a JPanel to a plain Component
    }

    return comp;
}

}

在 table 中,我用 prepareRenderer 尝试了一些东西,但在这里我无法操作数据(值)和我在自定义渲染器中做的所有其他事情。也许我对如何处理这个问题有一个基本的理解问题。感谢您提供任何提示!

我刚刚找到了一个非常简单的解决方案,我认为它会覆盖我想要的行为,但事实并非如此。

刚刚将其实施到 Table:

@Override
public Component prepareRenderer(TableCellRenderer renderer, int rowIndex, int vColIndex) {
    Component comp = super.prepareRenderer(renderer, rowIndex, vColIndex);

    if (isRowSelected(rowIndex)) {
        comp.setBackground(Color.ORANGE);
    }

    return comp;
}

工作起来很有魅力!