Custom TableCellRenderer vs. prepareRenderer или как исправить проблему с подсветкой строк?

Короче говоря:

О чем это

У меня есть JTable с моделью, которая отображает данные, полученные из системы SAP. Моя цель - в определенном столбце отображать только часть данных, которые есть в модели. Например, в строке модели есть Object["a","b"] но пользователь должен видеть только a.

Итак, я прочитал много тем здесь, в StackOverflow, и множество руководств о том, как использовать пользовательские tablecellrenderers и редакторы и т. д., но я не могу решить свою проблему, заключающуюся в том, что ячейка, в которой я зарегистрировал средство визуализации, не будет выделена, когда выбрано. Возможное решение описано ЗДЕСЬ, но это не работает для меня.

Вот мой пользовательский рендерер:

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

}

В таблице я пробовал некоторые вещи с prepareRenderer, но здесь я не могу манипулировать данными (значениями) и всем остальным, что я делаю в пользовательском рендерере. Может быть, у меня есть основная проблема понимания того, как подойти к этому. Я благодарен за любые подсказки!


person m0rb    schedule 09.09.2016    source источник


Ответы (1)


Я только что нашел очень простое решение, которое, как я думал, перезапишет желаемое поведение, но это не так.

Просто внедрил это в таблицу:

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

работает как шарм!

person m0rb    schedule 14.09.2016
comment
будет добавлено: у меня все еще есть собственный рендерер, установленный для этой ячейки таблицы, и он ведет себя так, как ожидалось! - person m0rb; 14.09.2016