2009-09-04 71 views
2

场景:懒惰实例化的JTable + TableModel缓存提取事件?

您正在使用带有自定义TableModel的JTable来查看位于数据库或网络中某些集合的内容或其他内容。

使这项工作的蛮力方法是一次加载整个集合。假设这是不切实际的,因为需要资源。

解决这个问题的简单方法是随着JTable呈现每一行,按需提取行,每次一行,并调用TableModel.getValueAt();必要时缓存。不过,这会导致数据库命中很多。

是否有一种方法来侦听JTable的滚动/视口事件,找出它在呈现每个单元格之前要显示的行?如果是这样,我想拦截并导致我的自定义TableModel一次预取一页。

编辑:我只想澄清,这里的关键是要能够在一个批次中获取一组可见表行的内容,而不是通过自身获取的每一行的内容。

+0

为了保持模型视图为1-n关系,我认为最好不要查询视口,而只需要依靠在模型上执行的实际请求。自己检查视口不会更快。对于没有填充的单元格返回'null'是没有问题的,因为当你的实际批量数据来自后端时,你可以生成tableRow事件。并且jtable将再次刷新。 您可以在每个model.getValue()请求中重置一个计时器。一旦定时器激活(比如说10ms),就可以检索在一个批量请求中查询的记录。 – Houtman 2009-09-16 07:04:31

回答

2

实际上,这正是JTable所允许的。 afaik 如果getRowCount()方法确切反映了有多少条记录,则在绘制单元格时仅查询可见部分。 我不认为通过在视口上聆听预取会更快。

您可以等待所有的getvalue请求。记录那些,返回“null”或已经缓存的值。那么在getvalue没有被调用之后,比如20ms对所有记录的单元格做实际的请求。并在模型上激发rowUpdated事件,以便JTable再次重绘。

**您可以维护模型上查询的最后记录列表。您的列表不需要长于屏幕上可见的行数。在getValue()不查询几ms后,您可以对后端执行此异步批量请求

这里唯一的问题是排序/过滤算法。 当您查询视口并让数据依赖于该视口时,则数据与视图之间存在一个关系。 JTable本身没有的东西。 但我想这是没有办法的。 我会让IDE调试器通过太阳代码进行挖掘。然后看看他们的渲染实现如何找出要重绘的行。我不知道。

3

看看http://www.javaworld.com/javaworld/javatips/jw-javatip137.html文章。在本文中,有一个自定义的TableModel,可以从数据库中检索“块”行

该场景的另一个解决方案虽然不是您正在寻找的内容,但会延迟加载每行而不是预取。查看我自己的帖子(在谷歌上搜索“JTable绑定到数据库,使用延迟加载”),了解如何执行此操作。这个想法是,当tablemodel被询问一个没有被缓存/加载的行时,它会为每一列返回“wait..retrieving”字符串(假设所有列都是字符串)。同时它将在另一个线程中安排任务(使用ExecutorService)。然后该任务将从数据库检索数据并更新数据模型。在我的文章中,我实际上使用了Beans绑定,因此使用自定义列表而不是自定义表模型。但我相信你可以推断这个想法。