#java #colors #jtable #row #customization
#java #Цвет #jtable #строка #настройка
Вопрос:
Я пытаюсь изменить цвет строк в Java JTable, но у меня возникают некоторые проблемы. Это сценарий: у меня есть таблица с некоторыми данными для обработки, и я хотел бы, чтобы в конце обработки (запускаемой с помощью кнопки) таблица обновлялась путем окрашивания строк в зеленый, желтый или красный цвета в зависимости от результата операций. У каждого обрабатываемого объекта есть переменная «результат», которая устанавливается после обработки. Таблица создается графическим редактором Netbeans (поэтому невозможно изменить автоматически сгенерированный код). Я использовал эту табличную модель:
public class QuotationsTableModel extends AbstractTableModel {
private List<Quotation> quotationsList;
public QuotationsTableModel(List<Quotation> quotationsList) {
this.quotationsList= quotationsList;
}
@Override
public int getRowCount() {
if (quotationsList== null) {
return 0;
}
return this.quotationsList.size();
}
@Override
public int getColumnCount() {
return 4;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
if (quotationsList== null) {
return null;
}
Quotation quotation = quotationsList.get(rowIndex);
if (columnIndex == 0) {
return quotation.getQuotationNumber();
}
if (columnIndex == 1) {
return quotation.getBillingType();
}
if (columnIndex == 2) {
return quotation.getAdvance();
}
if (columnIndex == 3) {
return quotation.getOutcome();
}
return null;
}
@Override
public String getColumnName(int column) {
if (column == 0) {
return "Number";
} else if (column == 1) {
return "Billing type";
} else if (column == 2) {
return "Advance";
} else if (column == 3) {
return "Outcome";
}
return null;
}
public void updateTable() {
this.fireTableDataChanged();
}
и я попытался достичь цели, создав класс:
public class CustomTableRenderer extends DefaultTableCellRenderer {
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Component original = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
Color background = table.getBackground();
//Color grid = Color.YELLOW;
Color fg = null;
Color bg = null;
if (isSelected) {
super.setForeground(fg == null ? table.getSelectionForeground()
: fg);
super.setBackground(bg == null ? table.getSelectionBackground()
: bg);
} else {
if (column == 3) {
String outcome = String.valueOf(value);
if (outcome .equalsIgnoreCase("COMPLETED")){
background = Color.GREEN;
} else if (outcome .equalsIgnoreCase("PARTIAL")) {
background = Color.YELLOW;
} else if (outcome .equalsIgnoreCase("ERROR")) {
background = Color.RED;
}
}
}
original.setBackground(background);
return original;
}
а затем вызовите:
QuotationsTableModel quotationsTableModel= new QuotationsTableModel(quotationsList);
this.quotationsTable.setModel(quotationsTableModel);
this.quotationsTable.setDefaultRenderer(Object.class, new CustomTableRenderer());
но результат окрашивается только при выборе строки, и, более того, как только строка выбрана, все значения исчезают, за исключением результата. Не могли бы вы мне помочь, пожалуйста?
Я нашел рабочее решение, возможно, оно может быть полезно тем, кто придет:
import java.awt.Color;
import java.awt.Component;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
public class CustomTableCellRenderer extends DefaultTableCellRenderer {
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Component original = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
Color background = table.getBackground();
if (isSelected) {
original.setBackground(javax.swing.UIManager.getDefaults().getColor("TextField.selectionBackground"));
original.setForeground(javax.swing.UIManager.getDefaults().getColor("TextField.selectionForeground"));
table.setRowSelectionInterval(row, row);
} else {
original.setBackground(javax.swing.UIManager.getDefaults().getColor("TextField.highlight"));
original.setForeground(Color.BLACK);
if (column == 3) {
String outcome = String.valueOf(value);
if (outcome.equalsIgnoreCase("COMPLETED")){
background = Color.GREEN;
} else if (outcome.equalsIgnoreCase("PARTIAL")) {
background = Color.YELLOW;
} else if (outcome.equalsIgnoreCase("ERROR")) {
background = Color.RED;
}
original.setBackground(background);
}
}
return original;
}
}
Спасибо.
Комментарии:
1. Не могли бы вы, пожалуйста, объяснить рабочее решение? Я вижу только, что вы закомментировали тело
CustomTableCellRenderer
. Как с этим может работать раскраска?2. Извините, комментарий был ошибкой
Ответ №1:
Я создал приведенный ниже пример программы, используя ваши классы QuotationsTableModel
и CustomTableRenderer
. Единственная проблема, которую я увидел, заключается в CustomTableRenderer.getTableCellRendererComponent()
методе.
Вы меняли цвет столбца «Результат» только тогда, когда строка не выбрана. Из-за этого раскраска не сработала при выборе строки. Чтобы устранить эту проблему, я удалил if (isSelected) {
часть кода. Запустите приведенный ниже пример и посмотрите.
(Когда вы будете публиковать вопросы в будущем, публикуйте минимальную исполняемую программу, подобную приведенному ниже примеру программы. Тогда другим будет проще запустить сценарий и увидеть проблему.)
import javax.swing.*;
import javax.swing.table.*;
import java.awt.Color;
import java.awt.Component;
import java.util.ArrayList;
import java.util.List;
public class ColorTable {
public static void main(String[] args) {
List<Quotation> quotationsList = new ArrayList<>();
quotationsList.add(new Quotation(111, "AA", 2500, "COMPLETED"));
quotationsList.add(new Quotation(222, "BB", 4000, "PARTIAL"));
quotationsList.add(new Quotation(333, "CC", 5000, "COMPLETED"));
quotationsList.add(new Quotation(444, "DD", 1500, "SOME_OTHER_OUTCOME"));
quotationsList.add(new Quotation(555, "EE", 3500, "ERROR"));
QuotationsTableModel quotationsTableModel= new QuotationsTableModel(quotationsList);
JTable quotationsTable = new JTable();
quotationsTable.setModel(quotationsTableModel);
quotationsTable.setDefaultRenderer(Object.class, new CustomTableRenderer());
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new JScrollPane(quotationsTable));
frame.pack();
frame.setVisible(true);
}
}
class QuotationsTableModel extends AbstractTableModel {
private List<Quotation> quotationsList;
public QuotationsTableModel(List<Quotation> quotationsList) {
this.quotationsList= quotationsList;
}
@Override
public int getRowCount() {
if (quotationsList== null) {
return 0;
}
return this.quotationsList.size();
}
@Override
public int getColumnCount() {
return 4;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
if (quotationsList== null) {
return null;
}
Quotation quotation = quotationsList.get(rowIndex);
if (columnIndex == 0) {
return quotation.getQuotationNumber();
}
if (columnIndex == 1) {
return quotation.getBillingType();
}
if (columnIndex == 2) {
return quotation.getAdvance();
}
if (columnIndex == 3) {
return quotation.getOutcome();
}
return null;
}
@Override
public String getColumnName(int column) {
if (column == 0) {
return "Number";
} else if (column == 1) {
return "Billing type";
} else if (column == 2) {
return "Advance";
} else if (column == 3) {
return "Outcome";
}
return null;
}
public void updateTable() {
this.fireTableDataChanged();
}
}
class CustomTableRenderer extends DefaultTableCellRenderer {
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Component original = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
Color background = table.getBackground();
//Color grid = Color.YELLOW;
if (column == 3) {
String outcome = String.valueOf(value);
if (outcome .equalsIgnoreCase("COMPLETED")){
background = Color.GREEN;
} else if (outcome .equalsIgnoreCase("PARTIAL")) {
background = Color.YELLOW;
} else if (outcome .equalsIgnoreCase("ERROR")) {
background = Color.RED;
}
}
original.setBackground(background);
return original;
}
}
class Quotation {
private int quotationNumber;
private String billingType;
private int advance;
private String outcome;
Quotation(int quotationNumber, String billingType, int advance, String outcome) {
this.quotationNumber = quotationNumber;
this.billingType = billingType;
this.advance = advance;
this.outcome = outcome;
}
int getQuotationNumber() {
return quotationNumber;
}
String getBillingType() {
return billingType;
}
int getAdvance() {
return advance;
}
String getOutcome() {
return outcome;
}
}
Вывод:
Комментарии:
1. Большое вам спасибо за ответ. По какой-то причине это решение у меня не работает, я уже пробовал его. Я отредактировал первый пост, добавив свое решение, возможно, это может быть полезно для тех, кто придет. Спасибо.