【发布时间】:2020-02-24 22:32:27
【问题描述】:
我的 Java 8 应用在 JScrollPane 中使用了 JTable。目前该表有超过 10 列,数据是使用DefaultTableModel 的addRow(someObjectArray) 添加的。列中的所有单元格当前具有相同类型的数据,但列 4+ 可以包含具有“null”的单元格(0-3 始终包含数据!= null!)。
如果前三列的数据与上一行的数据不同,则当前行的前三个单元格用黑色粗体字书写,否则使用普通、纯色和深色灰色字体 - 它只是一种标记新数据开始的方法:
填充表格并垂直滚动正确设置粗体字体和纯字体但向右滚动然后返回前三列,粗体字体被搞砸了:有时为每个单元格设置,有时为错误的单元格设置,有时它改变了中间文本:
再次向下和向上滚动会将单元格重置为应有的样子。
这就是表格的设置方式:
JTable myTable = new JTable() {
@Override
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
Component c = super.prepareRenderer(renderer, row, column);
if (column<3) {
if(row==0) { //Always mark column 0-2 in row 0
c.setFont(c.getFont().deriveFont(Font.BOLD));
c.setForeground(Color.BLACK);
} else {
if(column==0) { //Check if column 0-2 should be marked and mark column 0 (or not)
Object prevColumnA = getValueAt(row-1, column); //String
Object currColumnA = getValueAt(row, column); //String
Object prevColumnB = getValueAt(row-1, column+1); //int
Object currColumnB = getValueAt(row, column+1); //int
Object prevColumnC = getValueAt(row-1, column+2); //String
Object currColumnC = getValueAt(row, column+2); //String
if(!prevColumnA.equals(currColumnA) || !prevColumnB.equals(currColumnB) || !prevColumnC.equals(currColumnC)) {
markRow = true;
c.setFont(c.getFont().deriveFont(Font.BOLD));
c.setForeground(Color.BLACK);
} else {
markRow = false;
c.setFont(c.getFont().deriveFont(Font.PLAIN));
c.setForeground(Color.DARK_GRAY);
}
} else { //Mark column 1-2 (or not)
if(markRow) {
c.setFont(c.getFont().deriveFont(Font.BOLD));
c.setForeground(Color.BLACK);
} else {
c.setFont(c.getFont().deriveFont(Font.PLAIN));
c.setForeground(Color.DARK_GRAY);
}
}
}
} else {
c.setFont(c.getFont().deriveFont(Font.PLAIN));
c.setForeground(Color.DARK_GRAY);
}
//System.out.println("row="+row+", column="+column+", markRow="+markRow);
return c;
}
};
我该如何解决这个问题?
编辑:从here复制MRE:
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
public class SomeMRE extends JPanel {
boolean markRow = false;
public SomeMRE() {
JTable myTable = new JTable() {
@Override
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
Component c = super.prepareRenderer(renderer, row, column);
if (column<3) {
if(row==0) { //Always mark column 0-2 in row 0
c.setFont(c.getFont().deriveFont(Font.BOLD));
c.setForeground(Color.BLACK);
} else {
if(column==0) { //Check if column 0-2 should be marked and mark column 0 (or not)
Object prevColumnA = getValueAt(row-1, column); //String
Object currColumnA = getValueAt(row, column); //String
Object prevColumnB = getValueAt(row-1, column+1); //int
Object currColumnB = getValueAt(row, column+1); //int
Object prevColumnC = getValueAt(row-1, column+2); //String
Object currColumnC = getValueAt(row, column+2); //String
if(!prevColumnA.equals(currColumnA) || !prevColumnB.equals(currColumnB) || !prevColumnC.equals(currColumnC)) {
markRow = true;
c.setFont(c.getFont().deriveFont(Font.BOLD));
c.setForeground(Color.BLACK);
} else {
markRow = false;
c.setFont(c.getFont().deriveFont(Font.PLAIN));
c.setForeground(Color.DARK_GRAY);
}
} else { //Mark column 1-2 (or not)
if(markRow) {
c.setFont(c.getFont().deriveFont(Font.BOLD));
c.setForeground(Color.BLACK);
} else {
c.setFont(c.getFont().deriveFont(Font.PLAIN));
c.setForeground(Color.DARK_GRAY);
}
}
}
} else {
c.setFont(c.getFont().deriveFont(Font.PLAIN));
c.setForeground(Color.DARK_GRAY);
}
//System.out.println("row="+row+", column="+column+", markRow="+markRow);
return c;
}
};
myTable.setModel(new DefaultTableModel(
new Object[][] {
{"ColumnA text 1", 123, "ColumnC text 1", 1, null, "bla", "bla", "bla", null},
{"ColumnA text 2", 234, "ColumnC text 2", 2, null, "bla", "bla", null, null},
{"ColumnA text 2", 234, "ColumnC text 2", 3, null, "bla", "bla", "bla", null},
{"ColumnA text 2", 234, "ColumnC text 2", 4, null, "bla", "bla", null, null},
{"ColumnA text 2", 234, "ColumnC text 2", 5, null, "bla", null, null, null},
{"ColumnA text 1", 123, "ColumnC text 1", 6, null, "bla", "bla", "bla", null},
{"ColumnA text 2", 234, "ColumnC text 2", 7, null, "bla", null, null, null},
{"ColumnA text 2", 234, "ColumnC text 2", 8, null, "bla", "bla", null, null},
{"ColumnA text 2", 234, "ColumnC text 2", 9, null, "bla", "bla", null, null}
},
new String[] {
"ColumnA", "ColumnB", "ColumnC", "ColumnD", "ColumnE", "ColumnF", "ColumnG", "ColumnH", "ColumnI"
}
));
setLayout( new BorderLayout() );
add(new JScrollPane(myTable));
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("SomeMRE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new SomeMRE());
frame.pack();
frame.setVisible( true );
}
public static void main(String[] args) throws Exception {
java.awt.EventQueue.invokeLater( () -> createAndShowGUI() );
}
}
【问题讨论】:
-
(1-) 过去您曾被要求在每个问题上发布minimal reproducible example。你没有,所以我们无能为力。我猜问题出在你的 markRow 变量上。我不认为变量是必要的。基本逻辑应该是设置默认渲染,然后只有在满足粗体条件时才更改渲染。
-
我在这里第二个 camickr...minimal reproducible example 是解决此类问题所需要的。 camickr 的猜测也很中肯。例如,当 column>=3 时,您没有正确配置渲染器。但这就是我们没有minimal reproducible example:猜测。
-
@TT。那我该如何“正确配置”渲染器呢?我添加了一个
else案例并将字体设置为Font.Plain和Color.DARK_GRAY,这确实会改变其他列的颜色,但问题并没有解决。 -
我在您的代码中看到的 else 不是
if( column < 3 )AFAICT 的 else 部分。另外,我怀疑您使用markRow标记特定行是正确的。最好专门为每个单元格确定设置,不要指望 markRow 对另一个单元格是正确的。 -
@TT。我在我的代码中为
if (column<3)添加了一个“else”来测试它,但我还没有编辑 MRE 以将它添加到那里。我必须检查前 3 列的内容,我只在查看第一列时才这样做。据我了解,它遍历当前显示的单元格,然后为每个单元格设置渲染器。我不想对每个单元格进行整个大检查if(column==0),所以我需要一些可以轻松检查同一行的第 1 列和第 2 列的东西,这是我的markRow布尔值。
标签: java swing jtable tablecellrenderer