Java 从GUI代码外部请求用户输入,在这种情况下,我是否需要事件或操作来与GUI通信?

Java 从GUI代码外部请求用户输入,在这种情况下,我是否需要事件或操作来与GUI通信?,java,swing,events,actionlistener,Java,Swing,Events,Actionlistener,我正在编写一个2D多边形和物理编辑器,其中一个功能是为关节设置旋转限制 要使用此功能,用户单击并拖动需要接收限制的关节点之间的线 确定拾取是否有效的逻辑发生在GUI代码之外 如果找到一个提货,我想弹出一个作业窗格。showInputDialog,用户可以在其中输入限额 问题是,如果我直接这样做,程序会变得无响应,我想这是因为线程 有没有一种方法可以定义GUI可以使用的事件侦听器,而不需要实际的GUI组件 我想向该组件发送一个事件,该事件还包含对目标对象的引用,然后告诉它已进行了有效拾取,需要用户

我正在编写一个2D多边形和物理编辑器,其中一个功能是为关节设置旋转限制

要使用此功能,用户单击并拖动需要接收限制的关节点之间的线

确定拾取是否有效的逻辑发生在GUI代码之外

如果找到一个提货,我想弹出一个
作业窗格。showInputDialog
,用户可以在其中输入限额

问题是,如果我直接这样做,程序会变得无响应,我想这是因为线程

有没有一种方法可以定义GUI可以使用的事件侦听器,而不需要实际的GUI组件

我想向该组件发送一个事件,该事件还包含对目标对象的引用,然后告诉它已进行了有效拾取,需要用户输入,然后通过目标对象的方法将值发送回

我对荡秋千非常缺乏经验。 我的直觉是,我可能能够在主窗口中添加一个
ActionListener
,但我不知道如何专门针对该侦听器。 在中,我需要如何定义一个只由特定侦听器处理的
操作
? 当然,如果这真的有可能的话

到目前为止,我只使用侦听器让GUI与逻辑对话,而不是相反

编辑: 程序对我调用的运动没有响应
result=JOptionPane.showInputDialog(这是“输入限制”)

这就破坏了它。甚至不能在文本框中输入任何内容,也不能关闭它,等等

我想这是因为它产生了一个暂停某个线程的模式对话框,从非GUI代码内部的某个地方调用它不是我应该做的事情,但我太没有经验了,不知道另一种方法

编辑2: 我应该补充一点,如果我生成了JOptionPane.showInputDialog,例如,在单击按钮或选择弹出菜单选项后,我可以使用它,而不会出现任何问题。 事实上,这就是我重命名正在处理的项目的方式

但我假设此时,对话框是在GUI线程中生成的,或者是这个事件调度程序队列

但问题是,这需要触发该事件的可见、交互式GUI组件。 但是,我想要的是某种组件,它可以生成JOptionPane.showInputDialog,就像单击的按钮或上下文菜单一样,但不必与用户交互,而是由代码交互。 我想我可以使用不可见的按钮和模拟鼠标点击事件,但这是相当黑客

此外,我还尝试生成线程和可运行程序,它们生成了JOptionPane.showInputDialog,但这也没有帮助。
除非我从GUI源生成JOptionPane,否则一切都会暂停,对话框将无法工作。

发布服务器将有一个公共添加/删除侦听器,订阅服务器将在其中添加自己或通过另一个频道添加到发布服务器中的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并重写MyEventToCurred(..)方法。

另一种方法是使用SwingWorker类在专用线程中执行确定拾取的逻辑,而不阻塞GUI调度线程,并使用其回调方法执行GUI操作(打开“输入”对话框)

见:


(这个页面对这个概念的解释比我写的更好。)

您的后台线程应该可以生成一个带有
invokeAndWait()的对话框。


在这里,我将
结果制作成一个数组,这样它就可以是最终的(匿名类可以访问),也可以是可变的。

因此序列是1)用户单击一个点并拖动到另一个点2)模型代码确定这两个点是否定义了关节3)如果是,用户界面会显示一个对话框,询问数字4)当对话框关闭时,模型将更新,UI将重新绘制。我理解对了吗?用户界面在什么阶段变得无响应?@Russell Zahniser更新了我的帖子,不确定清除了多少,但它确实看起来像是一个不属于那里的函数调用。我如何将MyEventListener添加到我的用户界面?主窗口类是一个JFrame,它缺少addActionListener方法……因此您的发布者(发送事件的类)需要包含将MyEventListener作为参数的公共add和remove方法。然后,发布者将该侦听器添加到EventListenerList类型的列表中。订阅者(需要听到事件发生的类)需要实现MyEventListener,并通过公共add方法将自己添加到发布者列表中。当发布者需要发布一个事件时,它会循环通过它的订阅者并将事件发送给每个订阅者。嗯,我刚刚尝试过这个,但最后它似乎再次模拟了对JOptionPane.showInputDialog的直接调用。看来我在这里遇到的真正问题是线程相关的。当生成输入对话框时,非GUI代码会暂停,对话框本身变得不可用,迫使我从外部终止应用程序。想象一下,在编写了一个游戏之后,在物理集成的某个地方,您生成了一个模式对话框,它暂停了一切,而不仅仅是GUI层。这似乎是罪魁祸首。更新了问题,也许现在可以提供更多的澄清。invokeAndWait()不起作用,奇怪的是抛出了一个异常,并告诉我“无法从事件调度程序线程调用invokeAndWait”。然而,invokeLater确实起了作用。我不知道为什么这段代码被认为是事件调度器线程的一部分。我正在使用Libgdx,而且
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]