Приложение Java Swing: как получить данные из потока GUI в другой поток? - PullRequest
4 голосов
/ 22 февраля 2012

В моем Java-приложении с графическим интерфейсом Swing я хотел бы добиться следующего.

Работает не-GUI-поток, выполняющий некоторую работу.В какой-то момент этот поток требует ввода от пользователя, прежде чем он сможет продолжить.Затем я хотел бы внести некоторые изменения в GUI, дождаться определенного действия GUI (например, пользователь нажал кнопку OK), получить введенные данные из GUI в поток, не связанный с GUI, и позволить ему продолжить вычисления.

Оглядываясь вокруг, я нашел много информации о том, как инициировать выполнение (длительной) задачи из потока графического интерфейса Swing в другом потоке, но ничего о моей проблеме.

SwingUtilites.invokeAndWait звучит так, как будто он выполняет свою работу, но сначала он принимает аргумент Runnable вместо Callable, поэтому нет простого способа вернуть результат, а во-вторых, это не такрешить проблему ожидания определенного события графического интерфейса.

Я понимаю, что мог бы придумать свое собственное решение, например, с помощью CountDownLatch, но мне кажется, что проблема кажется достаточно частой для стандартного решения.

Итак, мои вопросы: действительно ли это частая проблема, и если да, есть ли решение в стандартной библиотеке / библиотеках?Если нет стандартного решения, как бы вы его решили?Если эта проблема возникает не часто, почему бы и нет?

Ответы [ 4 ]

6 голосов
/ 22 февраля 2012

Простое изменение графического интерфейса пользователя, поэтому я предполагаю, что вы спрашиваете только о возврате данных в рабочий поток.

Сначала создайте очередь блокировки . Пусть рабочий поток вызовет take() в очереди, и он заблокируется. В GUI-пространстве, как только пользователь введет корректный ввод, поместите его в очередь с offer(), и рабочий поток получит данные и сможет продолжить.

1 голос
/ 22 февраля 2012

java.awt.EventQueue.invokeLater отлично работает для запуска кода на AWT EDT.Вероятно, лучше всего копировать изменяемые данные или лучше использовать неизменяемые данные.Блокировки возможны, но немного рискованно.

Если ваш другой поток является циклом диспетчеризации событий, вы можете реализовать что-то вроде invokeLater для своего потока (но не делайте его статичным!).Вероятно, используйте его за каким-то интерфейсом, который имеет смысл для поведения потока - так что это реальные операции, а не run, который указан как выполняющий все, что ему нравится.Если ваш поток собирается блокировать, то BlockQueue в порядке, но не блокируйте его из AWT EDT.

java.awt.EventQueue.invokeAndWait похоже на использование блокировки.Вероятно, вы собираетесь использовать другой замок.Или, возможно, блокировка типа invokeAndWait в вашем собственном потоке.Если вы этого не сделаете, AWT все равно использует блокировку.Итак, неконтролируемые вложенные блокировки, это, вероятно, означает тупик.Не используйте invokeAndWait!

1 голос
/ 22 февраля 2012

Я думаю, вы можете использовать ExecutorService , где вы также можете отслеживать ход выполнения вашей задачи через Future интерфейс.

0 голосов
/ 22 февраля 2012
final bool result = doSomething();
SwingUtilities.invokeLater( new Runnable(){
       //Runnable method implementation. 
       //use result in your method like local var.
    });

Убедитесь, что ваши общие данные синхронизированы, используйте объекты блокировки. Если вам нужно передать аргументы в Runnable, просто сделайте ваши локальные переменные окончательными, и использовать их в методе запуска.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...