Запрашивая ввод пользователя извне кода GUI, нужно ли в этом случае События или Действие для связи с GUI? - PullRequest
2 голосов
/ 19 января 2012

Я пишу 2D-редактор полигонов и физики, одна из функций - установить предел поворота для соединений.

Чтобы использовать эту функцию, пользователь щелкает и перетаскивает линию между точками соединения, которые должны получить ограничение.

Логика определения правильности выбора происходит вне кода GUI.

Если найден пик, я хотел бы вызвать JOptionPane.showInputDialog, где пользователь может ввести ограничение.

Дело в том, что если я делаю это напрямую, программа перестает отвечать на запросы, я полагаю, это из-за многопоточности.

Есть ли способ определить прослушиватель событий, который может использовать GUI, для которого не требуется фактический компонент GUI?

Я хочу отправить событие, которое также содержит ссылку на целевой объект, на этот компонент, затем сообщить ему, что был сделан правильный выбор и требуется ввод данных пользователем, а затем отправить значение обратно через метод цели объект.

Я очень неопытен в свинге. Я догадываюсь, что я мог бы добавить ActionListener в главное окно, но я не знаю, как я мог бы обратиться к этому слушателю конкретно. Например, как мне нужно определить Action, который обрабатывается только этим конкретным слушателем? Если это действительно возможно, конечно.

До сих пор я использовал только слушателей, чтобы позволить GUI общаться с логикой, а не наоборот ...

Edit: Программа перестает отвечать на движения, которые я называю result = JOptionPane.showInputDialog(this,"Enter Limit.");

Это просто ломает это. Даже не могу ничего ввести в текстовое поле, закрыть его и т. Д.

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

Edit2: Я должен добавить, что я могу без проблем использовать JOptionPane.showInputDialog, если я его создаю, например, после нажатия кнопки или выбора опции всплывающего меню. Фактически, так я переименовываю предметы, с которыми работаю.

Но я предполагаю, что в этот момент диалог создается в потоке графического интерфейса или в очереди событий Диспетчер событий.

Однако проблема в том, что для этого нужны видимые интерактивные компоненты графического интерфейса, которые запускают это событие. Однако мне бы хотелось, чтобы какой-то компонент вызывал JOptionPane.showInputDialog точно так же, как и нажатая кнопка или контекстное меню, но без необходимости взаимодействия с пользователем, а не с помощью кода. Думаю, я мог бы использовать невидимые кнопки и эмулировать события щелчка мышью, но это довольно забавно ...

Кроме того, я пытался порождать Threads и Runnables, которые порождали JOptionPane.showInputDialog, но это тоже не помогло. Если я не создаю JOptionPane из источника с графическим интерфейсом, все останавливается, и диалог не будет работать.

Ответы [ 3 ]

2 голосов
/ 19 января 2012

Другой подход заключается в использовании класса SwingWorker для выполнения логики определения выбора в выделенном потоке без блокировки потока диспетчеризации GUI и использования его метода обратного вызова для выполнения действия GUI (откройте диалоговое окно ввода).

См .: http://docs.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html

(Эта страница содержит лучшее объяснение концепции, чем я мог бы написать.)

2 голосов
/ 19 января 2012

У издателя будет общедоступный слушатель добавления / удаления, где подписчик будет добавлять себя или добавляться через другой канал в EventListenerList в издателе.

Вы можете создать свой собственный интерфейс слушателя, который расширяет EventListener ифункция для съемки события.Ниже приведен пример:

import java.util.EventListener;

public interface MyEventListener extends EventListener {
   public void myEventOccurred(MyEvent event);
}

Затем вы можете создать свой собственный класс событий "MyEvent" в приведенном выше примере, например:

import java.util.EventObject;

public class MyEvent extends EventObject {
  // customer fields and methods here
  public MyEvent(Object source) //more possible args here {
    super(source);
    //other things here to do what you want
  }
}

Теперь вы можете настроить подписчика на реализацию MyEventListener ипереопределить метод myEventOccurred (..).

1 голос
/ 19 января 2012

Ваш фоновый поток должен иметь возможность вызывать диалог с invokeAndWait():

final double[] result = new double[1];
SwingUtilities.invokeAndWait(new Runnable() {
   public void run() {
      try {
         result[0] = Double.parseDouble(
            JOptionPane.showInputDialog("Enter value:"));
      } catch(NumberFormatException e) { 
         result[0] = -1;
      }
   }
}
// ... do something with result[0]

Здесь я сделал массив result только для того, чтобы он мог быть окончательным (доступным для анонимного класса) и также изменяемым.

...