【问题标题】:Waiting for mouse input in Java Swing在 Java Swing 中等待鼠标输入
【发布时间】:2009-10-20 14:05:01
【问题描述】:

我正在开发一个 Java Swing 应用程序。我有一个按钮,其操作在数据库上运行查询,然后绘制结果。这些命令是从“运行”按钮上的侦听器执行的。据我了解,这意味着此时运行的线程来自EventQueue。

给定某些输入,我需要停止处理并等待用户单击绘图区域。我正在努力寻找一种方法来做到这一点。我已经查看了所有内容,但似乎找不到有效的解决方案。我试图创建一个等待用户输入的新线程(我在这个线程上调用 join)。问题是这会使前一个线程(来自 EventQueue)等待。由于某种原因,鼠标点击不会导致中断,因此鼠标点击不会被捕获。

任何帮助将不胜感激。提前致谢。

【问题讨论】:

    标签: java multithreading swing mouseevent wait


    【解决方案1】:

    让 EventDispatcherThread 处理输入。相反,您生成的线程应该是进行计算的线程。我在一两年前构建了一个交互式 UI,它做了类似的事情,这就是我实现这种行为的方式。

    本质上,您在 GUI 和数据处理线程之间创建了一个生产者/消费者模型。当一个输入被触发时,你会提供给消费者线程并恢复活动。

    【讨论】:

    • 所有你需要做的就是创建一个 SwingWorker 实例,其中长时间运行的数据库代码在 doInBackground() 方法中,随后的 UI 更新在 done() 方法中,并执行这个 SwingWorker 线程在按钮的 ActionListener 中。
    【解决方案2】:

    使用SwingWorker 类。

    【讨论】:

    • 我在 1.6 之前构建了我的应用程序。如果您可以访问 1.6,请务必使用 SwingWorker。
    • 不幸的是,我坚持使用 1.5。我有一台基于 Intel 的 Mac,上次检查时,我无法使用 1.6。
    • SwingWorker 类非常适合演示,但我不想看到它在生产代码中使用。它通过将 EDT 上的 UI 操作与 EDT 上的非 UI 操作紧密耦合来削弱设计。
    • @Tom Hawtin - 那么你对生产代码有什么建议呢?我同意这是低级的,但老实说,当您需要在 EDT 之外运行长时间运行的任务时,您别无选择,在这种情况下,经过时间测试、调试的 API 是正确的选择。
    • SwingWorker 绝对是要走的路。您可以在此处获取 1.6 版本的 1.5 的反向端口:swingworker.dev.java.net
    【解决方案3】:

    您似乎在做大致正确的事情,但您不应该从 UI 线程调用后台线程上的 join,因为这会冻结 UI,直到后台线程完成。

    这是我将使用的基本方法的高度压缩示例(如果 SwingWorker 不可用):

    class QueryPerformer implements Runnable {
         private volatile boolean plotAreaClicked;
    
         public void run() {
             // Perform query and process
             while (!plotAreaClicked) {
                  try {
                       Thread.sleep(500);
                  } catch (InterruptedException exception) {
                  }
             }
             // Perform tasks following plot area click
         }
    
         public void setPlotAreaClicked(boolean plotAreaClicked) {
             this.plotAreaClicked = plotAreaClicked;
         }
    }
    

    在你的 UI 监听器中:

    private QueryPerformer queryPerformer;
    
    public void actionPerformed(ActionEvent event) {
        // Run button pressed
        queryPerformer = new QueryPerformer();
        new Thread(queryPerformer).start();
    }
    
    public void mouseClicked(MouseEvent event) {
        // Plot area clicked
        if (queryPerformer != null) {
            queryPerformer.setPlotAreaClicked(true);
        }
    }
    

    请注意,以上不是最优的,有些事情还没有处理(例如多次按下运行按钮)。

    【讨论】:

      猜你喜欢
      • 2012-07-28
      • 2011-08-18
      • 2015-09-03
      • 2012-11-15
      • 1970-01-01
      • 1970-01-01
      • 2021-05-09
      • 2013-05-25
      • 1970-01-01
      相关资源
      最近更新 更多