Как структурировать publish() и process() в SwingWorker для обновления более одного компонента Swing в EDT?

У меня есть процесс подключения ServerSocketChannel в SwingWorker. В самом приложении Swing два JLabels должны обновляться (1) строкой (статус соединения) и (2) целым числом (количество подключенных клиентов). Ниже приведен скриншот приложения до того, как JButton «Обнаружение клиентов» запустит процесс подключения. Однако я не уверен, как опубликовать () и обработать (), чтобы обновить более одного компонента Swing в EDT. Есть ли у кого-нибудь руководство о том, как этого добиться?

Снимок экрана

Поскольку 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
    } 
}

person Arvanem    schedule 15.09.2012    source источник
comment
Вы пытались следовать примерам из javadoc SwingWorker? это довольно просто. пример обновляет один компонент в методе process(), но должно быть довольно просто обновить несколько компонентов.   -  person jtahlborn    schedule 15.09.2012
comment
@jtahlborn Я принял примеры из javadoc. Я продолжал сталкиваться с проблемами с преобразованием и ошибками, указывающими, что мой process() не переопределяет версию суперкласса. Стало запутанно...   -  person Arvanem    schedule 15.09.2012


Ответы (2)


А, теперь я понимаю вашу проблему. вы пытаетесь опубликовать 2 разных бита информации. обратите внимание, что список, переданный в метод process(), может содержать результаты нескольких вызовов publish(), поэтому передача разных типов значений будет запутана в вашем методе process(). вместо этого вы должны создать простой объект для инкапсуляции всех состояний, которые вы хотите передать, и всегда публиковать экземпляры этого класса (что также решит все ваши проблемы с кастингом). например.:

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

Затем вы всегда будете публиковать экземпляр ChannelStatus с текущим количеством клиентов и «активным» статусом.

person jtahlborn    schedule 15.09.2012
comment
Он может легко различать int и String, как я описал, однако это был бы и мой предпочтительный метод. Еще одна вещь, которую он мог бы сделать, это установить прогресс (флаг int) и прослушивать связанное свойство прогресса. Затем он мог различать String и int в зарегистрированном PropertyChangeListener на основе этого флага. - person nullpotent; 15.09.2012
comment
@iccthedral - что, если одно из строковых значений будет проанализировано как целое число? запихивать кучу разнородных данных в строковые значения и надеяться на лучшее на другом конце... в лучшем случае сомнительно. - person jtahlborn; 15.09.2012
comment
Спасибо. Ваше решение приводит к более ясному и простому коду для обработки различных состояний. Я также включил решение для прослушивания свойств icctedral от icctedral, так что теперь очень приятно напевать. - person Arvanem; 16.09.2012

Вы можете использовать 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 и соответствующих геттеров, заполните его по мере продвижения и опубликуйте объект этого класса.

Скажи мне, если я не понял тебя должным образом, потому что у меня есть предчувствие, что ты можешь захотеть, чтобы PropertyChangeListeners был вовлечен в это дело.

person nullpotent    schedule 15.09.2012
comment
Я думаю, что вы правильно понимаете мою проблему. Я попробую еще раз через несколько часов, используя предложенную вами структуру. Будет неприятно, если снова возникнет ошибка аннотации @Override, о которой я упоминал выше. - person Arvanem; 15.09.2012
comment
PropertyChangeListeners может быть билетом. Я изучу их и SwingWorkers и дам вам знать, как это происходит. Спасибо за уделенное время. - person Arvanem; 15.09.2012
comment
Все хорошо. Если вам нужна дополнительная помощь, просто дайте мне знать. - person nullpotent; 15.09.2012