用Swing编写灵敏的图形用户界面

2016-02-19 14:34 3 1 收藏

只要你有一台电脑或者手机,都能关注图老师为大家精心推荐的用Swing编写灵敏的图形用户界面,手机电脑控们准备好了吗?一起看过来吧!

【 tulaoshi.com - 编程语言 】

不灵敏的图形用户界面会降低应用程序的可用性。当以下现象出现的时候,我们通常说这个用户界面反应不灵敏。
  
  不响应事件的现象;
  
  没有更新的现象;
  
  !-- frame contents -- !-- /frame contents --  这些现象在很大程度上与事件的处理方法相关,而在编写Swing应用程序的时候,我们几乎必然要编写方法去响应鼠标点击按钮,键盘回车等事件。在这些方法中我们要编写一些代码,在运行时去触发一些动作。常见动作包括查找,更新数据库等。在这篇文章中通过对一个实例的分析,介绍了一些基本概念,常见的错误以及提出了一个解决方案。
  
  event-dispatching thread
  
  我们一定要记住,事件响应方法的代码都是在event-dispatching thread中执行的,除非你启用另一个线程。
  
  那么,什么是event-dispatching thread呢?单一线程规则:一旦一个Swing组件被实现(realized),所有的有可能影响或依靠于这个组件的状态的代码都应该在event-dispatching thread中被执行。而实现一个组件有两种方式:
  
  对顶层组件调用show(), pack(), 或者setVisible(true);
  
  将一个组件加到一个已经被实现的容器中。
  
  单一线程规则的根源是由于Swing组件库的大部分方法是对多线程不安全的。
  
  为了支持单一线程模型,Swing组件库提供了一个专门来完成这些与Swing组件相关的操作的线程,而这一线程就是event-dispatching thread。我们的事件响应方法通常都是由这一线程调用的,除非你自己编写代码来调用这些事件响应方法。在这里初学者经常犯的一个错误就是在事件响应方法中完成过多的与修改组件没有直接联系的代码。其最有可能的效果就是导致组件反应缓慢。比如以下响应按钮事件的代码:
  
  String str = null;
  this.textArea.setText("Please wait...");
  try {
   //do something that is really time consuming
   str = "Hello, world!";
   Thread.sleep(1000L);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  this.textArea.setText(str);
  执行之后的效果就是按钮似乎定住了一段时间,直到Done.出现之后才弹起来。原因就是Swing组件的更新和事件的响应都是在event-dispatching thread中完成的,而事件响应的时候,event-dispatching thread被事件响应方法占据,所以组件不会被更新。而直到事件响应方法退出时才有可能去更新Swing组件。
  
  为了解决这个问题,有人也许会试图通过调用repaint()方法来更新组件:
  
  final String[] str = new String[1];
  this.jTextArea1.setText("Please wait...");
  this.repaint();
  
  try {
   Thread.sleep(1000L);
  }catch(InterruptedException e) {
   e.printStackTrace();
  }
  str[0] = "Done.";
  
  jTextArea1.setText(str[0]);
  但是这一个方法没有起到预期的作用,按钮仍然定住一段时间,在察看了repaint()方法的源代码之后就知道原因了。
  
  PaintEvent e = new PaintEvent(this, PaintEvent.UPDATE,
  new Rectangle(x, y, width, height));
  Toolkit.getEventQueue().postEvent(e);
  repaint()方法实际上是在事件队列里加了一个UPDATE的事件,而没有直接去重画组件,而且这一个事件只能等待当前的事件响应方法结束之后才能被分配。因此只有绕过分配机制直接调用paint方法才能达到目的。
  
  final String[] str = new String[1];
  this.jTextArea1.setText("Please wait...");
  this.paint(this.getGraphics());
  
  try {
   Thread.sleep(1000L);
  }catch(InterruptedException e) {
   e.printStackTrace();
  }
  str[0] = "Done.";
  
  jTextArea1.setText(str[0]);
  这样却是实现了更新,但是还存在着以下的问题。虽然从感觉上,按钮已经弹起来了,但是在Done.出现之前,我们却无法按下这个按钮。可以说按钮还是定住了,只不过定在了弹起的状态。调用重绘方法无法从根本上解决问题,因此我们需要寻求其他的方法。
  
  进入讨论组讨论。   使用多线程
  
  有效的解决方法是使用多线程。首先看一看一个更好的解决方案,这一方案是在参考《Rethinking Swing Threading》的一个程序片段完成的:
  

来源:http://www.tulaoshi.com/n/20160219/1607229.html

延伸阅读
标签: ASP
  从属列表问题(dependent list problem)"的问题时常被提出。问题时常出现于当你有两个以上的选择列表时,一个主列表有若干个选项,你希望当用户选择主列表中的某个选项时,在其他的从属列表中显示相关的选项。你可以通过eXtensible Markup Language(XML)的数据岛(data islands)来实现这一功能,把XML内嵌到你的HTML中。这一结果...
标签: ASP
  把数据库的表数据保存到文件中 我曾答应向你展示如何避免每次请求都要读取数据库和串联成XML字符串的步骤。答案就是把数据库的表数据保存到文件中;这样做有几个好处。读取文件比查询数据库并把记录集格式化成XML要快。这样做也可以简化你的HTML文件,因为你只需在HTML中包含对XML的引用。最后这样做使数据对于客户端来说是透明的...
界面样式 如果使用过基于 Windows 的应用程序,也许已经注意到不是所有用户界面看上去或操作起来都一样。用户界面样式主要有两种:单文档界面 (SDI) 和多文档界面 (MDI)。SDI 界面的一个示例就是 Microsoft Windows 中的WordPad(记事本)应用程序(图 6.1)。在 WordPad 中,只能打开一个文档,想要打开另一个文档时,必须先关上已打...
标签: ASP
  “技术天地”中的《编写ASP图形计数器》一文,详细的说明了如何利用流行的ASP来编写计数器。但是,美中不足的是,如果某个用户反复点击“刷新”按钮,那么计数器还是要不断的增加的,这对网站点击率评比来说是不公平的,也失去了计数器做为正常统计功能的作用。如何在技术上避免这种情况的发生呢? 我认为要防止上网用户连续按下“刷新...
标签: Web开发
网上有很多JavaScript编写的日历,这种日历读取的是本地的时间,可能会不准确。所以想找一个用php编写的,能读取服务器时间的日历,但是一直都找不到合适的,于是我自己尝试着写了一个。代码拷贝框 ?php $mnow=(isset($HTTP_GET_VARS['month']) && intval($HTTP_GET_VARS['month'])0 && intval($HTTP_GET_VARS['month'])13)?intval($HTTP_GET...

经验教程

555

收藏

12
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部