2010-01-30 69 views
3

我有一个小的Java应用程序有效地“尾巴”在ini文件中定义的任意文件集合。我的“LogReader”类扩展了JFrame,并完成了繁重的工作。将文件路径的集合读入向量,然后遍历向量,读取每个文件并将每个文件的最后X行添加到JTabbedPane选项卡上的文本区域。通过点击一个JButton,通过一个ActionListener来启动构建向量并遍历文件的过程。Swing“阻塞”,我想我需要线程,但不知道多少

对文件的读取工作正常(但仍然有效),但是读取20个文件的过程需要一些时间,其中一些文件增长到30MB。为了帮助消磨时间,我决定添加一个进度屏幕,其中显示“正在读取文件#3/26:c:\ logs \ superduper1.log”等。所以我创建了另一个类“SplashScreen”,它也扩展了JFrame,并添加了一个JLabel来指示进度。 SplashScreen类有一个update()方法,它只是在JLabel上执行setText()。

上的JButton的ActionListener的调用RefreshLogs(),它看起来像:

vctFileStrings.clear(); 
tpMain.removeAll(); 
frmSplash.update("Loading Configuration"); //Update the label on the Splash Screen instance 
BuildVectorOfLogs(strConfFile); //Read the collection of files into the vector 
frmSplash.update("Reading Logs"); 
ReadLogs(); //read the files, updating the Splash Screen as we go 

,然后ReadLogs()在矢量迭代,读取文件和建设的TabbedPane。

但我注意到,当从ActionListener中调用RefreshLogs()时,Splash Screen不会更新。但是,如果将RefreshLogs()添加到第一帧的构造函数中,则初始屏幕将按预期工作(每个文件都会更新进度)。经过一些实验和阅读后,我认为我需要创建一个读取文件的工作线程,同时更新事件派发队列中的启动画面。

我的问题是:
- 我的想法是否正确?是否有一些简单的替代方案来实现线程,这将允许我从ActionListener调用的方法更新启动画面?
- 如果使用线程可以最好地完成此操作,那么我需要线程的活动范围是什么?我需要将所有的文件I/O活动放到他们自己的线程中吗?我应该将GUI活动(标签更新)放在他们自己的线程中,以便它们与JButton单击事件分开进行吗?

回答

0

对于您来说,了解如何执行此操作以及如果您使用NetBeans或有权访问NetBeans,请参阅默认的Java Desktop Application template。它创建了一个预先连线的桌面应用程序,并在状态栏中内置了进度栏,当任何“Action”代码执行时它会自动更新。它利用了Action API,它也被预先连线在后台线程中运行。

通过查看自动生成的代码,您将能够正确并轻松地在自己的代码中实施它。

3

是的,你应该把你的时间激烈阅读到一个单独的线程。现在,您在事件分派线程(EDT)中执行所有操作,它将更新您的GUI,但正在忙于读取数据。

您可以使用SwingWorker。看看Using a Swing Worker Thread看起来像你所需要的。

4

我会说:是的,你的想法将大文件的读取卸载到单独的线程是正确的。您不应该在事件调度线程上执行长时间任务,因为在该线程繁忙时,GUI将无响应,并且您的应用程序会感觉很慢。

这听起来像SwingWorker的好例子。此类允许您在单独的线程上执行缓慢的请求(例如磁盘或网络访问),并使用EDT将进度更新反馈给GUI。 SwingWorker关注线程之间切换的所有复杂性。您所要做的就是在适当的地方实施您的业务逻辑。太阳有a tutorial on SwingWorker

相关问题