我正在开发一个图书馆程序,当我进行给定的连续操作时,我的书籍 JTable 中添加了一个意想不到的行。
动作是这样的:
- 启动程序
- 根据注释添加过滤器(我有很多过滤器,它们是从 RowFilter 继承的类,它们都与 JTable 的 RowSorter 相关联。程序的这一部分工作正常)。在初始状态下,JTable 中有 2 本书,分别是“le livre de la丛林”和“Eloge des mathématiques”。使用过滤器后,只剩下一个“Eloge des mathématiques”。另一个未显示,但仍在模型中。
- 在 JTable 中选择剩余的书(“le livre de la丛林”)。使用调试器,我看到在单击触发的操作期间,创建了一本标题和作者为空的书。它不可见,但如果我
- 停用所有过滤器,JTable 中现在有 3 本书。(2 前一个加上带有虚拟值的“幽灵”。)虚拟值来自保存当前字段的方法 saveChanges()。
这是程序的图片,带有功能区(北)、字段(中)和 JTable(下)。
你可以看到额外的行,出乎意料。
现在,让我们看一些代码:
当我点击 JTable 的行时,我触发了这个方法:
table.getSelectionModel().addListSelectionListener(e -> {
if (!e.getValueIsAdjusting()) {
if (table.getSelectedRow() > -1) {
Book book = ((TableATM) table.getModel()).getBook(table
.convertRowIndexToModel(table.getSelectedRow()));
getStatesManager().getState().selectBook(book);
}
}
});
这从 UnboundState 类调用 selectBook。窗口有 2 种状态:BoundState 和 UnboundState。UnboundState 在字段为空时使用。当这些字段包含一本书的数据时(例如,在互联网上使用 ISBN 进行远程搜索之后),它会立即被保存并且状态变为绑定。
在我上面谈到的搜索之后,状态与最初的状态保持一致,我的意思是 UnboundState :搜索只更改 JTable,而不更改字段。
所以,UnboundState 的 selectBook 被触发:
@Override
public void selectBook(Book book) {
statesManager.setBound(book);
}
setBound 方法的目的是改变状态:
public void setBound(Book book) {
state = new BoundState(book, this, bookWindow,
new ChoiceISBNDialog(bookWindow));
}
这是 setBound 调用的构造函数:
public BoundState(Book book, StatesManager statesManager,
BookWindow bookWindow, ChoiceISBNDialog choice) {
this.statesManager = statesManager;
this.bookWindow = bookWindow;
this.choice = choice;
SwingUtilities.invokeLater(() -> {
statesManager.enableFields(true);
if (statesManager.getState().getName().equals("BOUND"))
saveChanges();
statesManager.displayBook(book);
statesManager.setCaretsToZero();
bookWindow.ribbon.btn_revertChanges.setEnabled(false);
bookWindow.ribbon.btn_storeInTable.setEnabled(false);
});
}
重要的是不应该调用方法 saveChanges(),因为调用 invokeLater 时的当前状态是“UNBOUND”。
但是当我调试程序时,我得到这个:方法运行,按照我给你的odrer,除了调试器不进入invokeLater,它继续,方法完成,最后一个是JTable听众。但是我在 saveChanges() 方法中放置了一个断点,我看到 saveChanges() 方法是在 JTable 的侦听器结束后触发的。这是我认为的 invokeLater 的效果。但当时,状态变为“绑定”,saveChanges 方法认为字段中的实际书籍是新的并尝试保存它。
我怎样才能让它工作?我尝试调用 invokeAndWait 但它冻结了程序(它肯定会停止,即使在 1 分钟或更长时间之后)。