加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

实战 Groovy(6)- 事件分派线程

发布时间:2020-12-14 16:54:44 所属栏目:大数据 来源:网络整理
导读:Swing 的缺点在于,它期望图形设计师能够应付多线程问题,而这是应该由软件工程师处理的,或者期望软件工程师理解图形设计和易用性问题。 我不可能在短短几段文字中讨论 Swing 应用程序中的线程问题这么复杂的主题。只需指出基本的 Swing 应用程序本质上是单



Swing 的缺点在于,它期望图形设计师能够应付多线程问题,而这是应该由软件工程师处理的,或者期望软件工程师理解图形设计和易用性问题。

我不可能在短短几段文字中讨论 Swing 应用程序中的线程问题这么复杂的主题。只需指出基本的 Swing 应用程序本质上是单线程的。所有活动都在事件分派线程 (EDT) 上进行。当用户抱怨 Swing 应用程序反应迟缓或完全没有反应时,往往是因为某个开发新手在 EDT 上执行长时间的计算密集型的数据库查询或 Web 服务调用 — 这个线程也负责处理屏幕刷新、菜单单击等。我们无意中在搜索按钮的?actionPerformed?处理函数上犯了同样的错误。(您可以看出多么容易犯这种错误)。

好在?javax.swing.SwingUtilities?类提供了几个方便的方法 —?invokeAndWait()?和?invokeLater(),它们可以消除某些线程问题。可以使用这两个方法在 EDT 上同步或异步地执行操作。(关于?SwingUtilities?类的更多信息见?参考资料)。SwingBuilder?让我们很容易调用这两个方法,还提供了第三个选择:可以简便地生成新线程以执行处理时间长的操作。

要想在 EDT 上执行同步调用 (SwingUtilities.invokeAndWait()),可以把调用放在?edt{}?闭包中。要想在 EDT 上执行异步调用 (SwingUtilities.invokeLater()),就把调用放在?doLater{}?闭包中。但是,我想让您体验一下第三个选择:生成新线程来处理Search.byKeyword()?方法调用。为此,需要把代码放在?doOutside{}?闭包中,见清单 14:


清单 14. 使用?doOutside?闭包
				
def searchPanel = {
  swingBuilder.panel(constraints: BorderLayout.NORTH){
    searchField = textField(columns:15)
    button(text:"Search",actionPerformed:{ 
      doOutside{ 
        resultsList.listData = Search.byKeyword(searchField.text)
      }
    } )
  }
}

在像 Gwitter 这样简单的应用程序中,在 EDT 上执行 Web 服务调用很可能没什么不好的效果。但是,如果把这样的代码拿给 Swing 专家看,他们会用鄙视的目光看您,就像是您在快车道里慢慢地开车,或者把车停在商店停车场的残疾人专用车位上了。因为通过使用?SwingBuilder?很容易正确地处理线程,完全没有理由不这么做。

既然解决了线程问题,下面就让这个应用程序更漂亮一些。

给列表增加条纹效果

坦率地说,Gwitter 目前很难看。我要使用一些 HTML 代码做两个简单的改进,让外观和感觉好一些。JLabel?可以显示基本的 HTML。按清单 15 调整 Tweet.groovy 的?toString()?方法。JList?调用?toString()?方法显示结果。


清单 15. 在?toString()?方法中返回 HTML
class Tweet{ String content String published String author String toString(){ //return "${author}: ${content}" return """<html> <body> <p><b><i>${author}:</i></b></p> <p>${content}</p> </body> </html>""" } }

下一个改进略微有点复杂。一种常用的 GUI 技巧是给长的列表或表格加上条纹效果。用不同的颜色显示奇数行和偶数行,这样读者更容易阅读。我在搜索引擎中搜索了?JList stripes,采纳了找到的第一篇文章中的建议。作者建议创建一个定制的DefaultListCellRenderer。我完全赞同他的意见并按原样借用他的示例代码(完整的文章见?参考资料)。

因为 Groovy 语法是 Java 语法的超集,所以可以把 Java 代码复制到 Groovy 文件中,不需要修改。如果有功能全面的构建系统,可以编译 Java 和 Groovy 代码,那么只需把这段代码留在 Java 文件中。但是,通过把代码文件的扩展名改为 .groovy,我可以运行所有未编译的 Gwitter 代码。我再次利用了 Java 语言和 Groovy 之间的无缝集成。可以在 Groovy 应用程序中不加修改地使用任何 Java 解决方案。

创建文件 StripeRenderer.groovy,添加清单 16 中的代码:


清单 16. 创建有条纹效果的?CellRenderer?
import java.awt.*; import javax.swing.*; class StripeRenderer extends DefaultListCellRenderer { public Component getListCellRendererComponent(JList list,Object value,int index,boolean isSelected,boolean cellHasFocus) { JLabel label = (JLabel) super.getListCellRendererComponent(list,value,index,isSelected,cellHasFocus); if(index%2 == 0) { label.setBackground(new Color(230,230,255)); } label.setVerticalAlignment(SwingConstants.TOP); return label; } }

有了?StripeRenderer?类之后,最后需要让?JList?使用它。按清单 17 调整?resultsPanel


清单 17. 在?JList?中添加定制的?CellRenderer?
def resultsPanel = { swingBuilder.scrollPane(constraints: BorderLayout.CENTER){ //resultsList = list() resultsList = list(fixedCellWidth: 380,fixedCellHeight: 75,cellRenderer:new StripeRenderer()) } }

在命令提示上再次输入?groovy Gwitter。搜索?thirstyhead?应该会产生图 16 所示的结果:


图 6. 有条纹效果的结果

?

我可以花更多时间美化 Gwitter 的外观和感觉,但是我希望您对大约 50 行 Swing 代码(当然不包括支持类)所实现的效果印象深刻。

正如本文中指出的,Groovy 并不能降低 Swing 内在的复杂性,但是它可以显著降低语法复杂性。这让您能够留出时间应付更重要的问题。

如果本文引起了您对 Groovy 和 Swing 的兴趣,您应该好好研究一下 Griffon 项目(见?参考资料)。它提供许多优于 Grails 项目的功能和惯例,但是它基于?SwingBuilder?和 Groovy 而不是 Spring MVC 和 Hibernate。这个项目仍然处于早期阶段(到编写本文时最新版本是 0.2),但是它已经很出色了,在 JavaOne 2009 上赢得了 Scripting Bowl for Groovy。另外,它提供的示例项目之一是 Greet,这是一个用 Groovy 实现的完整的 Twitter 客户机。

下一次,我将在 Gwitter 中添加一些必备特性:发布新 Tweet 的功能。在此过程中,您将学习如何处理基本的 HTTP 身份验证、执行 HTTP POST 以及使用与?XmlSlurper?相似的?ConfigSlurper。在此之前,我希望您探索应用 Groovy 的各种可能性。


描述 名字 大小 下载方法
文章示例的源代码 j-groovy09299.zip 24KB HTTP

更新的详细信息请参考 ? java进阶网 ? www.javady.com

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读