【问题标题】:How to structure publish() and process() in a SwingWorker to update more than one Swing component on the EDT?如何在 SwingWorker 中构造 publish() 和 process() 以更新 EDT 上的多个 Swing 组件?
【发布时间】:2012-09-16 01:25:23
【问题描述】:

我在 SwingWorker 中有一个 ServerSocketChannel 连接进程。在 Swing 应用程序本身中,两个 JLabel 应该更新为 (1) 字符串(连接状态)和 (2) 整数(连接的客户端数)。下面是“检测客户端”JButton 运行连接过程之前应用程序的屏幕截图。但是,我不确定如何发布()和处理(),以便在 EDT 上更新多个 Swing 组件。有没有人指导如何实现这一目标?

因为List<V>是process()的参数,所以我试了<Object>为<V>。但是,这似乎遇到了从字符串/整数到对象的转换问题,反之亦然。

下面的演示代码说明了应该发布更新的几点:

protected Void doInBackground() {
    try {
       // Omitted: obtain selector
       ServerSocketChannel ssc = ServerSocketChannel.open() // could fail, may need
       // to publish status
       ssc.socket().bind(serverAddress); // could fail, may need to publish status
       ssc.configureBlocking(false); // could fail, may need to publish status
       // Omitted: register ssc
       while (true) {
           int count = sel.select(1000); // may need to publish for # of clients
           // Omitted: rest of processing     
       }
    } catch (IOException e) {
        //handle error
    } 
}

【问题讨论】:

  • 您是否尝试按照 SwingWorker javadoc 中的示例进行操作?这很简单。该示例更新了process() 方法中的一个组件,但更新多个组件应该非常简单。
  • @jtahlborn 我确实采用了 javadoc 中的示例。我一直遇到转换问题,并且错误表明我的 process() 没有覆盖超类版本。越来越混乱了……

标签: java multithreading swingworker


【解决方案1】:

啊,现在我明白你的问题了。您正在尝试发布 2 条不同的信息。请注意,传递给process() 方法的列表可能包含多个 publish() 调用的结果,因此传递不同类型的值会在您的process() 方法中混淆。相反,您应该创建一个简单的对象来封装所有您希望传递的状态,并始终发布该类的实例(这也将解决您的所有转换问题)。例如:

public class ChannelStatus {
  public final boolean active;
  public final int numClients;
}

然后,您将始终发布具有当前客户端数量和“活动”状态的 ChannelStatus 实例。

【讨论】:

  • 他可以像我描述的那样轻松区分 int 和 String,但这也是我的首选方法。他可以做的另一件事是设置进度(int 标志)并监听“进度”绑定属性。然后他可以根据该标志区分 String 和已注册 PropertyChangeListener 中的 int。
  • @iccthedral - 如果“字符串”值之一恰好被解析为“int”怎么办?将一堆异构数据推入字符串值并希望在另一端获得最好的结果......充其量是可疑的。
  • 谢谢。您的解决方案会产生更清晰、更简单的代码来处理各种状态。我还加入了 iccthedral 的 propertychange 监听器解决方案,所以现在非常好听。
【解决方案2】:

您可以使用 String 作为结果类型。说,对于一个整数(客户数量)做publish(String.valueOf(integer)),然后在你的process()方法中尝试类似

try {
 int numClients = Integer.parseInt(passedString);
 //all well, it's the client number
} catch(NumberFormatException ex) {
 //not a number, must be a connection status
}

或者简单地将这两个信息用setNumClients, setConnStatus 和适当的getter 包装在一个单独的类中,随着您的进展填充它,然后发布该类的对象。

如果我没有正确理解您,请告诉我,因为我有一种预感,您可能希望 PropertyChangeListeners 参与其中。

【讨论】:

  • 我认为您对我的问题的理解是正确的。我将在几个小时后使用您提出的结构再试一次。如果我上面提到的@Override注解错误再次出现,那将是令人沮丧的。
  • PropertyChangeListeners 可能是票。我会研究这些和 SwingWorkers 并让你知道它是如何进行的。感谢您的宝贵时间。
  • 一切顺利。如果您需要进一步的帮助,请告诉我。
猜你喜欢
  • 2015-04-23
  • 2013-09-03
  • 1970-01-01
  • 2013-02-12
  • 1970-01-01
  • 2018-06-21
  • 2011-01-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多