*我正在使用Java。
我有这个线程,代理,探索一个房间来确定它的大小,如果它很脏就清理它。然后我有了界面,它在探索环境时绘制代理。 Agent是Thread的子类,Java负责管理线程。我所做的就是创建线程并说出object.start()。
这在正常情况下非常有效。但是,在此期间启用菜单,这意味着用户可以在代理正在探索时弄乱房间。这不应该发生。
因此,一旦用户点击告诉代理清理房间的选项,我想禁用所有菜单。除非它不能正常工作。这是问题所在:
...
public void ActionPerformed(ActionEvent e)
{
//disable the menus with setEnabled(false);
agent.start();
//enable the menus with setEnabled(true);
}
问题是在代理程序线程执行其功能之前启用了菜单。我想过使用Thread.join() - 这可以保证启用菜单的代码只在代理程序线程结束后执行。但是,如果我使用Thread.join(),代理移动时接口不会自动更新,因为它正在等待代理完成!
我已经考虑过从代理中禁用接口,然后在代理完成后启用它,但我不确定它是否会起作用,这里最大的问题是代理不应该乱用菜单。
所以,总而言之,我需要一个执行更新接口的线程/绘制代理移动,但该线程不能与启用菜单相同。目前似乎有一个线程同时执行这两个操作。假设这是可能的而不是太复杂。
答案 0 :(得分:5)
我考虑过禁用 然后从代理接口 代理完成后启用它, 但我不确定那会起作用 这里最大的问题是 代理人不应该搞乱 菜单。
您可以让代理调用GUI类中的一个方法,该方法在完成后重新启用菜单。当然,该方法将在EDT上调用适当的Swing方法。
class Agent extends Thread
{
@override
public void run()
{
// run around the room
// finally done
gui.agentIsDone();
}
}
class GUI extends JFrame
{
...
void agentIsDone()
{
SwingUtilities.invokeLater(new Runnable()
{
@override
public void run()
{
menus.setEnabled(true);
}
});
}
}
如果多个代理可以同时运行,则需要在重新启用菜单之前检查是否所有代理都已完成。
答案 1 :(得分:2)
听起来你需要你的代理人发出通知(有人还使用Observer
/ Observable
吗?)到您的界面,清洁已经开始并完成了。您的界面会在收到这些通知后分别致电setEnabled(false)
和setEnabled(true)
。
编辑:这个想法是将菜单的操作与代理的执行分开。即除了菜单项之外,如果您引入另一种方式来启动清洁会发生什么?在这种情况下,您可能仍希望禁用菜单。
答案 2 :(得分:1)
在你的actionPerformed
方法中,只需禁用菜单然后启动线程即可 - 但是你不应该在同一个功能中再次启用菜单。相反,您需要在线程完成时触发菜单的启用。我建议,在代理线程结束时,使用Runnable
调用SwingUtilities.invokeLater()
将重新启用菜单。
答案 3 :(得分:0)
在启动线程之前禁用菜单。完成后,线程需要在控制器上调用某些方法,并在该方法中再次启用菜单。代理人不会搞乱菜单;它只会在控制器完成时通知它。当控制器知道代理已完成时,控制器将启用菜单。
另外,据推测,继承Thread是不好的做法。您应该实现Runnable,然后创建一个以Runnable为目标的Thread,并启动该线程。这样,如果您的代理是Runnable,您可以在自己的线程中运行它,或者在主线程中运行它(通过简单地调用run())或在线程池中运行它。