我使用Java Swing创建了一个桌面应用程序。它需要用户的一些输入,创建配置文件和批处理文件来运行python脚本。许多问题是:
- 当批处理文件正在执行时,我希望GUI处于活动模式
- 应用程序中有一个类似ShowLog的按钮,用于在执行期间检查控制台输出。这应该适用于点击
- 我在GUI中有一个“正在进行的任务”类型的消息,当批处理文件执行完毕时,应该用“任务已完成”替换
- 还有一个“停止”按钮可以强制停止批处理文件的执行。这应该也可以正常工作
(注意:批处理文件的执行需要几个小时才能完成)
有人能想出一些如何实现这些目标的想法吗?
答案 0 :(得分:1)
您似乎意识到,Swing是一个单线程框架,这意味着在事件调度线程的上下文中运行的任何内容都将阻止它更新屏幕或响应用户输入。
基本解决方案是使用Thread
来运行批处理过程,但这会引起UI更新同步化的问题,因为您永远不应该从UI的上下文之外修改或与UI交互。美国东部时间。
更好的解决方案是使用SwingWorker
,它可以让您在后台运行长时间运行的任务,但是为您提供publish
更新和{{1在EDT的上下文中更新,它还为您提供process
方法,该方法在done
方法退出后调用,并在EDT的上下文中调用。
最后,它为您提供了doInBackground
选项 - 但这是问题发生的地方。据推测,您将在辅助线程中读取进程的输入,并且cancel
将使进程在您启动它的同一线程(waiting
)内退出。 SwingWorker
依赖SwingWorker
interrupt
的{{1}}功能,可能不会触发Thread
方法返回。
现在已经阅读了waitFor
文档,Process
确实引发了waitFor
如果当前线程被另一个线程中断 等待,然后等待结束并抛出InterruptedException。
这表明当调用InterruptedException
时,您需要调用done
来检查工作人员是否被取消。如果是,您需要致电isCancelled
上的destroy
并关闭您可能已经投放的所有辅助Process
。
您可以使用额外的Thread
来阅读流程中的输入,并利用其SwingWorker
/ publish
功能来更新日志。
这意味着,您可以启动process
来执行外部流程。这可能是为了响应某些事件而完成的,比如按钮按下。
当调用此worker的SwingWorker
方法时,它将执行外部进程并调用doInBackground
。这将阻止Process#waitFor
方法返回,直到进程退出。
在致电doInBackground
之前,您可以创建另一个Process#waitFor
并将SwingWorker
的{{1}}传递给它。这将允许该工作人员独立处理该过程的输出。然后,您可以使用此功能通过Process
的{{1}} / OutputStream
功能将流程输出发送回EDT,该功能可以添加到{{1} }}
这可以帮助您在处理SwingWorker
时节省很多麻烦。
你需要第二件作品吗?这取决于你希望工人做什么。我倾向于在单独的线程中处理外部进程的所有输出,并允许谁创建进程使用publish
,它将责任隔离一点,并防止IO被锁定永不到达{{1} },但那只是我。
请查看Concurrency in Swing了解详情
答案 1 :(得分:0)
您可以使用Runtime
在java中运行bat文件Runtime.getRuntime().exec("cmd /c start your_batch_file.bat");