Добавить поведение к средству визуализации ячеек JTable по умолчанию

Если я использую следующее для отображения JTable:

package jtable.fontsize;
import java.awt.BorderLayout;
import java.awt.Font;
import java.lang.reflect.InvocationTargetException;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;

import rcutil.swing.table.LastColumnChangesWidthJTable;


public class JTableCellPlay extends JFrame
{
  public JTableCellPlay()
  {
    super("setting Table font size");
    setDefaultCloseOperation(EXIT_ON_CLOSE);
  }

  public static void main(String ... arguments) throws InvocationTargetException, InterruptedException
  {
    JTableCellPlay mainScreen = new JTableCellPlay();
    mainScreen.go();
  }

  public void go() throws InvocationTargetException, InterruptedException
  {
    SwingUtilities.invokeAndWait(new Runnable() { public void run() { createScreen(); } } );
    setVisible(true);
  }

  public void createScreen()
  {
    LastColumnChangesWidthJTable aLittleJTable = new LastColumnChangesWidthJTable(new LittleTableModel());
    aLittleJTable.setDefaultRenderer(Integer.class, new IntegerCellRenderer());
    JScrollPane scrollPane = new JScrollPane(aLittleJTable);
    add(scrollPane, BorderLayout.CENTER);
    pack();
  }
}

со следующим рендерером:

package jtable.fontsize;

import java.awt.Color;
import java.awt.Component;

import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;


public class IntegerCellRenderer extends JLabel implements TableCellRenderer
{
  @Override
  public Component getTableCellRendererComponent
                      (JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
  {
    String resultString = String.format("~%d~", (Integer)value);
    setText(resultString);
    setHorizontalAlignment(JLabel.CENTER);
//    if (isSelected) 
//    { 
//      setOpaque(true);  // evidently necessary for JLabel as a component in a JTable cell
//      setBackground(Color.GRAY);
//    }
    return this;
  }
}

и следующая модель (чтобы ваш код работал, да, я знаю, что есть и другие способы сделать эту часть):

package jtable.fontsize;

import javax.swing.table.AbstractTableModel;

public class LittleTableModel extends AbstractTableModel
{
  public Class<? extends Object> getColumnClass(int column)
  {
    Class<? extends Object> c = null;
    switch (column)
    {
    case 0: c = String.class; break;
    case 1: c = Integer.class; break;
    case 2: c = String.class; break;
    }
    return c;
  }

  String[] columnNames = { "first", "second", "third" };
  Object[][] data = { { "one", 2, "three" }, { "four", 5, "six" } };

  public int getColumnCount() { return 3; }
  public int getRowCount() { return 2; }
  public String getColumnName(int index) { return columnNames[index]; }

  public Object getValueAt(int row, int column)
  {
    Object result = data[row][column];
    return result;
  }
}

Затем, когда я выбираю одну из строк, два столбца String выделяются выделением, а столбец «Целое число» - нет.

Если я закомментирую строку, которая устанавливает средство визуализации «Целое число», то при нажатии на строку будет выбрана вся строка, как и ожидалось.

Я знаю, что могу использовать закомментированные строки в рендерере, чтобы выделить ячейку, добавить setOpaque(true) и setBackground(Color) и даже играть в игры, чтобы получить правильные цвета фона, выбранные и невыбранные, но я подозреваю, что есть какой-то способ использовать тот же рендерер который изначально использовался для подобных вещей, и просто использую код в моем рендерере, чтобы делать специальные вещи, которые мне нужно делать. Может кто-нибудь объяснить, как это работает?


person arcy    schedule 24.09.2017    source источник
comment
В разделе Выделять ячейку при выборе строки предлагается несколько подходов.   -  person trashgod    schedule 24.09.2017


Ответы (1)


Почему бы просто не дать вашему рендереру блок else, где вы отмените изменения, сделанные в блоке if?

if (isSelected) {
    setOpaque(true); 
    setBackground(Color.GRAY);
} else {
    setOpaque(false); // allow underlying color to show
    setBackground(null); // no color added
}

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

@SuppressWarnings("serial")
class IntegerCellRenderer2 extends DefaultTableCellRenderer {
    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
            int row, int column) {
        String resultString = String.format("~%d~", (Integer) value);
        setText(resultString);
        setHorizontalAlignment(JLabel.CENTER);
        return super.getTableCellRendererComponent(table, resultString, isSelected, hasFocus, row, column);
    }
}

Обратите внимание, что вы можете установить некоторые свойства средства визуализации в его конструкторе. Например:

@SuppressWarnings("serial")
class IntegerCellRenderer2 extends DefaultTableCellRenderer {
    public IntegerCellRenderer2() {
        setHorizontalAlignment(JLabel.CENTER);
    }

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
            int row, int column) {
        String resultString = String.format("~%d~", (Integer) value);
        setText(resultString);
        // setHorizontalAlignment(JLabel.CENTER);
        return super.getTableCellRendererComponent(table, resultString, isSelected, hasFocus, row, column);
    }
}
person DontKnowMuchBut Getting Better    schedule 24.09.2017
comment
Что ж, я априори не знаю, что такое непрозрачная настройка и фон, не больше, чем я знаю, что цвет выделения серый. И, как я уже сказал, я знаю, что могу звонить, чтобы узнать, что это такое, но я хотел узнать способ получше. Ваш второй метод, кажется, работает, хотя мне он кажется изворотливым - что, если средство визуализации по умолчанию устанавливает выравнивание? Мне не нравится, когда в моем классе есть код, зависящий от внутренностей его суперкласса. - person arcy; 24.09.2017
comment
@arcy: что точно ты пытаешься сделать? - person DontKnowMuchBut Getting Better; 24.09.2017
comment
@арси; Если вы используете средство визуализации по умолчанию, вы можете достаточно легко запросить компонент super относительно его фонового состояния и состояния его непрозрачного свойства, но опять же, что в конечном итоге вы пытаетесь с этим сделать? - person DontKnowMuchBut Getting Better; 24.09.2017
comment
Я пытаюсь использовать поведение по умолчанию средства визуализации по умолчанию вместо того, чтобы пытаться его дублировать. - person arcy; 24.09.2017
comment
@arcy: мой второй вызов - это SOP (стандартная рабочая процедура) для расширения средства визуализации ячеек. И вы устанавливаете выравнивание в рендерере, так что нет проблем. Ничего хитрого. - person DontKnowMuchBut Getting Better; 24.09.2017
comment
Если бы рендерер по умолчанию устанавливал выравнивание, то мои настройки не работали бы. Таким образом, код, который устанавливает выравнивание, зависит от того факта, что рендерер по умолчанию этого не делает. Мы знаем, что это работает, но были ли основания полагать, что это сработает? Указывает ли контракт средства визуализации по умолчанию, что он не устанавливает и никогда не будет устанавливать выравнивание? Это изворотливая часть. - person arcy; 24.09.2017
comment
@arcy: вы также можете установить свойства суперобъекта в конструкторе вашего переопределения, как указано выше. - person DontKnowMuchBut Getting Better; 24.09.2017
comment
Давайте продолжим обсуждение в чате. - person arcy; 24.09.2017
comment
@arcy, если вы просто создаете собственный модуль визуализации для форматирования данных, тогда проще переопределить метод setValue(...) модуля визуализации по умолчанию, как показано в учебном пособии Swing на Использование пользовательских средств визуализации. И если вы хотите быть более изобретательным, вы можете создать многоразовый рендерер, который принимает Formatter в качестве параметра, как показано в Визуализаторы табличного формата - person camickr; 24.09.2017