使用SwingWorker实现了一个图片在网上搜索和获取搜索结果进行显示的功能。其功能流程图如下:
本工程的包结构如下:
MainFrame.java:为程序的入口,负责界面的布局
ImageInfo.java:为一个Bean,记录图片的描述信息
ImageSearcher.java:图片搜索和返回搜索得到的数据
ImageInfoReaderer.Java:图片信息的渲染器
ImageRetriever.java:返回具体的一张图片
Swing是一个单线程图形库,里面的绝大多数代码不是线程安全的,这意味着它并不是在任何地方都能随便调用的,假若随便使用这些API去更新界面元素如设置值,更新颜色等很可能造成反应不灵敏,卡机等情形。虽然Swing的API不是线程安全,但是其用了其他方式来保障线程安全,那就是Event Queue和EDT,如下图:
Swing将所有的重画更新等操作放在一个EDT里排队,每次只执行一个事件。所以EDT里尽量不要放一些耗时的操作,否则会使其占用大部分的事件而无法响应界面的其它事件从而使界面卡住。在本实验中,其采用的是SwingWorker来解决这个问题,将查找的耗时动作放在SwingWorker中使得查找的时候界面的反应依旧灵敏。如下图所示:
本实验中通过函数getApiKey()来获得配置文件中的API_KEY,用于连接服务器端。接着便是初始化线程,在初始化的时候采用了SwingUtilities.invokeLater的方法,其除了创建MainFrame之外还采用了UIManager来美化界面。如此,便完成了界面的初始化。
接着当输入搜索关键词之后,增加了按键的监听txtSearchKeyPressed(java.awt.event.KeyEventevt),当按下enter键的时候激发事件searchImages(strSearchText,1)函数进行搜索。在searchImage中,首先进行的是检测当前是否有查询进行,如果有则先取消当前操作,然后再重新开始一个新的searcher。Searcher对象是ImageSearcher的一个实例,它继承了SwingWorker使得其可以单独处于一个线程而不在EDT中。在ImageSearcher重写了process()、doInBackground()和done()方法,其中doInBackground() 执行的是图片的搜索,而在done()方法里则是get()获得doInBackground()的return数据,并通过触发一个监听的处理事件函数返回给listModel以显示查找到的图片。
当用户点击一个list的Item的时候则触发函数listImagesValueChanged(javax.swing.event.ListSelectionEventevt)的发生,在该函数里通过调用retrieveImage(String imageUrl)函数来从服务器下载该图片并显示出来。ImageRetriever.java也是继承了SwingWorker类,它也重写了doInBackground()和done()方法,在doInbackground()里调用retrieveImage()函数来获取指定的图片,然后在done()里通过get()方法取得返回值给lblImage控件显示图片。