Java 在fireTableDataChanged()之后突出显示JTable中的更改
我使用的是一个JTable,其TableModel通过Java 在fireTableDataChanged()之后突出显示JTable中的更改,java,swing,jtable,tablemodel,Java,Swing,Jtable,Tablemodel,我使用的是一个JTable,其TableModel通过fireTableDataChanged()定期更新。这些变化通常很小,例如添加或修改了一行,但是我无法预测它会发生在哪里 有没有办法知道在fireTableDataChanged()上添加或修改了哪些行?我想突出显示这些行,以便用户也知道。首先,您必须为Swing设置适当的上下文:TableModel必须对自身有足够的了解/控制,以完全遵守其通知契约。也就是说,每当发生这样的更改时,它必须激发row-/cellUpdated或rowsIns
fireTableDataChanged()
定期更新。这些变化通常很小,例如添加或修改了一行,但是我无法预测它会发生在哪里
有没有办法知道在
fireTableDataChanged()
上添加或修改了哪些行?我想突出显示这些行,以便用户也知道。首先,您必须为Swing设置适当的上下文:TableModel必须对自身有足够的了解/控制,以完全遵守其通知契约。也就是说,每当发生这样的更改时,它必须激发row-/cellUpdated或rowsInserted
然后,突出显示JTable中的更改(特定时间)的基本方法是
- 实现一个自定义渲染器,用于装饰某些存储中的单元
- 使用自定义渲染器配置表
- 倾听模型的变化
- 将changeEvents(或具有相关属性的自定义对象)添加到渲染器知道的存储中
- 使用计时器在一段时间后删除更改标记
- 为桌子配置荧光灯,以进行视觉装饰
- 倾听模型中的变化
- 将更改后的单元格添加到自定义高亮谓词,并使用它配置高亮
- 使用计时器在一段时间后删除更改标记
JXTable table = new JXTable(model);
final ChangeDecorator controller = new ChangeDecorator();
table.addHighlighter(controller.getChangeHighlighter());
TableModelListener l = new TableModelListener() {
@Override
public void tableChanged(TableModelEvent e) {
if (TableUtilities.isUpdate(e)) {
Change change = new Change(e.getFirstRow(), e.getColumn());
controller.addChange(change);
} else if (TableUtilities.isInsert(e)) {
Change change = new Change(e.getFirstRow());
controller.addChange(change);
}
}
};
model.addTableModelListener(l);
/**
* Manages the Highlighters for inserted rows/updated cells.
*/
public static class ChangeDecorator {
private List<Change> changes;
private AbstractHighlighter update;
private AbstractHighlighter insert;
private Highlighter compound;
public ChangeDecorator() {
changes = new ArrayList<>();
}
public Highlighter getChangeHighlighter() {
if (compound == null) {
update = new ColorHighlighter(new ChangePredicate(changes, true),
Color.YELLOW, null);
insert = new ColorHighlighter(new ChangePredicate(changes, false),
Color.GREEN, null);
compound = new CompoundHighlighter(update, insert);
}
return compound;
}
public void addChange(Change change) {
startTimer(change, change.isCell ? update : insert);
}
private void startTimer(final Change change, final AbstractHighlighter hl) {
changes.add(change);
hl.setHighlightPredicate(new ChangePredicate(changes, change.isCell));
ActionListener l = new ActionListener() {
boolean done;
@Override
public void actionPerformed(ActionEvent e) {
if (!done) {
done = true;
return;
}
((Timer) e.getSource()).stop();
changes.remove(change);
hl.setHighlightPredicate(new ChangePredicate(changes, change.isCell));
}
};
Timer timer = new Timer(2000, l);
timer.setInitialDelay(100);
timer.start();
}
}
/**
* A predicate enables highlighting a cell if it
* contains a change for that cell.
*/
public static class ChangePredicate implements HighlightPredicate {
private List<Change> changes;
private boolean matchCell;
public ChangePredicate(List<Change> changes, boolean matchCell) {
this.changes = new ArrayList(changes);
this.matchCell = matchCell;
}
@Override
public boolean isHighlighted(Component renderer,
ComponentAdapter adapter) {
return changes.contains(createChange(adapter));
}
private Change createChange(ComponentAdapter adapter) {
int modelRow = adapter.convertRowIndexToModel(adapter.row);
if (matchCell) {
int modelColumn =
adapter.convertColumnIndexToModel(adapter.column);;
return new Change(modelRow, modelColumn);
}
return new Change(modelRow);
}
}
/**
* A crude class encapsulating a cell change.
*
*/
public static class Change {
int row;
int column;
boolean isCell;
public Change(int row) {
this(row, -1, false);
}
public Change(int row, int col) {
this(row, col, true);
}
private Change(int row, int col, boolean update) {
this.row = row;
this.column = col;
this.isCell = update;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Change)) return false;
Change other = (Change) obj;
return row == other.row && column == other.column && isCell == other.isCell;
}
}
JXTable表=新的JXTable(模型);
最终ChangeDecorator控制器=新的ChangeDecorator();
table.addHighlighter(controller.getChangeHighlighter());
TableModelListener l=新的TableModelListener(){
@凌驾
公共作废表已更改(TableModelEvent e){
if(TableUtilities.isUpdate(e)){
Change Change=新更改(e.getFirstRow(),e.getColumn());
控制器。添加更改(更改);
}else if(TableUtilities.isInsert(e)){
Change Change=新的更改(例如getFirstRow());
控制器。添加更改(更改);
}
}
};
model.addTableModelListener(l);
/**
*管理插入行/更新单元格的高亮显示。
*/
公共静态类变更装饰器{
私人名单变更;
私人荧光灯更新;
私人荧光灯插页;
私人荧光灯化合物;
公共变更装饰器(){
changes=新的ArrayList();
}
公共荧光灯getChangeHighlighter(){
if(复合==null){
更新=新的彩色荧光灯(新的ChangePredicate(更改,真),
颜色:黄色,空);
插入=新的彩色荧光灯(新的ChangePredicate(更改,错误),
颜色:绿色,空);
化合物=新化合物荧光灯(更新、插入);
}
返回化合物;
}
公共无效添加更改(更改更改){
startTimer(change,change.isCell?更新:插入);
}
私有void startTimer(最终变更、最终抽象){
更改。添加(更改);
hl.setHighlightPredicate(newchangePredicate(changes,change.isCell));
ActionListener l=新的ActionListener(){
布尔完成;
@凌驾
已执行的公共无效操作(操作事件e){
如果(!完成){
完成=正确;
返回;
}
((计时器)e.getSource()).stop();
更改。删除(更改);
hl.setHighlightPredicate(newchangePredicate(changes,change.isCell));
}
};
定时器=新定时器(2000,l);
定时器。设置初始延迟(100);
timer.start();
}
}
/**
*谓词启用高亮显示单元格,如果它
*包含对该单元格的更改。
*/
公共静态类ChangePredicate实现HighlightPredicate{
私人名单变更;
私有布尔匹配单元;
公共ChangePredicate(列表更改,布尔匹配单元格){
this.changes=新的ArrayList(变更);
this.matchCell=matchCell;
}
@凌驾
公共布尔isHighlighted(组件渲染器,
组件适配器(适配器){
returnchanges.contains(createChange(adapter));
}
私有更改createChange(组件适配器){
int modelRow=adapter.convertRowIndexToModel(adapter.row);
if(匹配单元){
int模型列=
adapter.convertColumnIndexToModel(adapter.column);;
返回新更改(modelRow、modelColumn);
}
返回新更改(modelRow);
}
}
/**
*封装单元格更改的原始类。
*
*/
公共静态类变更{
int行;
int列;
布尔isCell;
公共变更(国际行){
这(第-1行,错误);
}
公共更改(整数行,整数列){
这(行、列、真);
}
私有更改(整数行、整数列、布尔更新){
this.row=行;
this.column=col;
this.isCell=更新;
}
@凌驾
公共布尔等于(对象obj){
如果(!(obj instanceof Change))返回false;
变更其他=(变更)obj;
返回row==other.row&&column==other.column&&isCell==other.isCell;
}
}
首先,您必须为Swing:TableMo设置适当的上下文