我一直在询问有关我最近一直在做的项目的很多问题。这是我所处的情景,正确方向的任何帮助或观点都会有所帮助......
这是一个使用服务器和多个客户端构建的网络程序。每个客户端都有一个GUI,必须根据服务器发送的命令执行操作。每个客户端都包含在一个名为Player
的类中。这个Player
有一个GUI(扩展JFrame
)和一个main方法,而Server只有一个main方法(没有GUI)。起初,这个类是在主线程中创建的,如下所示:
EventQueue.invokeLater(new Runnable()
{
public void run()
{
new Player().setVisible(true);
}
});
这很好用,直到我意识到整个Player
类现在正在EDT中执行。因此,当我等待来自服务器的命令时,整个GUI会锁定,直到发送该命令并执行适当的操作。你可以想像,这是一个可怕的设计,并被证明是一个编码环境的真正的痛苦时,每次要检查的东西,你必须找到周围一些疯狂的工作,使GUI依然保持完好。
显然,我必须在单独的线程中检查来自服务器的命令,并在EDT中运行GUI组件。我的第二个实现有两个类 - 一个用于GUI,一个用于Player
。我的想法是Player
有一个包含GUI的变量,以便我可以从Player
类访问GUI,如下所示:
class Player
{
public GUI gui;
...
// And then start this gui inside of the EDT.
EventQueue.invokeLater(new Runnable()
{
public void run()
{
this.gui = new GUI().setVisible(true);
}
}
这也不起作用,因为新this
对象内的Runnable
引用了Runnable
对象,而不是Player
。
如何在一个线程中的Player
类与EDT线程中相应的GUI类之间进行通信?
答案 0 :(得分:3)
要使用this
指针处理问题,您应该写:
class Player
{
public GUI gui;
...
// And then start this gui inside of the EDT.
EventQueue.invokeLater(new Runnable()
{
public void run()
{
Playser.this.gui = new GUI().setVisible(true);
}
}
}
答案 1 :(得分:2)
BorisPavlović语法正确(实际上您可以删除this.
),但代码仍然没有意义。 gui
字段在Runnable
事件排队后的某个时间初始化,因此播放器线程使用它是不安全的。
您可以在EDT上构建Player
(但在EDT上执行网络操作)。或者将GUI注册为Player
的监听器(观察者)。 invokeAndWait
会起作用,但是很危险,因为它经常会导致偶尔难以调试的死锁。
答案 2 :(得分:1)
答案 3 :(得分:1)
你可以试试这个:
班级球员 { 公共桂桂;
...
// And then start this gui inside of the EDT.
EventQueue.invokeLater(new Runnable()
{
public void run()
{
Player.this.gui = new GUI().setVisible(true);
}
}
答案 4 :(得分:1)
“直到我意识到整个Player类现在正在EDT中执行”
构造函数出现在EDT上,但在此类上调用的方法可能不是。
您应该按照最初的意图构建播放器GUI。
EventQueue.invokeLater(new Runnable()
{
public void run()
{
new Player().setVisible(true);
}
});
但是Player可以在构造函数中启动一个单独的线程(我个人在玩家之间共享一个连接)。
当然,服务器的回调方法在修改可见组件时应使用invokeLater()。
答案 5 :(得分:0)
为什么不将匿名内部类声明为实现Runnable的类,而是使用一个以GUI实例作为参数的构造函数,而不是使用匿名内部类?
此外,如果您的GUI类不是线程安全的,请考虑使用消息队列在EDT和&之间进行通信。主线。