ListSelectionListener事件的延迟

时间:2018-01-25 18:21:52

标签: java jtable delay listselectionlistener

我有一个普通的JTable和一个ListSelectionListener。我认为它可以正常工作,但有一个问题:

  1. 我点击表格行
  2. 事件触发(方法valueChanged启动)
  3. Inside valueChanged我启动一个http请求(需要几毫秒)
  4. 表格行明显被选中(蓝色背景)
  5. 这会产生明显的延迟。

    我可以更改活动的顺序吗?我想首先使用蓝色背景,然后执行http请求。 在valueChanged方法中插入睡眠定时器会使选择等到计时器结束。

1 个答案:

答案 0 :(得分:1)

您应该在后台线程上执行HTTP请求。如果需要非常长的时间,这也有保持UI响应的优势。

根据您的实际需求,您最终会得到类似的代码:

private static class HttpWorker extends SwingWorker<Void, Void> {
    private final String url;
    private HttpWorker(String url) {
        this.url = Objects.requireNonNull(url);
    }
    @Override
    protected Void doInBackground() {
        // do request, possibly producing some result
    }
    @Override
    protected void done() {
        if (!isCancelled()) {
            // update UI
        }
    }
}

private HttpWorker worker;

@Override
public void valueChanged(ListSelectionEvent e) {
    if (worker != null) {
        // preserve apparent order of operations if
        // the user selects something different while
        // a background task is already running
        worker.cancel(true);
        worker = null;
    }
    worker = new HttpWorker(...);
    worker.execute();
}

doInBackground通常可以采取任何操作,只要您不与Swing UI进行交互。

另见the SwingWorker tutorialsdocumentation

为了获得完整的答案,在列表选择事件开始时执行以下操作可以

工作:

jlist.paintImmediately(0, 0, jlist.getWidth(), jlist.getHeight());

至少在paintImmediately被指定做隐含的事情的时候:

  

立即绘制此组件中指定区域及其与区域重叠的所有后代。 [...]如果需要在调度当前事件时更新显示,此方法很有用。

我不建议使用它的原因是没有特别的原因需要在我们自己的监听器之前更新JList,这样列表实际上会绘制新的选择。

还有一个问题是,通常不应该在Swing线程上执行像HTTP请求这样的繁重任务,因为它会冻结UI。即使在您希望用户等待一段时间的情况下,也不会直接在Swing线程上执行任务。你可以在后台线程中执行它并弹出一个模态对话框,可能会让用户提前取消任务。