有很多方法可以解决这个问题
用户可以根据需要打开和关闭任意多个 Jframe,并且所有 Jframe 都必须显示从 rs232 读取的相同数据
如果您只对实时结果或历史结果感兴趣,这就提出了一个问题。为了论证起见,我只关注实时结果。
基本上,您需要从一个负责实际从端口读取数据的类开始。这个类应该只做两件事:
- 读取数据
- 读取新数据时生成事件
为什么?因为您想要实现的任何其他功能(例如将数据写入数据库或出于某种原因缓存结果)都可以稍后添加,只需监控生成的事件即可。
接下来,您需要定义一个interface,它描述了观察者为了能够接收事件而实施的合约
public interface ScaleDataSourceListener {
public void scaleDataUpdated(ScaleDataSourceEvent evt);
}
您还可以添加连接事件(连接/断开连接)或其他可能很重要的事件,但我保持简单。
ScaleDataSourceEvent 将是一个简单的interface,它描述了事件的数据
public interface ScaleDataSourceEvent {
public ScaleDataSource getSource();
public double data();
}
例如(我喜欢接口,它们描述了预期的契约,定义了职责并限制了其他人在收到实现接口的对象的实例时可以做什么,但那是我)
然后,您的数据源将允许观察者注册自己以收到有关它生成的事件的通知...
public interface ScaleDataSource ... {
//...
public void addDataSourceListener(ScaleDataSourceListener listener);
public void removeDataSourceListener(ScaleDataSourceListener listener);
}
(我假设数据源将能够执行其他操作,但我已将其留给您来填写,同样,我更喜欢可能的接口,这不是您的设计限制;) )
因此,当从端口读取数据时,它会生成一个新事件并通知所有注册的侦听器。
现在,Swing 不是线程安全的,这意味着,您不应该从除事件调度线程之外的任何线程更新 UI。
在您的情况下,最简单的解决方案可能是简单地使用 SwingUtilities.invokeLater 从数据源线程上下文移动到 EDT。
基本上,这是一个简单的Observer Pattern
您还需要考虑许多其他注意事项。即,框架是在与数据源相同的进程中打开的,还是数据源在其自己的单独进程中运行。这使过程复杂化,因为您需要某种 IPC 系统,可能使用套接字,但最重要的设计是相同的。
如果数据源读取数据的速度比您生成事件的速度更快,会发生什么情况?您可能需要某种队列,其中数据源只是将数据转储到队列中,并且您有某种调度程序(在另一个线程上)读取它并调度事件。
有多种阻塞队列的实现可以提供一定程度的线程安全,请查看并发 API 以了解更多详细信息。
...作为一些想法;)