Swing JTable - изменить цвет фона строки в зависимости от предыдущей строки

У меня есть свинг JXTable, и требуется, чтобы цвет фона менялся, если поле отличается от предыдущей строки.

Вот пример:

  • Строка 0: var = 1 -> СИНИЙ фон

  • Строка 1: var = 1 -> СИНИЙ фон

  • Строка 2: var = 2 -> Фон КРАСНЫЙ

  • Ряд 3: var = 3 -> Фон СИНИЙ

Я пробовал несколько решений.

Переопределение prepareRenderer, но это решение не работает нормально. Линии мигают и меняют цвет в зависимости от первой строки, видимой в таблице.

    @Override
public Component prepareRenderer(TableCellRenderer renderer, int row, int column)
{
    Component c = super.prepareRenderer ( renderer , row , column );
    if(lastRow  != -1)
    {
        Data actualData = ( ( MessagesTableModel ) getModel ( ) ).getData ( row );
        Data previousData = ( ( MessagesTableModel ) getModel ( ) ).getData ( lastRow );
        if ( previousData != null )
        {
            if ( previousData.getNbr ( ) != actualData.getNbr ( ) )
            {
                if(lastColor.equals ( COLOR1 ))
                {
                    System.out.println ("A");
                    lastColor = COLOR2;
                }
                else
                {
                    System.out.println ("b");
                    lastColor = COLOR1;
                }
            }
        }
    }
    lastRow = row;
    c.setBackground ( lastColor );
    return c;
}

Я также думаю об определении пользовательского TableCellRender, но это не совпало.

Так что я застрял, я не знаю, как это сделать. У Вас есть какие-то предложения ?

ИЗМЕНИТЬ

Я пробовал с HighlightPredicate, так как использую JXTable.

        HighlightPredicate predicate = new HighlightPredicate ( )
    {
        public boolean isHighlighted(Component renderer, ComponentAdapter adapter)
        {
            Data actualData = ( ( MessagesTableModel ) getModel ( ) ).getData ( adapter.row );
            if ( adapter.row - 1 >= 0 )
            {
                Data previousData = ( ( MessagesTableModel ) getModel ( ) )
                        .getData ( adapter.row - 1 );
                if ( actualData.getNbr ( ) != previousData.getNbr ( ) )
                {   
                    return true;
                }

            }
            return false;
        }
    };

    addHighlighter ( new ColorHighlighter ( predicate , COLOR1 , null ) );

На этот раз цвет меняется при изменении значения, но если строка сразу после не меняется, цвет меняется.

  • Строка 0: var = 1 -> СИНИЙ фон

  • Строка 1: var = 1 -> СИНИЙ фон

  • Строка 2: var = 2 -> Фон КРАСНЫЙ

  • Ряд 3: var = 2 -> СИНИЙ фон

Это нормально, потому что именно так кодируется :) Но я перед такой же проблемой, как узнать, была ли выделена предыдущая строка или нет.

ИЗМЕНИТЬ 2

Я нашел решение, не очень чистое, но оно работает.

        HighlightPredicate predicate = new HighlightPredicate ( )
    {
        public boolean isHighlighted(Component renderer, ComponentAdapter adapter)
        {
            Data actualData = ( ( MessagesTableModel ) getModel ( ) ).getData ( adapter.row );
            if ( adapter.row - 1 >= 0 )
            {
                Data previousData = ( ( MessagesTableModel ) getModel ( ) )
                        .getData ( adapter.row - 1 );
                if ( actualData.getMsgNbr ( ) != previousData.getMsgNbr ( ) )
                {   
                    adapter.row--;
                    if(isHighlighted ( renderer , adapter ))
                    {
                        return false;
                    }
                    else
                    {
                        return true;
                    }                       
                }
                else
                {
                    adapter.row--;
                    if(isHighlighted ( renderer , adapter ))
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
            }
            return false;
        }
    };

    addHighlighter ( new ColorHighlighter ( predicate , COLOR1 , null ) );

Спасибо за вашу помощь !


person FlorianB    schedule 07.01.2013    source источник
comment
в SwingX вы не должны переопределять prepareRenderer (или реализовывать собственный рендерер) - вместо этого реализуйте/используйте Highlighter и соответствующий HighlightPredicate для визуального оформления. Судя по вашему описанию, это больше похоже на свойство данных, а не просто на визуальные эффекты? Если это так, пусть модель решает, отличается ли строка, и предоставляет свойство, которое можно использовать в HighlightPredicate.   -  person kleopatra    schedule 07.01.2013
comment
плюс: последовательность (индекса строки) вызова средства визуализации не определена - никогда не позволяйте ему иметь состояние, связанное с ранее настроенной строкой   -  person kleopatra    schedule 07.01.2013
comment
возможно   -  person mKorbel    schedule 07.01.2013
comment
@mKorbel - точно, ты опередил меня, найдя это :-)   -  person kleopatra    schedule 07.01.2013
comment
@kleopatra хмммм ...., оба этих ответа о превосходной логике, великих умах, а не о JTable, отличный урок для меня (ясная логика, а не о кодировании)   -  person mKorbel    schedule 07.01.2013
comment
вы читали другую ветку, на которую ссылается @mKorbel, не так ли? Если это не поможет, пришло время для SSCCE.   -  person kleopatra    schedule 07.01.2013
comment
арррггг... не меняйте адаптер, он строго только для чтения (правда, не похоже, ранняя авария апи ;-)!   -  person kleopatra    schedule 08.01.2013


Ответы (2)


Вам также нужно сделать рендерер непрозрачным:

if (c instanceof JComponent)
    ((JComponent)c).setOpaque(true);
person Guillaume Polet    schedule 07.01.2013
comment
У меня есть цвета, но не такие, как я хочу, я отредактировал свое сообщение, чтобы объяснить больше. - person FlorianB; 07.01.2013
comment
@FlorianB 2 вещи могут вызвать это: 1) вы делаете предположение, что все строки отображаются каждый раз 2) перед отрисовкой таблицы вы не сбрасываете значение lastColor. Эту последнюю проблему можно решить, переопределив paintComponent(), и перед вызовом super.paintComponent вы сбросите значение lastColor. - person Guillaume Polet; 07.01.2013
comment
повторяюсь: неправильно хранить что-то вроде lastColor/lastRow, где бы вы это ни делали. При рисовании просто нет понятия последовательности. - person kleopatra; 07.01.2013
comment
Я знаю, я понял это, попробовав это решение и прочитав документацию. Вот почему я ищу другой способ сделать это. - person FlorianB; 07.01.2013

int lastRow=Math.max(0, row-1);

Вместо сохранения индекса последней строки просто используйте фактическое значение row и вычтите 1.

person StanislavL    schedule 07.01.2013