Как правильно использовать пользовательские средства визуализации для рисования определенных ячеек в JTable? - PullRequest
5 голосов
/ 07 марта 2012

У меня есть компонент JTable в моем графическом интерфейсе, который отображает psuedocode алгоритма. Я хочу выделить текущую строку выполнения, изменив фон определенной ячейки, а затем изменив ячейку под ней и т. Д.

Прямо сейчас мой код меняет фоны для всех ячеек в моей JTable, как показано ниже:

JTable

Код, который я использую для архивирования текущего состояния, выглядит следующим образом:

class CustomRenderer extends DefaultTableCellRenderer 
{
    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
    {
            JLabel d = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            if((row == 0) && (column == 0))
                d.setBackground(new java.awt.Color(255, 72, 72));
            return d;
        }
    }

Затем я вызываю jTable2.setDefaultRenderer(String.class, new CustomRenderer()); в моем конструкторе.

Я предполагаю, что:

  • Этот метод вызывается в каждой ячейке таблицы типа String.
  • что это только изменит цвет ячейки в позиции (0,0)

Как мне исправить мой код, чтобы только ячейка (0,0) была окрашена?

Ответы [ 3 ]

12 голосов
/ 08 марта 2012

Это не ответ (*), он слишком длинный для комментария к обоим ответам: оба верны в том смысле, что блок else важен для обеспечения того, чтобы цвет по умолчанию использовался для ячейки, которая не должна быть подсвечен. Они немного ошибаются в том, как этого достичь, и оба имеют одинаковый общий эффект: они пропускают любую особую окраску, например, f.i. из-за выделения, фокусировки, редактируемые, dnd ...

Они достигают этого "промаха" разными способами с немного разными эффектами

setBackground(Color.WHITE);

установить фиксированный цвет, который может быть или не быть стандартным фоном таблицы по умолчанию

setBackground(null);

Устанавливает отсутствие цвета, что приводит к отображению "нормального" цвета фона - из-за внутренней хитрости реализации isOpaque DefaultTableCellRenderer: -)

Основной причиной проблемы (также известной как печально известная цветная память TM) является необычно плохая реализация рендерера по умолчанию, из-за которого он практически не расширяется:

 /**
 * Overrides <code>JComponent.setBackground</code> to assign
 * the unselected-background color to the specified color. 
 *
 * JW: The side-effect is documented and looks innocent enough :-) 
 */
public void setBackground(Color c) {
    super.setBackground(c); 
    unselectedBackground = c; 
}

// using that side-effect when configuring the colors in getTableCellRendererComp
// is what leads to the horrendeous problems
// in the following lines of the else (not selected, that is normal background color)
 Color background = unselectedBackground != null
           ? unselectedBackground : table.getBackground();
 super.setBackground(background);

Видя это, выход (кроме использования SwingX и его гибкого, чистого, мощного, непротиворечивого .. :-) Поддержка рендерера - @ Hovercraft, но обратная: сначала сделайте пользовательскую раскраску (или ноль, если никто не намеревался), затем вызовите супер:

  @Override
  public Component getTableCellRendererComponent(JTable table,
        Object value, boolean isSelected, boolean hasFocus, int row,
        int column) {
      if (myHighlightCondition) {
          setBackground(Color.RED);
      } else {
          setBackground(null);
      }
     super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
           row, column);
     return this;
  }

(*) В конце концов, этот комментарий привел к ответу, забыл, что это можно исправить на уровне пользовательского рендерера: -)

Кстати: перехват «первого» вызова для средства визуализации очень хрупок, нет гарантии, по какой ячейке это произойдет, вполне может быть последний ряд последнего столбца.

6 голосов
/ 07 марта 2012

Вы забыли другую часть блока if, код, который закрашивает фон по умолчанию, если он не важная строка:

        if (row == 0 && column == 0) {
           d.setBackground(new java.awt.Color(255, 72, 72));
        } else {
           d.setBackground(null);
        }

Мой SSCCE

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;

public class TestJTable {
   private static int highlightedRow = 0;
   private static void createAndShowGui() {
      String[] columnNames = {"Program"};
      Object[][] rowData = {{"Row 1"}, {"Row 2"}, {"Row 3"}, {"Row 4"}, 
            {"Row 1"}, {"Row 2"}, {"Row 3"}, {"Row 4"}, 
            {"Row 1"}, {"Row 2"}, {"Row 3"}, {"Row 4"}};
      final JTable myTable = new JTable(rowData , columnNames );
      myTable.setDefaultRenderer(Object.class, new DefaultTableCellRenderer()
      {
         @Override
         public Component getTableCellRendererComponent(JTable table,
               Object value, boolean isSelected, boolean hasFocus, int row,
               int column) {
            Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
                  row, column);
            if (row == highlightedRow && column == 0) {
               c.setBackground(new java.awt.Color(255, 72, 72));
            } else {
               c.setBackground(null);
            }
            return c;
         }
      });


      JFrame frame = new JFrame("TestJTable");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(new JScrollPane(myTable));
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);

      new Timer(1000, new ActionListener() {

         @Override
         public void actionPerformed(ActionEvent arg0) {
            highlightedRow++;
            int rowCount = myTable.getRowCount();
            highlightedRow %= rowCount;
            myTable.repaint();
         }
      }).start();
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}
4 голосов
/ 07 марта 2012

Добавьте предложение else к вашему if:

if ((row == 0) && (column == 0)) {
    d.setBackground(new java.awt.Color(255, 72, 72));
}
else {
    d.setBackground(Color.WHITE);
}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...