﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-Swing-随笔分类-Swing</title><link>http://www.blogjava.net/Swing/category/22030.html</link><description>&lt;font size="3"&gt;&lt;br&gt;&lt;font color="#669933"&gt;&lt;em&gt;天行健  君子以自强不息&lt;/em&gt;&lt;/font&gt;&lt;br&gt;&lt;br&gt;&lt;/font&gt;
</description><language>zh-cn</language><lastBuildDate>Sun, 01 Apr 2012 04:34:51 GMT</lastBuildDate><pubDate>Sun, 01 Apr 2012 04:34:51 GMT</pubDate><ttl>60</ttl><item><title>Swing _自定义颜色选择器&amp;颜色选择下拉框</title><link>http://www.blogjava.net/Swing/archive/2010/04/29/319736.html</link><dc:creator>zht</dc:creator><author>zht</author><pubDate>Thu, 29 Apr 2010 14:10:00 GMT</pubDate><guid>http://www.blogjava.net/Swing/archive/2010/04/29/319736.html</guid><wfw:comment>http://www.blogjava.net/Swing/comments/319736.html</wfw:comment><comments>http://www.blogjava.net/Swing/archive/2010/04/29/319736.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/Swing/comments/commentRss/319736.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Swing/services/trackbacks/319736.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Swing_自定义ColorChooser&ColorComboBox<br>&nbsp;&nbsp;<a href='http://www.blogjava.net/Swing/archive/2010/04/29/319736.html'>阅读全文</a><img src ="http://www.blogjava.net/Swing/aggbug/319736.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Swing/" target="_blank">zht</a> 2010-04-29 22:10 <a href="http://www.blogjava.net/Swing/archive/2010/04/29/319736.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>修改JTable默认Copy实现</title><link>http://www.blogjava.net/Swing/archive/2010/03/05/314579.html</link><dc:creator>zht</dc:creator><author>zht</author><pubDate>Fri, 05 Mar 2010 03:34:00 GMT</pubDate><guid>http://www.blogjava.net/Swing/archive/2010/03/05/314579.html</guid><wfw:comment>http://www.blogjava.net/Swing/comments/314579.html</wfw:comment><comments>http://www.blogjava.net/Swing/archive/2010/03/05/314579.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Swing/comments/commentRss/314579.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Swing/services/trackbacks/314579.html</trackback:ping><description><![CDATA[<p><span style="font-size: 10pt; color: #008000">&nbsp;&nbsp; &nbsp;最近有人问，如何在table中Ctrl+C赋值的时候，定制选中的内容。默认情况下是返回value值，但是很多情况下，我们都会定制一些显示，举个例子，取出来的原始位置数据是0，重载renderer以后可能就变成了"右",当我们copy的时候，而我们取到的值仍然是0，而对于客户而言，可能取出"右"可能更有意义，这个时候就需要做一些处理了，如下所示:</span></p>
<p></p>
<div style="padding-right: 5px; padding-left: 4px; font-size: 13px; border-left-color: #cccccc; padding-bottom: 4px; width: 98%; word-break: break-all; padding-top: 4px; background-color: #eeeeee"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008000"><span style="color: #000000">table.getActionMap().put(</span><span style="color: #000000">"</span><span style="color: #000000">copy</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;</span><span style="color: #0000ff">new</span></span><span style="color: #008000"><span style="color: #000000">&nbsp;AbstractAction()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span></span><span style="color: #008000"><span style="color: #000000">&nbsp;actionPerformed(ActionEvent&nbsp;e)&nbsp;{<br />
</span><span style="color: #008000">//</span><span style="color: #008000">至于此处如何处理，就看具体的逻辑了</span></span><span style="color: #008000"><br />
</span><span style="color: #008000"><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;box.getLastSelectedElement();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;column&nbsp;</span><span style="color: #000000">=</span></span><span style="color: #008000"><span style="color: #000000">&nbsp;table.getSelectedColumn();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;row&nbsp;</span><span style="color: #000000">=</span></span><span style="color: #008000"><span style="color: #000000">&nbsp;table.getSelectedRow();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(column&nbsp;</span><span style="color: #000000">!=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">1</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&amp;&amp;</span><span style="color: #000000">&nbsp;row&nbsp;</span><span style="color: #000000">!=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">1</span></span><span style="color: #008000"><span style="color: #000000">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;value&nbsp;</span><span style="color: #000000">=</span></span><span style="color: #008000"><span style="color: #000000">&nbsp;table.getValueAt(row,&nbsp;column);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StringSelection&nbsp;stringSelection&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span></span><span style="color: #008000"><span style="color: #000000">&nbsp;StringSelection(value.toString()+"hello");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Clipboard&nbsp;clipboard&nbsp;</span><span style="color: #000000">=</span></span><span style="color: #008000"><span style="color: #000000">&nbsp;Toolkit.getDefaultToolkit().getSystemClipboard();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;clipboard.setContents(stringSelection,&nbsp;</span><span style="color: #0000ff">null</span></span><span style="color: #000000"><span style="color: #008000">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});</span></span></div>
<p><span style="color: #008000">&nbsp;</span></p>
<img src ="http://www.blogjava.net/Swing/aggbug/314579.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Swing/" target="_blank">zht</a> 2010-03-05 11:34 <a href="http://www.blogjava.net/Swing/archive/2010/03/05/314579.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Swing DayDayUp之六: QQ风格JTextField</title><link>http://www.blogjava.net/Swing/archive/2010/02/09/312402.html</link><dc:creator>zht</dc:creator><author>zht</author><pubDate>Tue, 09 Feb 2010 04:06:00 GMT</pubDate><guid>http://www.blogjava.net/Swing/archive/2010/02/09/312402.html</guid><wfw:comment>http://www.blogjava.net/Swing/comments/312402.html</wfw:comment><comments>http://www.blogjava.net/Swing/archive/2010/02/09/312402.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/Swing/comments/commentRss/312402.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Swing/services/trackbacks/312402.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: QQ风格JTextField&nbsp;&nbsp;<a href='http://www.blogjava.net/Swing/archive/2010/02/09/312402.html'>阅读全文</a><img src ="http://www.blogjava.net/Swing/aggbug/312402.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Swing/" target="_blank">zht</a> 2010-02-09 12:06 <a href="http://www.blogjava.net/Swing/archive/2010/02/09/312402.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JavaGUI应用程序部署</title><link>http://www.blogjava.net/Swing/archive/2010/02/05/312114.html</link><dc:creator>zht</dc:creator><author>zht</author><pubDate>Fri, 05 Feb 2010 07:16:00 GMT</pubDate><guid>http://www.blogjava.net/Swing/archive/2010/02/05/312114.html</guid><wfw:comment>http://www.blogjava.net/Swing/comments/312114.html</wfw:comment><comments>http://www.blogjava.net/Swing/archive/2010/02/05/312114.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/Swing/comments/commentRss/312114.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Swing/services/trackbacks/312114.html</trackback:ping><description><![CDATA[<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp; </span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">JavaGUI应用程序部署<br />
</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt"><br />
JavaGUI程序发布分类</span></span></span><br />
<span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;1)&nbsp; Applet：可以嵌入到浏览器中，通过网页的方式展示给用户</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;2)&nbsp; application ：有两种发布方式</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;&nbsp;&#252; 打包成jar包通过bat的方式运行，或者通过第三方软件打成exe(后续会再详细介绍)</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;&nbsp;&#252; 通过Java Web Start的方式发布到服务器端，通过JNLP运行</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;相对来说第二种方式可能更好一些，免除了更新的麻烦。</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;用applet或者jws的方式发布，大部分都需要数字签名。<br />
</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt"><br />
<br />
为什么要签名</span></span></span><br />
<span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;其实签名不是必须的，如果你的程序只是单纯的绘图，显示，只要不访问网络资源也不访问本地文件，是不用签名的，<br />
&nbsp;但是如果要访问本地或网上资源就必须签名，<br />
&nbsp;比如读取本地文件或者访问数据库，这是由java的沙箱机制决定的，即jvm内部有一组安全检查规则，要通过检查之后才能访问特定资源。</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;如果要突破这个规则，可以有两个方法:</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;1) 修改jre权限文件如下</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;&nbsp;java.policy为grant {<br />
&nbsp;&nbsp;&nbsp;permission java.security.AllPermission;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;};</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;&nbsp;一般权限文件的目录如下C:"Program Files"Java"jre6"lib"security</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;&nbsp;但是修改每个客户端的权限文件，无论从时间还是操作上都是很麻烦的。</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;2)&nbsp; 签名，意思就是告诉用户，这个程序是谁发布的，是不是能信任，如果客户确定，ok，这个applet或者jws就可以访问外部资源了。<br />
<br />
</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt"><br />
如何签名</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;1)首先确保你已经完全安装了Java2的环境，有keytool工具，它位于JDK的bin目录下。这一般不会有问题。</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;2)到Dos状态下，进入你需发布应用程序的jar包所在的目录，运行下面这句话<br />
&nbsp;&nbsp; keytool -genkey -keystore myKeystore -alias jwstest -validity 1000<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 它将会提示你输入用户名、密码等，按照提示随便输入即可，不输入直接回车即可，<br />
&nbsp;&nbsp; 但一定要记住密码。运行结束它将会在当前路径下创建名为myKeystore的文件。</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;3)如果你想查看一下刚才生成的myKeystore文件的内容，可以使用下面这句话：<br />
&nbsp;&nbsp;keytool -list -keystore myKeystore<br />
&nbsp;&nbsp;显示出来应该类似如下：<br />
&nbsp;&nbsp;Keystore type: jks<br />
&nbsp;&nbsp;Keystore provider: SUN<br />
&nbsp;&nbsp;Your keystore contains 1 entry:<br />
&nbsp;&nbsp;jwstest, Tue Nov 23 19:29:32 PST 2001, keyEntry,<br />
&nbsp;&nbsp;Certificate fingerprint (Test):<br />
&nbsp;&nbsp;C3:A9:CD:F3:D3:AC:4D:3F:3C:5B:AF:9E:CF:0D:46:5C</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;4)对你需发布应用程序的jar包进行签名，运行下面这句话：<br />
&nbsp;&nbsp;jarsigner -keystore myKeystore yourtest.jar jwstest<br />
&nbsp;&nbsp;其中yourtest.jar是你的jar包名，你需要修改它，别的就不必修改了。<br />
&nbsp;&nbsp;运行时会提示你输入密码，就是你刚才在生成myKeystore文件时设定的密码。<br />
</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt"><br />
<br />
如果有很多jar包怎么办</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;在开发的过程中很可能会引用到第三方的jar包，而第三方的jar包又可能引用到其它的，所以可能有很多的jar包，需要和applet一起发布，有两个方法<br />
&nbsp;&nbsp;1) 分别打包签名，使用于包比较少，比如只有3、4个的情况<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2) 只 把applet的jar包签名，让用户确认访问授权，applet已经被用户授权，那么就可以在applet里改变安全管理器（SecurityManager）<br />
&nbsp;&nbsp;&nbsp;只需要继承SecurityManager类，创建自己的安全管理器类，然后覆盖checkPermission方法，允许访问任何资源。<br />
&nbsp;&nbsp;&nbsp;在applet的init方法中调用System.setSecurityManager把安全管理器设置为我们自定义的即可。</span></span></span></p>
<p><br />
<span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;class CustomManager extends SecurityManager {<br />
&nbsp;&nbsp;public void checkPermission(Permission perm, Object context) {<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;public void checkPermission(Permission perm) {<br />
&nbsp;&nbsp;}<br />
&nbsp;}<br />
&nbsp; </span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">其它一些相关资料如下</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;JDK中keytool常用命令</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;-genkey&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在用户主目录中创建一个默认文件".keystore",还会产生一个mykey的别名，mykey中包含用户的公钥、私钥和证书 <br />
&nbsp;-alias&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 产生别名<br />
&nbsp;-keystore&nbsp;&nbsp;&nbsp; 指定密钥库的名称(产生的各类信息将不在.keystore文件中<br />
&nbsp;-keyalg&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 指定密钥的算法&nbsp;&nbsp;&nbsp; <br />
&nbsp;-validity&nbsp;&nbsp;&nbsp; 指定创建的证书有效期多少天<br />
&nbsp;-keysize&nbsp;&nbsp;&nbsp;&nbsp; 指定密钥长度<br />
&nbsp;-storepass&nbsp;&nbsp; 指定密钥库的密码<br />
&nbsp;-keypass&nbsp;&nbsp;&nbsp;&nbsp; 指定别名条目的密码<br />
&nbsp;-dname&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 指定证书拥有者信息 例如：&nbsp; "CN=sagely,OU=atr,O=szu,L=sz,ST=gd,C=cn"<br />
&nbsp;-list&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 显示密钥库中的证书信息&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; keytool -list -v -keystore sage -storepass ....<br />
&nbsp;-v&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 显示密钥库中的证书详细信息<br />
&nbsp;-export&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 将别名指定的证书导出到文件&nbsp; keytool -export -alias caroot -file caroot.crt<br />
&nbsp;-file&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 参数指定导出到文件的文件名<br />
&nbsp;-delete&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 删除密钥库中某条目&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; keytool -delete -alias sage -keystore sage<br />
&nbsp;-keypasswd&nbsp;&nbsp; 修改密钥库中指定条目口令&nbsp;&nbsp;&nbsp; keytool -keypasswd -alias sage -keypass .... -new .... -storepass ... -keystore sage<br />
&nbsp;-import&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 将已签名数字证书导入密钥库&nbsp; keytool -import -alias sage -keystore sagely -file sagely.crt <br />
&nbsp;&nbsp;&nbsp;&nbsp; 导入已签名数字证书用keytool -list -v 以后可以明显发现多了认证链长度，并且把整个CA链全部打印出来。</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;Keytool 是安全钥匙与证书的管理工具.它管理一个存储了私有钥匙和验证相应公共钥匙的与它们相关联的X.509 证书链的keystore(相当一个数据库).</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;Keytool 是一个有效的安全钥匙和证书的管理工具. 它能够使用户使用数字签名来管理他们自己的私有/公共钥匙对,管理用来作自我鉴定的相关的证书,管理数据完整性和鉴定服务.它还能使用户在通信时缓存它们的公共钥匙.</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;一个证书是某一实体(个人,公司等)的数字签名,指出其他实体的公共钥匙(或其他信息)的详细的值.当数据被签名后,这个签名信息被用来检验数据的完整性和真实性.完整性指数据没有被修改和篡改,真实性指数据从任何产生和签名的一方真正的传输到达.</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;Keytool 把钥匙和证书储存到一个keystore.默任的实现keystore的是一个文件.它用一个密码保护钥匙.</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;而另外的一个工具jarsigner用keystore中的信息产生或检验Java aRchive(jar文件)中的数字签名.</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;Keystore有两个不同的入口:</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;1.钥匙入口:保存了非常敏感的加密的钥匙信息,并且是用一个保护的格式存储以防止未被授权的访问.以这种形式存储的钥匙是秘密钥匙,或是一个对应证书链中公有钥匙的私有钥匙.</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;2.信任证书入口:包含一个属于其他部分的单一公共钥匙证书.它之所以被称为"信任证书",是因为keystore信任的证书中的公共钥匙真正属于证书所有者的身份识别.</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;Keystore的别名:</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;所有的keystore入口(钥匙和信任证书入口)是通过唯一的别名访问.别名是 不区分大小写的.如别名Hugo和hugo指向同一个keystore入口.</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;可以在加一个入口到keystore的时候使用-genkey参数来产生一个钥匙对(公共钥匙和私有钥匙)时指定别名.也可以用-import参数加一个证书或证书链到信任证书.</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;如:</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;keytool -genkey -alias duke -keypass dukekeypasswd</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;其中duke为别名,dukekeypasswd为duke别名的密码.这行命令的作用是产生一个新的公共/私有钥匙对.</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;假如你想修改密码,可以用:</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;keytool -keypasswd -alias duke -keypass dukekeypasswd -new newpass</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;将旧密码dukekeypasswd改为newpass.</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;Keystore的产生:</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;1.当使用-genkey 或-import或-identitydb命令添加数据到一个keystore,而当这个keystore不存在时,产生一个keystore.默认名是.keystore,存放到user-home目录.</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;2.当用-keystore指定时,将产生指定的keystore.</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;Keystore的实现:</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;Keytool 类位于java.security包下,提供一个非常好的接口去取得和修改一个keystore中的信息. 目前有两个命令行:keytool和jarsinger,一个GUI工具Policy 可以实现keystore.由于keystore是公开的,用户可以用它写一些额外的安全应用程序.</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;Keystore还有一个sun公司提供的內在实现.它把keystore作为一个文件来实现.利用了一个keystore类型(格式)"JKS".它用单独的密码保护每一个私有钥匙.也用可能不同的密码保护整个keystore的完整性.</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;支持的算法和钥匙大小:</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;keytool允许用户指定钥匙对和注册密码服务供应者所提供的签名算法.缺省的钥匙对产生算法是"DSA".假如私有钥匙是"DSA"类型,缺省签名算法是"SHA1withDSA",假如私有钥匙是"RSA"类型,缺省算法是"MD5withRSA".</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;当产生一个DSA钥匙对,钥匙必须在512-1024位之间.对任何算法的缺省钥匙大小是1024位.</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;证书:</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;一个证书是一个实体的数字签名,指出其他实体的公共钥匙有明确的值.</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;1.公共钥匙 :是同一个详细的实体的数字关联,并有意让所有想同这个实体发生信任关系的其他实体知道.公共钥匙用来检验签名;</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;2.数字签名:假如数据已被签名,并用身份存储在一个实体中,一个签名能够证明这个实体知道这个数据.这个数据用实体私有钥匙签名并递交;</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;3.身份:知道实体的方法.在一些系统中身份是公共钥匙,其他系统中可以是从一个X.509名字的邮件地址的Unix UID来的任何东西;</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;4.签名:一个签名用用实体私有钥匙来计算某些加密数据;</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;5.私有钥匙:是一些数字,每一个私有钥匙只能被特定的拥有该私有钥匙的实体知道.私有和公共钥匙存在所有用公共钥匙加密的系统的钥匙对中.一个公共钥匙加密(如DSA),一个私有钥匙与一个正确的公共钥匙通信.私有钥匙用来计算签名.</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;6.实体:一个实体可以是一个人,一个组织,一个程序,一台计算机,一个商业,一个银行,或其他你想信任的东西.</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;Keytool应用实例:</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;1.产生一个keystore:</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;keytool -genkey -alias User(keystore的别名) -keyalg RSA -validity 7 -keystore keystore(指定keystore).</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;运行这个命令,系统提示:</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;Enter keystore password:yourpassword(输入密码)</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;What is your first and last name?</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;[Unknown]: your name(输入你的名字)</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;What is the name of your organizational unit?</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;[Unknown]:your organizational(输入你所在组织单位的名字)</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;What is the name of your organization?</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;[Unknown]:your organization name (输入你所在组织的名字)</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;What is the name of your City or Locality?</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;[Unknown]:your city name(输入所在城市的名字)</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;What is the name of your State or Province?</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;[Unknown]:your provice name(输入所在省份名字)</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;What is the two-letter country code for this unit?</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;[Unknown]:cn(输入国家名字)</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;Is CN=your name, OU=your organizaion, O="your organization name",</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;L=your city name, ST=your province name, C=cn correct?</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;[no]: yes</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;2.检查一个keystore:</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;keytool -list -v -keystore keystore</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;Enter keystore password:your password(输入密码)</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;将显示keystore內容如:</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;Keystore type: jks</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;Keystore provider: SUN</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;Your keystore contains 1 entry</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;Alias name: yourname</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;Creation date: Dec 20, 2001</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;Entry type: keyEntry</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;Certificate chain length: 1</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;Certificate[1]:</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;Owner: CN=yourname, OU=your organization, O="your organization name",</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;L=your city name, ST=your province name, C=CN</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;Issuer: CN=Duke, OU=Java Software, O="Sun Microsystems, Inc.", L=Palo Alto, ST=CA, C=US</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;Serial number: 3c22adc1</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;Valid from: Thu Dec 20 19:34:25 PST 2001 until: Thu Dec 27 19:34:25 PST 2001</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;Certificate fingerprints:</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;MD5: F1:5B:9B:A1:F7:16:CF:25:CF:F4:FF:35:3F:4C:9C:F0</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;SHA1: B2:00:50:DD:B6:CC:35:66:21:45:0F:96:AA:AF:6A:3D:E4:03:7C:74</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;3.输出keystore到一个文件:testkey:</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;keytool -export -alias duke -keystore keystore -rfc -file testkey</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;系统输出:</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;Enter keystore password:your password(输入密码)</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;Certificate stored in file &lt; td&gt;</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;4.输入证书到一个新的truststore:</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;keytool -import -alias dukecert -file testkey -keystore truststore</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;Enter keystore password:your new password.(输入truststore新密码)</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;5.检查truststore:</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;keytool -list -v -keystore truststore</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;系统将显示truststore的信息.</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;现在可以用适当的keystore运行你的应用程序.如:</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;java -Djavax.net.ssl.keyStore=keystore -Djavax.net.ssl.keyStorePassword=password Server</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;和: java -Djavax.net.ssl.trustStore=truststore</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;-Djavax.net.ssl.trustStorePassword=trustword Client</span></span></span></p>
<p><br />
<span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;by </span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp;张涛<br />
&nbsp;&nbsp;&nbsp; zht_dream@hotmail.com</span></span></span></p>
<p><span style="color: #008000"><span style="font-family: 宋体"><span style="font-size: 10pt">&nbsp;</span></span></span></p>
<img src ="http://www.blogjava.net/Swing/aggbug/312114.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Swing/" target="_blank">zht</a> 2010-02-05 15:16 <a href="http://www.blogjava.net/Swing/archive/2010/02/05/312114.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>监听JComponent显示事件</title><link>http://www.blogjava.net/Swing/archive/2010/02/04/312027.html</link><dc:creator>zht</dc:creator><author>zht</author><pubDate>Thu, 04 Feb 2010 14:09:00 GMT</pubDate><guid>http://www.blogjava.net/Swing/archive/2010/02/04/312027.html</guid><wfw:comment>http://www.blogjava.net/Swing/comments/312027.html</wfw:comment><comments>http://www.blogjava.net/Swing/archive/2010/02/04/312027.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/Swing/comments/commentRss/312027.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Swing/services/trackbacks/312027.html</trackback:ping><description><![CDATA[<span style="word-spacing: 0px; font: medium Simsun; text-transform: none; color: rgb(0,0,0); text-indent: 0px; white-space: normal; letter-spacing: normal; border-collapse: separate; orphans: 2; widows: 2; webkit-border-horizontal-spacing: 0px; webkit-border-vertical-spacing: 0px; webkit-text-decorations-in-effect: none; webkit-text-size-adjust: auto; webkit-text-stroke-width: 0px">
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">&nbsp;&nbsp;&nbsp; <span style="font-family: 宋体">很多时候，我们需要在界面初始化以后对程序进行某些设置，举个例子，当界面呈现出来以后，设置下</span>SplitPane<span style="font-family: 宋体">的的百分比</span>(<span style="font-family: 宋体">关于这个为什么必须这么处理请参考</span>java<span style="font-family: 宋体">源代码</span>)<span style="font-family: 宋体">。很容易我们就想到给程序添加</span>ComponentListener<span style="font-family: 宋体">监听，然后在监听中作处理，如下所示</span></span></span></span></span></p>
<span style="font-size: 12pt"><span style="font-size: 10pt">
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">panel.addComponentListener(new ComponentAdapter() {</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public void componentShown(ComponentEvent e) {</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("panel:shown");</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000"><span style="font-family: 宋体">但是并没有和我们想象的那样，当组件在界面上显示出来的时候</span>fire<span style="font-family: 宋体">出</span>componentShown<span style="font-family: 宋体">类型的事件的，下面我们通过研究源代码分析下原因</span></span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000"><span style="font-family: 宋体">首先的问题是在什么地方会</span>fire<span style="font-family: 宋体">出</span>ComponentEvent</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000"><span style="font-family: 宋体">通过查看源代码，我们可以看到实在</span>Component<span style="font-family: 宋体">的</span>show()<span style="font-family: 宋体">方法中</span></span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">ComponentEvent e = new ComponentEvent(this,ComponentEvent.COMPONENT_SHOWN);</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">Toolkit.getEventQueue().postEvent(e);</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000"><span style="font-family: 宋体">具体代码，请参考</span>java<span style="font-family: 宋体">源程序</span></span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000"><span style="font-family: 宋体">也就是说只有在组件调用到</span>setVisible(true)<span style="font-family: 宋体">的时候才会</span>fire<span style="font-family: 宋体">出</span>ComponentEvent</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000"><span style="font-family: 宋体">但是你会发现，即便是我们调用</span>JComponent<span style="font-family: 宋体">的</span>setVisible(true)<span style="font-family: 宋体">，也不会监听到</span>shown<span style="font-family: 宋体">事件</span></span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000"><span style="font-family: 宋体">原因主要是</span>JComponent<span style="font-family: 宋体">重载了</span>setVisible<span style="font-family: 宋体">方法</span></span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-family: 宋体"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">如下</span></span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">public void setVisible(boolean aFlag) {</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(aFlag != isVisible()) {</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super.setVisible(aFlag);</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Container parent = getParent();</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(parent != null) {</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Rectangle r = getBounds();</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parent.repaint(r.x,r.y,r.width,r.height);</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Some (all should) LayoutManagers do not consider components</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// that are not visible. As such we need to revalidate when the</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// visible bit changes.</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;revalidate();</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; text-indent: 21.75pt; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">}</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000"><span style="font-family: 宋体">因为</span>JComponent<span style="font-family: 宋体">的</span>visible<span style="font-family: 宋体">属性默认就是</span>true<span style="font-family: 宋体">，所以不会调用到</span>Component<span style="font-family: 宋体">的</span>setVisible<span style="font-family: 宋体">方法，所以也不会</span>fire<span style="font-family: 宋体">出</span>ComponentEvent<span style="font-family: 宋体">，当然，如果你调用下</span>JComponent<span style="font-family: 宋体">的</span>setVisible(false)+setVisible(true)<span style="font-family: 宋体">是会</span>fire<span style="font-family: 宋体">出</span>ComponentEvent.COMPONENT_SHOWN<span style="font-family: 宋体">事件的，（但是在里面很可能得不到当前组件的大小信息或者不能</span>SplitPane<span style="font-family: 宋体">设置分割比例，因为这个时候界面还没有初始化），而且如果是</span>JFrame<span style="font-family: 宋体">，</span>JDialog<span style="font-family: 宋体">，</span>JApplet<span style="font-family: 宋体">等也是没问题的，因为他们调用的都是</span>Component<span style="font-family: 宋体">的</span>setVisible<span style="font-family: 宋体">方法</span>(<span style="font-family: 宋体">所以给这些顶层组件添加</span>ComponentListener<span style="font-family: 宋体">是没有问题的，都会监听到</span>)</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000"><span style="font-family: 宋体">如果不想使用上述方法，还有另外一种方式就是添加</span>HierarchyListener<span style="font-family: 宋体">监听，因为当顶层组件</span>(JFrame,JDialog<span style="font-family: 宋体">等</span>)setVisible(true)<span style="font-family: 宋体">界面显示的时候，里面都会</span>fire<span style="font-family: 宋体">出</span>HierarchyEvent<span style="font-family: 宋体">，具体代码如下</span>(<span style="font-family: 宋体">详细代码请参考</span>Component<span style="font-family: 宋体">的</span>show()<span style="font-family: 宋体">方法</span>)</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED,</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this, parent,</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HierarchyEvent.SHOWING_CHANGED,</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000"><span style="font-family: 宋体">而</span>createHierarchyEvents<span style="font-family: 宋体">方法会在每个组件上</span>fire<span style="font-family: 宋体">出</span>HierarchyEvent<span style="font-family: 宋体">，至于具体细节，有时间的可以</span>dubug<span style="font-family: 宋体">下，具体的解决方法如下</span></span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;panel.addHierarchyListener(new HierarchyListener() {</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public void hierarchyChanged(HierarchyEvent e) {</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ((e.getChangeFlags() &amp; HierarchyEvent.SHOWING_CHANGED) != 0) {</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (e.getComponent().isShowing()) {</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(panel.getBounds());</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("panel:hshow");</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else {</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("panel:hhide");</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></span></span></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 6px; margin: 0px; padding-top: 6px"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="font-size: 12pt"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});</span></span></span></span></p>
</span></span></span>测试代码如下<br />
<div style="padding-right: 5px; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left-color: #cccccc; width: 98%; word-break: break-all; padding-top: 4px; background-color: #eeeeee; "><img id="Codehighlighter1_18_1111_Open_Image" onclick="this.style.display='none'; Codehighlighter1_18_1111_Open_Text.style.display='none'; Codehighlighter1_18_1111_Closed_Image.style.display='inline'; Codehighlighter1_18_1111_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" alt="" /><img id="Codehighlighter1_18_1111_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_18_1111_Closed_Text.style.display='none'; Codehighlighter1_18_1111_Open_Image.style.display='inline'; Codehighlighter1_18_1111_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" alt="" /><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Test&nbsp;</span><span id="Codehighlighter1_18_1111_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif" alt="" /></span><span id="Codehighlighter1_18_1111_Open_Text"><span style="color: #000000">{<br />
<img id="Codehighlighter1_60_77_Open_Image" onclick="this.style.display='none'; Codehighlighter1_60_77_Open_Text.style.display='none'; Codehighlighter1_60_77_Closed_Image.style.display='inline'; Codehighlighter1_60_77_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><img id="Codehighlighter1_60_77_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_60_77_Closed_Text.style.display='none'; Codehighlighter1_60_77_Open_Image.style.display='inline'; Codehighlighter1_60_77_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;main(String[]&nbsp;args)&nbsp;</span><span id="Codehighlighter1_60_77_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif" alt="" /></span><span id="Codehighlighter1_60_77_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Test();<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img id="Codehighlighter1_95_1109_Open_Image" onclick="this.style.display='none'; Codehighlighter1_95_1109_Open_Text.style.display='none'; Codehighlighter1_95_1109_Closed_Image.style.display='inline'; Codehighlighter1_95_1109_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><img id="Codehighlighter1_95_1109_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_95_1109_Closed_Text.style.display='none'; Codehighlighter1_95_1109_Open_Image.style.display='inline'; Codehighlighter1_95_1109_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;Test()&nbsp;</span><span id="Codehighlighter1_95_1109_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif" alt="" /></span><span id="Codehighlighter1_95_1109_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">final</span><span style="color: #000000">&nbsp;JPanel&nbsp;panel&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;JPanel();<br />
<img id="Codehighlighter1_186_327_Open_Image" onclick="this.style.display='none'; Codehighlighter1_186_327_Open_Text.style.display='none'; Codehighlighter1_186_327_Closed_Image.style.display='inline'; Codehighlighter1_186_327_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><img id="Codehighlighter1_186_327_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_186_327_Closed_Text.style.display='none'; Codehighlighter1_186_327_Open_Image.style.display='inline'; Codehighlighter1_186_327_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;panel.addComponentListener(</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;ComponentAdapter()&nbsp;</span><span id="Codehighlighter1_186_327_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif" alt="" /></span><span id="Codehighlighter1_186_327_Open_Text"><span style="color: #000000">{<br />
<img id="Codehighlighter1_236_323_Open_Image" onclick="this.style.display='none'; Codehighlighter1_236_323_Open_Text.style.display='none'; Codehighlighter1_236_323_Closed_Image.style.display='inline'; Codehighlighter1_236_323_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><img id="Codehighlighter1_236_323_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_236_323_Closed_Text.style.display='none'; Codehighlighter1_236_323_Open_Image.style.display='inline'; Codehighlighter1_236_323_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;componentShown(ComponentEvent&nbsp;e)&nbsp;</span><span id="Codehighlighter1_236_323_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif" alt="" /></span><span id="Codehighlighter1_236_323_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(panel.getBounds());<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">panel:shown</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000">);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;panel.setVisible(false);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;panel.setVisible(true);</span><span style="color: #008000"><br />
<img id="Codehighlighter1_445_776_Open_Image" onclick="this.style.display='none'; Codehighlighter1_445_776_Open_Text.style.display='none'; Codehighlighter1_445_776_Closed_Image.style.display='inline'; Codehighlighter1_445_776_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><img id="Codehighlighter1_445_776_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_445_776_Closed_Text.style.display='none'; Codehighlighter1_445_776_Open_Image.style.display='inline'; Codehighlighter1_445_776_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;panel.addHierarchyListener(</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;HierarchyListener()&nbsp;</span><span id="Codehighlighter1_445_776_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif" alt="" /></span><span id="Codehighlighter1_445_776_Open_Text"><span style="color: #000000">{<br />
<img id="Codehighlighter1_497_772_Open_Image" onclick="this.style.display='none'; Codehighlighter1_497_772_Open_Text.style.display='none'; Codehighlighter1_497_772_Closed_Image.style.display='inline'; Codehighlighter1_497_772_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><img id="Codehighlighter1_497_772_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_497_772_Closed_Text.style.display='none'; Codehighlighter1_497_772_Open_Image.style.display='inline'; Codehighlighter1_497_772_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;hierarchyChanged(HierarchyEvent&nbsp;e)&nbsp;</span><span id="Codehighlighter1_497_772_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif" alt="" /></span><span id="Codehighlighter1_497_772_Open_Text"><span style="color: #000000">{<br />
<img id="Codehighlighter1_567_767_Open_Image" onclick="this.style.display='none'; Codehighlighter1_567_767_Open_Text.style.display='none'; Codehighlighter1_567_767_Closed_Image.style.display='inline'; Codehighlighter1_567_767_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><img id="Codehighlighter1_567_767_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_567_767_Closed_Text.style.display='none'; Codehighlighter1_567_767_Open_Image.style.display='inline'; Codehighlighter1_567_767_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;((e.getChangeFlags()&nbsp;</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;HierarchyEvent.SHOWING_CHANGED)&nbsp;</span><span style="color: #000000">!=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">)&nbsp;</span><span id="Codehighlighter1_567_767_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif" alt="" /></span><span id="Codehighlighter1_567_767_Open_Text"><span style="color: #000000">{<br />
<img id="Codehighlighter1_608_701_Open_Image" onclick="this.style.display='none'; Codehighlighter1_608_701_Open_Text.style.display='none'; Codehighlighter1_608_701_Closed_Image.style.display='inline'; Codehighlighter1_608_701_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><img id="Codehighlighter1_608_701_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_608_701_Closed_Text.style.display='none'; Codehighlighter1_608_701_Open_Image.style.display='inline'; Codehighlighter1_608_701_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(e.getComponent().isShowing())&nbsp;</span><span id="Codehighlighter1_608_701_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif" alt="" /></span><span id="Codehighlighter1_608_701_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(panel.getBounds());<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">panel:hshow</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img id="Codehighlighter1_713_761_Open_Image" onclick="this.style.display='none'; Codehighlighter1_713_761_Open_Text.style.display='none'; Codehighlighter1_713_761_Closed_Image.style.display='inline'; Codehighlighter1_713_761_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><img id="Codehighlighter1_713_761_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_713_761_Closed_Text.style.display='none'; Codehighlighter1_713_761_Open_Image.style.display='inline'; Codehighlighter1_713_761_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;</span><span id="Codehighlighter1_713_761_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif" alt="" /></span><span id="Codehighlighter1_713_761_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">panel:hhide</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000">);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JFrame&nbsp;frame&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;JFrame();<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img id="Codehighlighter1_865_963_Open_Image" onclick="this.style.display='none'; Codehighlighter1_865_963_Open_Text.style.display='none'; Codehighlighter1_865_963_Closed_Image.style.display='inline'; Codehighlighter1_865_963_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><img id="Codehighlighter1_865_963_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_865_963_Closed_Text.style.display='none'; Codehighlighter1_865_963_Open_Image.style.display='inline'; Codehighlighter1_865_963_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;frame.addComponentListener(</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;ComponentAdapter()&nbsp;</span><span id="Codehighlighter1_865_963_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif" alt="" /></span><span id="Codehighlighter1_865_963_Open_Text"><span style="color: #000000">{<br />
<img id="Codehighlighter1_915_959_Open_Image" onclick="this.style.display='none'; Codehighlighter1_915_959_Open_Text.style.display='none'; Codehighlighter1_915_959_Closed_Image.style.display='inline'; Codehighlighter1_915_959_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><img id="Codehighlighter1_915_959_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_915_959_Closed_Text.style.display='none'; Codehighlighter1_915_959_Open_Image.style.display='inline'; Codehighlighter1_915_959_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;componentShown(ComponentEvent&nbsp;e)&nbsp;</span><span id="Codehighlighter1_915_959_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif" alt="" /></span><span id="Codehighlighter1_915_959_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">frame:shown</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000">);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;frame.setContentPane(panel);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;frame.setSize(</span><span style="color: #000000">500</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">400</span><span style="color: #000000">);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;frame.setVisible(</span><span style="color: #0000ff">true</span><span style="color: #000000">);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" alt="" />}</span></span></div>
<br />
<img src ="http://www.blogjava.net/Swing/aggbug/312027.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Swing/" target="_blank">zht</a> 2010-02-04 22:09 <a href="http://www.blogjava.net/Swing/archive/2010/02/04/312027.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Swing DayDayUP之五：带标题栏右键菜单</title><link>http://www.blogjava.net/Swing/archive/2009/10/18/298751.html</link><dc:creator>zht</dc:creator><author>zht</author><pubDate>Sun, 18 Oct 2009 07:26:00 GMT</pubDate><guid>http://www.blogjava.net/Swing/archive/2009/10/18/298751.html</guid><wfw:comment>http://www.blogjava.net/Swing/comments/298751.html</wfw:comment><comments>http://www.blogjava.net/Swing/archive/2009/10/18/298751.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Swing/comments/commentRss/298751.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Swing/services/trackbacks/298751.html</trackback:ping><description><![CDATA[<p><span style="color: #008000">标题位置可以分别设置为上下左右，4个位置。如下图所示:</span></p>
<p><span style="color: #008000"><img alt="" src="http://www.blogjava.net/images/blogjava_net/swing/blog/t.png" width="67" height="157" /><img alt="" src="http://www.blogjava.net/images/blogjava_net/swing/blog/b.png" width="66" height="155" /><img alt="" src="http://www.blogjava.net/images/blogjava_net/swing/blog/r.png" width="96" height="127" /><img alt="" src="http://www.blogjava.net/images/blogjava_net/swing/blog/r.png" width="96" height="127" /><br />
</span></p>
<p><span style="color: #008000">/**<br />
* Title PopupMenu<br />
* <br />
* @author zhangtao<br />
*<br />
* Msn &amp; Mail: zht_dream@hotmail.com<br />
*/<br />
public class ZHTPopupMenu extends JPopupMenu { </span></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp; public static final int POSITION_TOP = 1;<br />
&nbsp;&nbsp;&nbsp; public static final int POSITION_BOTTOM = 2;<br />
&nbsp;&nbsp;&nbsp; public static final int POSITION_LEFT = 3;<br />
&nbsp;&nbsp;&nbsp; public static final int POSITION_RIGHT = 4; </span></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp; private int titleSize = 30;<br />
&nbsp;&nbsp;&nbsp; private Color titleColor = Color.BLACK;<br />
&nbsp;&nbsp;&nbsp; private Color titleFillColor = Color.WHITE;<br />
&nbsp;&nbsp;&nbsp; private boolean titleGradient = true;<br />
&nbsp;&nbsp;&nbsp; private Color titleGradientColor = new Color(0, 50, 50);<br />
&nbsp;&nbsp;&nbsp; private Font titleFont = new Font("Dialog", Font.BOLD, 12);<br />
&nbsp;&nbsp;&nbsp; private int titlePosition = POSITION_LEFT;<br />
&nbsp;&nbsp;&nbsp; private int titleGap = 5; </span></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp; public ZHTPopupMenu() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super();<br />
&nbsp;&nbsp;&nbsp; } </span></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp; public ZHTPopupMenu(String label) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super(label);<br />
&nbsp;&nbsp;&nbsp; } </span></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp; @Override<br />
&nbsp;&nbsp;&nbsp; public Insets getInsets() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Insets insets = (Insets) super.getInsets().clone();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch (titlePosition) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case POSITION_TOP:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; insets.top += titleSize;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case POSITION_BOTTOM:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; insets.bottom += titleSize;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case POSITION_LEFT:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; insets.left += titleSize;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case POSITION_RIGHT:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; insets.right += titleSize;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return insets;<br />
&nbsp;&nbsp;&nbsp; } </span></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp; @Override<br />
&nbsp;&nbsp;&nbsp; protected void paintComponent(Graphics g) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super.paintComponent(g);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Graphics2D g2d = (Graphics2D) g.create();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dimension size = this.getSize();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GradientPaint paint;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g2d.setColor(titleFillColor);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String text = this.getLabel();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int len = 0;//text.length();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (text != null &amp;&amp; text.trim().length() &gt; 0) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; len = text.length();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; boolean hasEN = false;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; len; i++) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (isEN(text.charAt(i))) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hasEN = true;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JLabel label = new JLabel(text);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; label.setFont(titleFont);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; label.setForeground(titleColor);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dimension labelSize = label.getPreferredSize();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch (titlePosition) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case POSITION_TOP: {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (titleGradient) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; paint = new GradientPaint(0, 0, titleFillColor, size.width, titleSize, titleGradientColor);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g2d.setPaint(paint);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g2d.fillRect(0, 0, size.width, titleSize);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (len != 0) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ZHTUtils.paintComponent(g2d, label, this, titleGap, titleGap, labelSize.width, labelSize.height);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case POSITION_BOTTOM: {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (titleGradient) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; paint = new GradientPaint(0, size.height - titleSize, titleFillColor, size.width, size.height, titleGradientColor);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g2d.setPaint(paint);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g2d.fillRect(0, size.height - titleSize, size.width, titleSize);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (len != 0) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ZHTUtils.paintComponent(g2d, label, this, titleGap, size.height - titleGap - labelSize.height, labelSize.width, labelSize.height);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case POSITION_LEFT: {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (titleGradient) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; paint = new GradientPaint(0, 0, titleFillColor, titleSize, size.height, titleGradientColor);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g2d.setPaint(paint);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g2d.fillRect(0, 0, titleSize, size.height);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (len != 0) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (hasEN) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g2d.rotate(90 * Math.PI / 180, titleGap, titleGap);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ZHTUtils.paintComponent(g2d, label, this, titleGap, titleGap - labelSize.height, labelSize.width, labelSize.height);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int sum = 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; len; i++) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; label.setText(text.charAt(i) + "");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; labelSize = label.getPreferredSize();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ZHTUtils.paintComponent(g2d, label, this, titleGap, sum, labelSize.width, labelSize.height);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sum += labelSize.height;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case POSITION_RIGHT: {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (titleGradient) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; paint = new GradientPaint(size.width - titleSize, 0, titleFillColor, size.width, size.height, titleGradientColor);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g2d.setPaint(paint);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g2d.fillRect(size.width - titleSize, 0, titleSize, size.height);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (len != 0) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (hasEN) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g2d.rotate(90 * Math.PI / 180, size.width - titleSize + titleGap, titleGap);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ZHTUtils.paintComponent(g2d, label, this, size.width - titleSize + titleGap, titleGap - labelSize.height, labelSize.width, labelSize.height);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int sum = 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; len; i++) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; label.setText(text.charAt(i) + "");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; labelSize = label.getPreferredSize();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ZHTUtils.paintComponent(g2d, label, this, size.width - titleGap - labelSize.width, sum, labelSize.width, labelSize.height);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sum += labelSize.height;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; } </span></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp; public static boolean isEN(char cn) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte[] bytes = (String.valueOf(cn)).getBytes();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (bytes == null || bytes.length &gt; 2 || bytes.length &lt;= 0) { // 错误&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (bytes.length == 1) { // 英文字符&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (bytes.length == 2) { // 中文字符&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<br />
&nbsp;&nbsp;&nbsp; } </span></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp; public int getTitleSize() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return titleSize;<br />
&nbsp;&nbsp;&nbsp; } </span></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp; public void setTitleSize(int titleSize) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.titleSize = titleSize;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.repaint();<br />
&nbsp;&nbsp;&nbsp; } </span></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp; public Color getTitleColor() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return titleColor;<br />
&nbsp;&nbsp;&nbsp; } </span></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp; public void setTitleColor(Color titleColor) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.titleColor = titleColor;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.repaint();<br />
&nbsp;&nbsp;&nbsp; } </span></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp; public Color getTitleFillColor() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return titleFillColor;<br />
&nbsp;&nbsp;&nbsp; } </span></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp; public void setTitleFillColor(Color titleFillColor) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.titleFillColor = titleFillColor;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.repaint();<br />
&nbsp;&nbsp;&nbsp; } </span></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp; public boolean isTitleGradient() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return titleGradient;<br />
&nbsp;&nbsp;&nbsp; } </span></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp; public void setTitleGradient(boolean titleGradient) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.titleGradient = titleGradient;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.repaint();<br />
&nbsp;&nbsp;&nbsp; } </span></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp; public Color getTitleGradientColor() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return titleGradientColor;<br />
&nbsp;&nbsp;&nbsp; } </span></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp; public void setTitleGradientColor(Color titleGradientColor) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.titleGradientColor = titleGradientColor;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.repaint();<br />
&nbsp;&nbsp;&nbsp; } </span></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp; public Font getTitleFont() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return titleFont;<br />
&nbsp;&nbsp;&nbsp; } </span></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp; public void setTitleFont(Font titleFont) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.titleFont = titleFont;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.repaint();<br />
&nbsp;&nbsp;&nbsp; } </span></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp; public int getTitlePosition() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return titlePosition;<br />
&nbsp;&nbsp;&nbsp; } </span></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp; public void setTitlePosition(int titlePosition) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.titlePosition = titlePosition;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.repaint();<br />
&nbsp;&nbsp;&nbsp; } </span></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp; public int getTitleGap() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return titleGap;<br />
&nbsp;&nbsp;&nbsp; } </span></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp; public void setTitleGap(int titleGap) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.titleGap = titleGap;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.repaint();<br />
&nbsp;&nbsp;&nbsp; }<br />
}&nbsp;</span></p>
 <img src ="http://www.blogjava.net/Swing/aggbug/298751.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Swing/" target="_blank">zht</a> 2009-10-18 15:26 <a href="http://www.blogjava.net/Swing/archive/2009/10/18/298751.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Swing可视化开发工具</title><link>http://www.blogjava.net/Swing/archive/2009/08/06/290164.html</link><dc:creator>zht</dc:creator><author>zht</author><pubDate>Thu, 06 Aug 2009 14:12:00 GMT</pubDate><guid>http://www.blogjava.net/Swing/archive/2009/08/06/290164.html</guid><wfw:comment>http://www.blogjava.net/Swing/comments/290164.html</wfw:comment><comments>http://www.blogjava.net/Swing/archive/2009/08/06/290164.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.blogjava.net/Swing/comments/commentRss/290164.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Swing/services/trackbacks/290164.html</trackback:ping><description><![CDATA[<p><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: red"><span style="color: #008000"><span style="font-size: 12pt">对于刚接触Swing的开发人员，由于水平所限，需要一个可视化的开发工具，来辅助理解学习和开发。也有时候是工作紧迫，需要可视化工具来提高工作效率，节省宝贵的时间。</span></span></span></span></span></p>
<p><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: red"><span style="color: #008000"><span style="font-size: 12pt">在此介绍下，如何可视化开发Swing组件。现在Java主流的两款开发工具NetBeans和Eclipse都提供了可视化的功能。</span></span></span></span></span></p>
<p><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: red"><span style="color: #008000"><span style="font-size: 12pt">一、NetBeans<br />
这个无需多言，Sun官方推荐的Swing开发工具，自身已经集成了可视化工具。<br />
下载地址：<br />
http://www.netbeans.org/downloads/index.html</span></span></span></span></span></p>
<p><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: red"><span style="color: #008000"><span style="font-size: 12pt">二、Eclipse<br />
Eclipse本身不提供可视化功能，需要插件来辅助。<br />
我了解到的，比较常用的插件有两种<br />
1、Visual Editor&nbsp; 简称VE<br />
关于安装 请参考<br />
http://wiki.eclipse.org/VE/Installing/Archived</span></span></span></span></span></p>
<p><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: red"><span style="color: #008000"><span style="font-size: 12pt">说明如下:<br />
VE Installation<br />
Make sure eclipse is close. <br />
Go to http://sourceforge.net/project/showfiles.php?group_id=131065&amp;package_id=154855 <br />
Click "Visual Editor patched as in bug 202562" <br />
Click org.eclipse.visualeditor-1.3.0.200709121813.zip <br />
Unpack the .zip file somewhere <br />
In that extracted folder, there is an " org.eclipse.visualeditor-1.3.0.200709121813" subdir, copy what's in that directory to your eclipse installation dir, say yes if prompted to overwrite. <br />
Open eclipse again and go to Window-&gt;Preferences-&gt;Java. If after expanding 'Java' you see Visual Editor at the bottom, then you are good to go. </span></span></span></span></span></p>
<p><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: red"><span style="color: #008000"><span style="font-size: 12pt">下载地址<br />
http://sourceforge.net/projects/easyeclipse/files/Various%20Patches/Visual%20Editor%20patched%20as%20in%20bug%20202562/org.eclipse.visualeditor-1.3.0.200709121813-2.zip/download</span></span></span></span></span></p>
<p><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: red"><span style="color: #008000"><span style="font-size: 12pt">2、jigloo<br />
这个以前用过，感觉还可以。<br />
官方网站是<br />
http://cloudgarden.com/jigloo/</span></span></span></span></span></p>
<p><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: red"><span style="color: #008000"><span style="font-size: 12pt">下载网址<br />
http://cloudgarden.com/jigloo/dnld_redirect.html</span></span></span></span></span></p>
<p><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: red"><span style="color: #008000"><span style="font-size: 12pt">安装说明<br />
Please note: if you have installed 4.0 RC1 or RC2 you will need to delete these folders from the plugins and features folders in eclipse before installing version 4.0.<br />
Alternatively, you can download the zip file from here. Unzip it into the eclipse folder so that the structure is eclipse/plugins/com.cloudgarden.jigloo_4.0.0</span></span></span></span></span></p>
<p><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: red"><span style="color: #008000"><span style="font-size: 12pt">&nbsp;</span></span></span></span></span></p>
<p><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: red"><span style="color: #008000"><span style="font-size: 12pt">安装都很简单，建议使用link的方式来安装Eclipse插件，方便插件管理，如下所示:<br />
解压yourplugin.zip到任意目录下，比如D:\eclipseplugins\yourplugin。<br />
在Eclipse的目录下有个links文件夹，在里面新建文件，命名为anyname.link，编辑此文件，加入如下内容并保存。path = D:/eclipseplugins/yourplugin<br />
详细使用，请自行搜索。</span></span></span></span></span></p>
<p><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: red"><span style="color: #008000"><span style="font-size: 12pt">其它还有</span></span></span></span></span></p>
<p><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: red"><span style="color: #008000"><span style="font-size: 12pt"><a href="http://www.jformdesigner.com/" style="color: #002c99; text-decoration: none; "></a></span></span></span></span></span></p>
<span style="font-size: 10pt; ">
<p><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: red"><span style="color: #008000"><span style="font-size: 12pt"><a href="http://www.jformdesigner.com/" style="color: #002c99; text-decoration: none; ">jformdesigner</a></span></span></span></span></span></p>
<p><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: red"><span style="color: #008000">官方网址：<span style="font-size: 16px; "><a href="http://www.jformdesigner.com/">http://www.jformdesigner.com/</a></span></span></span></span></span></p>
<p><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: red"><span style="color: #008000"><br />
</span></span></span></span></p>
<p><font color="#008000" size="3"><span style="font-size: 13px;">Visual Swing Designer for Eclipse</span></font></p>
<p><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: red"><span style="color: #008000"><span style="font-size: 12pt">开源网址：&nbsp;<span style="color: #000000; font-size: medium; "><a href="http://code.google.com/p/visualswing4eclipse/">http://code.google.com/p/visualswing4eclipse/</a></span></span></span></span></span></span></p>
<p><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: red"><span style="color: #008000"><span style="font-size: 12pt"><br />
</span></span></span></span></span></p>
<p><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: red"><span style="color: #008000"><span style="font-size: 12pt">WindowBuilder</span></span></span></span></span></p>
<p><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: red"><span style="color: #008000"><span style="font-size: 12pt">官方网址：<a href="http://www.instantiations.com/windowbuilder/">http://www.instantiations.com/windowbuilder/</a></span></span></span></span></span></p>
</span>
<p><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: red"><span style="color: #008000"><span style="font-size: 12pt"><span style="color: #000000; font-size: medium; "><a href="http://code.google.com/p/visualswing4eclipse/"></a></span></span></span></span></span></span></p>
<p><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: red"><span style="color: #008000"><span style="font-size: 12pt">附<br />
使用可视化工具拖拽编写Swing程序，一定要注意变量名和代码的可读性，否则代码非常让人崩溃。</span></span></span></span></span></p>
<img src ="http://www.blogjava.net/Swing/aggbug/290164.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Swing/" target="_blank">zht</a> 2009-08-06 22:12 <a href="http://www.blogjava.net/Swing/archive/2009/08/06/290164.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Swing DayDayUP之四: Swing 酷炫文字</title><link>http://www.blogjava.net/Swing/archive/2009/07/16/287022.html</link><dc:creator>zht</dc:creator><author>zht</author><pubDate>Thu, 16 Jul 2009 12:31:00 GMT</pubDate><guid>http://www.blogjava.net/Swing/archive/2009/07/16/287022.html</guid><wfw:comment>http://www.blogjava.net/Swing/comments/287022.html</wfw:comment><comments>http://www.blogjava.net/Swing/archive/2009/07/16/287022.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/Swing/comments/commentRss/287022.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Swing/services/trackbacks/287022.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 使用TextLayout和clip实现字体酷炫效果&nbsp;&nbsp;<a href='http://www.blogjava.net/Swing/archive/2009/07/16/287022.html'>阅读全文</a><img src ="http://www.blogjava.net/Swing/aggbug/287022.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Swing/" target="_blank">zht</a> 2009-07-16 20:31 <a href="http://www.blogjava.net/Swing/archive/2009/07/16/287022.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Swing DayDayUP之三:Swing组件层次结构介绍</title><link>http://www.blogjava.net/Swing/archive/2009/07/08/285979.html</link><dc:creator>zht</dc:creator><author>zht</author><pubDate>Wed, 08 Jul 2009 14:49:00 GMT</pubDate><guid>http://www.blogjava.net/Swing/archive/2009/07/08/285979.html</guid><wfw:comment>http://www.blogjava.net/Swing/comments/285979.html</wfw:comment><comments>http://www.blogjava.net/Swing/archive/2009/07/08/285979.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/Swing/comments/commentRss/285979.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Swing/services/trackbacks/285979.html</trackback:ping><description><![CDATA[<span style="color: #0fa418">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一直想写篇关于Swing体系结构的文章，不过一直不敢下手，怕理解的有偏差，最近看了下这方面的资料，记录下，Swing的整体组织结构如下图所示。<br />
</span>
<div align="center"><span style="color: #0fa418"><img height="650" alt="" src="http://www.blogjava.net/images/blogjava_net/swing/blog/structure.png" width="729" border="0" /></span></div>
<br />
<span style="color: #0fa418">Swing程序要呈现出来，肯定要将组件放到JFrame,JDialog,JApplet,JWindow这几个容器组件中，这些顶层容器组件，有一个共同的结构，如上图所示，都有一个JRootPane面板来承载着所有要显示的组件。JRootPane又有以下部分组成：<br />
1、GlassPane<br />
2、JLayeredPane<br />
&nbsp;(1)ContentPane<br />
&nbsp;(2)JMenuBar<br />
其中JRootPanel中的RootLayout对以上几部分进行布局，关于这点可以参考Java的API文档和java源码，里面有详细的说明。<br />
这里想要说的一点是，JRootPane并不是只能放在这些顶层容器中的，你也可以放在一般的组件，比如JPanel中，这样Panel就有了层次结构，可以再其不同的层次上放置组件，这个后边还会再讲一下。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 写这篇文章，并不是为了讲Swing的这个架构，主要是想通过讲述这个架构，给大家介绍些开发过程中用的技巧。<br />
GlassPanel这个可能大家都了解了，比如，可以模拟Eclipse中Tab页签的拖拽效果，当处理一些比较费时的操作，比如加载数据时，可以用来遮罩面板，一方面可以防止用户重复操作，另一方面可以用来显示进度。不过有一点限制就是每个顶层容器中GlassPanel只能有一个(其实像上面提到的，如果一个面板中的组件都有一个JRootPane来承载组件，其实在一个程序中GlassPane也是可以有多个的，通过这个，GlassPanel和JLayeredPane几乎可以达到相同的效果)。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JLayeredPane有了深度的概念，一般的Layout在JLayeredPane是不适用的。一个Integer来标示组件在JLayeredPane中的深度，这个值越大，就会显示在越上面。JLayeredPane还有一个同层的上下关系，这个可以参考API或者源代码。重要的一点是JLayeredPane默认的Layout是null，所以，放到JLayeredPane上的组件，必须要通过setBounds的形式来设置大小才会显示出来，否则是看不到的，这点尤其要注意。JLayeredPane的层次结构能实现非常多的特效，我甚至认为，JLayeredPane 是Swing结构中，最精妙的设计之一，通过JLayeredPane我们可以实现文本的验证提示功能，举个例子，有一个文本框，用来输入电话号码，有时候可能用户会输入些字母，甚至是汉字，当用户切换到下一个面板或者最后提交验证以后，你可能希望给出一些提示来标明这些输入非法，这时候，就可以用到JLayeredPane了，你可以将非法输入的组件，传递给一个Panel，这个Panel在非法的组件旁边绘制一个小图标，然后让这个Panel显示在主界面的上面(后续会把相关代码发出)。还有另外一个用途就是使用JInternalFrame做控制面板，可以通过JLayeredPane将一个JInternalFrame悬浮到一个面板中，既不会占用程序的空间，又不会像dialog那样，必须要弹出来才可以。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 附一个通过LayeredPane来显示加载进度的例子，使用方法很简单只需要将你的组件通过我的adapter封装下，然后再放到你的程序中即可MaskAdapter maskPanel = MaskAdapter.getMaskpanel(panel, false);。<br />
<a href="/Files/Swing/layer.zip">下载</a><br />
<img height="390" alt="" src="http://www.blogjava.net/images/blogjava_net/swing/blog/layer.PNG" width="688" border="0" /><br />
</span>
 <img src ="http://www.blogjava.net/Swing/aggbug/285979.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Swing/" target="_blank">zht</a> 2009-07-08 22:49 <a href="http://www.blogjava.net/Swing/archive/2009/07/08/285979.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Swing DayDayUP之一：JComponent组件保存为图片</title><link>http://www.blogjava.net/Swing/archive/2009/06/07/280383.html</link><dc:creator>zht</dc:creator><author>zht</author><pubDate>Sat, 06 Jun 2009 16:44:00 GMT</pubDate><guid>http://www.blogjava.net/Swing/archive/2009/06/07/280383.html</guid><wfw:comment>http://www.blogjava.net/Swing/comments/280383.html</wfw:comment><comments>http://www.blogjava.net/Swing/archive/2009/06/07/280383.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Swing/comments/commentRss/280383.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Swing/services/trackbacks/280383.html</trackback:ping><description><![CDATA[<p dir="ltr" style="font-size: 10pt; margin-right: 0px; font-family: Arial" align="left"><span style="color: #008000">知识点介绍<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JComponent提供了两个方法，print和printall可以将组件使用Graphics图形环境进行绘制，即将组件本身的内容都绘制到Graphics上，我们如果想要将组件保存成图片的话，只需要创建一个image对象，然后将其Graphics对象传递进去即可，如下所示<br />
BufferedImage image = new BufferedImage(imgW + xgap * 2, imgH + ygap * 2, BufferedImage.TYPE_INT_ARGB);<br />
&nbsp;Graphics2D g = (Graphics2D) image.getGraphics();<br />
component.print(g);</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
<div align="center"><img height="399" alt="" src="http://www.blogjava.net/images/blogjava_net/swing/daydayup/exportComponent.png" width="497" border="0" /></div>
<br />
<br />
<a href="/Files/Swing/daydayup/exportimage.zip">下载链接</a><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000">by zhangtao</span>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2009.6.7</span></p>
  <img src ="http://www.blogjava.net/Swing/aggbug/280383.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Swing/" target="_blank">zht</a> 2009-06-07 00:44 <a href="http://www.blogjava.net/Swing/archive/2009/06/07/280383.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JavaSwing也惊艳之二：环环相套</title><link>http://www.blogjava.net/Swing/archive/2009/03/03/257663.html</link><dc:creator>zht</dc:creator><author>zht</author><pubDate>Tue, 03 Mar 2009 14:22:00 GMT</pubDate><guid>http://www.blogjava.net/Swing/archive/2009/03/03/257663.html</guid><wfw:comment>http://www.blogjava.net/Swing/comments/257663.html</wfw:comment><comments>http://www.blogjava.net/Swing/archive/2009/03/03/257663.html#Feedback</comments><slash:comments>9</slash:comments><wfw:commentRss>http://www.blogjava.net/Swing/comments/commentRss/257663.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Swing/services/trackbacks/257663.html</trackback:ping><description><![CDATA[<p><strong><span style="color: #008000"><span style="color: #008000">一、序言</span></span></strong></p>
<p><span style="color: #008000"><span style="color: #008000">关于&#8220;Java做不好桌面&#8221;的争论已经由来已久。虽然Swing和Java2D已经有超过十年的历史，也有JIDE、JGoodies、TWaver等不少开源Swing组件，但是用Java做桌面程序仍然不是一件轻松的事。本《Java也惊艳》系列文章，就是想通过一些简单生动的例子，和大家一起认识Java、探索Swing。其实你只需要多一点创意、多一点耐心，你的Java程序也可以&#8220;惊艳&#8221;！本文就带您一起进入Java的惊艳之旅。</span></span></p>
<p><strong><span style="color: #008000"><span style="color: #008000">二、立体套管效果</span></span></strong></p>
<p><span style="color: #008000"><span style="color: #008000">在网络通讯中，经常要表达协议之间的&#8220;承载&#8221;关系。例如，IP协议作为高层协议可以承载在SDH上，也可以承载在ATM协议上。同样，IP作为协议还可以承载更多的高层协议，例如Voice over IP，甚至电信中Everything over IP的概念。在表现上，用相互嵌套的立体套管来表现协议的&#8220;承载&#8221;是再合适不过了（如下图）。<br />
</span>
<div align="center"><span style="color: #008000"><img height="96" alt="" src="http://www.blogjava.net/images/blogjava_net/swing/Swing/pie/swing2_1.jpg" width="271" border="0" /></span></div>
<br />
<br />
<span style="color: #008000">具体实现很简单，主要代码如下：</span></span>
<p></p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #008000"><span style="color: #008000"><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;java.awt.</span><span style="color: #000000">*</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">;&nbsp;<br />
</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;java.awt.geom.</span><span style="color: #000000">*</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">;&nbsp;<br />
</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;javax.swing.</span><span style="color: #000000">*</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">;&nbsp;<br />
<br />
</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;twaver.</span><span style="color: #000000">*</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">;&nbsp;<br />
<br />
</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;PipleComponent&nbsp;</span><span style="color: #0000ff">extends</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">&nbsp;JComponent&nbsp;{&nbsp;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">&nbsp;paint(Graphics&nbsp;g)&nbsp;{&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Graphics2D&nbsp;g2d&nbsp;</span><span style="color: #000000">=</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">&nbsp;(Graphics2D)&nbsp;g;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,&nbsp;RenderingHints.VALUE_ANTIALIAS_ON);&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Shape&nbsp;parentHollowShape</span><span style="color: #000000">=</span><span style="color: #000000">createPiple(g2d,</span><span style="color: #000000">100</span><span style="color: #000000">,</span><span style="color: #000000">100</span><span style="color: #000000">,</span><span style="color: #000000">200</span><span style="color: #000000">,</span><span style="color: #000000">200</span><span style="color: #000000">,TWaverUtil.getRandomColor(),</span><span style="color: #0000ff">null</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">);&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;createPiple(g2d,</span><span style="color: #000000">120</span><span style="color: #000000">,</span><span style="color: #000000">120</span><span style="color: #000000">,</span><span style="color: #000000">280</span><span style="color: #000000">,</span><span style="color: #000000">40</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">,TWaverUtil.getRandomColor(),parentHollowShape);&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;createPiple(g2d,</span><span style="color: #000000">130</span><span style="color: #000000">,</span><span style="color: #000000">170</span><span style="color: #000000">,</span><span style="color: #000000">310</span><span style="color: #000000">,</span><span style="color: #000000">40</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">,TWaverUtil.getRandomColor(),parentHollowShape);&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;createPiple(g2d,</span><span style="color: #000000">140</span><span style="color: #000000">,</span><span style="color: #000000">220</span><span style="color: #000000">,</span><span style="color: #000000">290</span><span style="color: #000000">,</span><span style="color: #000000">50</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">,TWaverUtil.getRandomColor(),parentHollowShape);&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;createPiple(g2d,</span><span style="color: #000000">130</span><span style="color: #000000">,</span><span style="color: #000000">190</span><span style="color: #000000">,</span><span style="color: #000000">300</span><span style="color: #000000">,</span><span style="color: #000000">30</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">,TWaverUtil.getRandomColor(),parentHollowShape);&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">private</span><span style="color: #000000">&nbsp;Shape&nbsp;createPiple(Graphics2D&nbsp;g2d,</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;x,&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;y,&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;width,&nbsp;</span><span style="color: #0000ff">int</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">&nbsp;height,Color&nbsp;color,Shape&nbsp;parentHollowShape)&nbsp;{&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">(parentHollowShape</span><span style="color: #000000">!=</span><span style="color: #0000ff">null</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">){&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Rectangle&nbsp;bounds</span><span style="color: #000000">=</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">parentHollowShape.getBounds();&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Rectangle&nbsp;rightClip</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Rectangle(bounds.x</span><span style="color: #000000">+</span><span style="color: #000000">bounds.width</span><span style="color: #000000">/</span><span style="color: #000000">2</span><span style="color: #000000">,bounds.y,</span><span style="color: #000000">3000</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">,bounds.height);&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Area&nbsp;clip</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">&nbsp;Area(parentHollowShape);&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;clip.add(</span><span style="color: #0000ff">new</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">&nbsp;Area(rightClip));&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g2d.setClip(clip);&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;circleWidth&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;height</span><span style="color: #000000">/</span><span style="color: #000000">3</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GradientPaint&nbsp;paint&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">&nbsp;GradientPaint(x,&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;y,&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;color.brighter(),&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x,&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;y&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;(</span><span style="color: #0000ff">int</span><span style="color: #000000">)&nbsp;(height&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0.65</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">),&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;color.darker(),&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">true</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">);&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g2d.setPaint(paint);&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Ellipse2D.Double&nbsp;leftCircle&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Ellipse2D.Double(x&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;circleWidth&nbsp;</span><span style="color: #000000">/</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">2</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">,&nbsp;y,&nbsp;circleWidth,&nbsp;height);&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Ellipse2D.Double&nbsp;rightCircle&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Ellipse2D.Double(x&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;width&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;circleWidth&nbsp;</span><span style="color: #000000">/</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">2</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">,&nbsp;y,&nbsp;circleWidth,&nbsp;height);&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;thickness</span><span style="color: #000000">=</span><span style="color: #000000">4</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Ellipse2D.Double&nbsp;rightHollowCircle&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Ellipse2D.Double(rightCircle.getX()</span><span style="color: #000000">+</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">thickness,&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rightCircle.getY()</span><span style="color: #000000">+</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">thickness,&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rightCircle.getWidth()</span><span style="color: #000000">-</span><span style="color: #000000">thickness</span><span style="color: #000000">*</span><span style="color: #000000">2</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">,&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rightCircle.getHeight()</span><span style="color: #000000">-</span><span style="color: #000000">thickness</span><span style="color: #000000">*</span><span style="color: #000000">2</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">);&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Rectangle&nbsp;rect&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">&nbsp;Rectangle(x,&nbsp;y,&nbsp;width,&nbsp;height);&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Area&nbsp;area&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">&nbsp;Area(leftCircle);&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;area.add(</span><span style="color: #0000ff">new</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">&nbsp;Area(rect));&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;area.subtract(</span><span style="color: #0000ff">new</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">&nbsp;Area(rightCircle));&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g2d.fill(area);&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g2d.setColor(color.darker());&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g2d.fill(rightCircle);&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;paint&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">&nbsp;GradientPaint(x,&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;y,&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Color.darkGray,&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x,&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;y&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;(</span><span style="color: #0000ff">int</span><span style="color: #000000">)&nbsp;(height&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0.4</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">),&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Color.lightGray,&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">true</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">);&nbsp;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g2d.setPaint(paint);&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g2d.fill(rightHollowCircle);&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g2d.setClip(</span><span style="color: #0000ff">null</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">);&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">&nbsp;rightHollowCircle;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">&nbsp;main(String[]&nbsp;args)&nbsp;{&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JFrame&nbsp;frame&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">&nbsp;JFrame();&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;frame.setSize(</span><span style="color: #000000">800</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">600</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">);&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;frame.add(</span><span style="color: #0000ff">new</span></span></span><span style="color: #008000"><span style="color: #008000"><span style="color: #000000">&nbsp;PipleComponent());&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;frame.setVisible(</span><span style="color: #0000ff">true</span></span></span><span style="color: #000000"><span style="color: #008000"><span style="color: #008000">);&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br />
}<br />
</span></span></span></div>
<div align="center"><span style="color: #008000"><img height="373" alt="" src="http://www.blogjava.net/images/blogjava_net/swing/Swing/pie/swing2_2.PNG" width="504" border="0" /></span></div>
<br />
<p><strong><span style="color: #008000"><span style="color: #008000">三、总结</span></span></strong></p>
<p><span style="color: #008000"><span style="color: #008000">本文知识要点：<br />
&nbsp;渐变填充：创建GradientPaint并设置&#8220;亮-暗-亮&#8221;的填充模式；<br />
&nbsp;使用Clip：类似蒙版/剪切的Java2D技术。看看Graphics的setClip函数即可；<br />
&nbsp;Area的使用：主要是Area的相交、合并等几个常见图形处理手法。详细请看java.awt.geom.Area类；<br />
&nbsp;使用随机色：这个就太简单了，如果有twaver.jar，可以直接使用TWaverUtil.getRandomColor()；如果没有，就直接new Color就行了，注意使用第四个int参数增加Alpha透明度的变化； <br />
<br />
如果大家感兴趣，可以尝试用上述Java2D技巧实现下图效果：<br />
<br />
</span></span></p>
<div align="center"><span style="color: #008000"><img height="170" alt="" src="http://www.blogjava.net/images/blogjava_net/swing/Swing/pie/swing2_3.gif" width="355" border="0" /></span></div>
<br />
<span style="color: #008000">&nbsp; <br />
</span>
<p class="MsoNormal"><strong style="mso-bidi-font-weight: normal"><span style="font-family: 华文楷体"><span style="color: #008000">六、参考资料</span></span></strong></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: 华文楷体"><a href="http://java.sun.com/j2se/1.4.2/docs/guide/2d/spec/j2d-bookTOC.html"><span style="color: #008000">http://java.sun.com/j2se/1.4.2/docs/guide/2d/spec/j2d-bookTOC.html</span></a><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: 华文楷体"><a href="http://java.sun.com/j2se/1.4.2/docs/guide/2d/spec.html"><span style="color: #008000">http://java.sun.com/j2se/1.4.2/docs/guide/2d/spec.html</span></a><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: 华文楷体"><a href="http://www.apl.jhu.edu/~hall/java/Java2D-Tutorial.html"><span style="color: #008000">http://www.apl.jhu.edu/~hall/java/Java2D-Tutorial.html</span></a><o:p></o:p></span></p>
  <img src ="http://www.blogjava.net/Swing/aggbug/257663.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Swing/" target="_blank">zht</a> 2009-03-03 22:22 <a href="http://www.blogjava.net/Swing/archive/2009/03/03/257663.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JavaSwing也惊艳之一：水晶之恋</title><link>http://www.blogjava.net/Swing/archive/2009/02/20/255676.html</link><dc:creator>zht</dc:creator><author>zht</author><pubDate>Thu, 19 Feb 2009 16:18:00 GMT</pubDate><guid>http://www.blogjava.net/Swing/archive/2009/02/20/255676.html</guid><wfw:comment>http://www.blogjava.net/Swing/comments/255676.html</wfw:comment><comments>http://www.blogjava.net/Swing/archive/2009/02/20/255676.html#Feedback</comments><slash:comments>23</slash:comments><wfw:commentRss>http://www.blogjava.net/Swing/comments/commentRss/255676.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Swing/services/trackbacks/255676.html</trackback:ping><description><![CDATA[<span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000">&nbsp; </span></span></span>
<p class="MsoNormal"><strong style="mso-bidi-font-weight: normal"><span style="font-family: 华文楷体"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000">一、序言<span lang="EN-US"><o:p></o:p></span></span></span></span></span></strong></p>
<p class="MsoNormal"><strong style="mso-bidi-font-weight: normal"><span lang="EN-US" style="font-family: 华文楷体"><o:p><span style="font-size: 12pt"><span style="font-size: 10pt"></span></span></o:p></span></strong></p>
<p class="MsoNormal"><span style="font-family: 华文楷体"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000">关于&#8220;<span lang="EN-US">Java</span>做不好桌面&#8221;的争论已经由来已久。虽然<span lang="EN-US">Swing</span>和<span lang="EN-US">Java2D</span>已经有超过十年的历史，也有<span lang="EN-US">JIDE</span>、<span lang="EN-US">JGoodies</span>、<span lang="EN-US">TWaver</span>等不少开源<span lang="EN-US">Swing</span>组件，但是用<span lang="EN-US">Java</span>做桌面程序仍然不是一件轻松的事。本《<span lang="EN-US">Java</span>也惊艳》系列文章，就是想通过一些简单生动的例子，和大家一起认识<span lang="EN-US">Java</span>、探索<span lang="EN-US">Swing</span>。其实你只需要多一点创意、多一点耐心，你的<span lang="EN-US">Java</span>程序也可以&#8220;惊艳&#8221;！本文就带您一起进入<span lang="EN-US">Java</span>的&#8220;水晶之恋&#8221;。<span lang="EN-US"><o:p></o:p></span></span></span></span></span></p>
<span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000">&nbsp; </span></span></span>
<p class="MsoNormal"><strong style="mso-bidi-font-weight: normal"><span style="font-family: 华文楷体"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000">二、立体水晶效果<span lang="EN-US"><o:p></o:p></span></span></span></span></span></strong></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: 华文楷体"><o:p><span style="font-size: 12pt"><span style="font-size: 10pt"></span></span></o:p></span></p>
<span style="font-size: 10.5pt; font-family: 华文楷体; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000">受苹果公司的影响，现在立体水晶风格的界面非常流行。<span lang="EN-US">Java</span>也可以吗？我们不妨先尝试一下用<span lang="EN-US">Java</span>绘制一个立体水晶风格的按钮到底有多难。一个立体的水晶按钮应当有一个图标、一个圆角矩形区域、边框以及一些立体反光效果，如下图：<br />
<img height="74" alt="" src="http://www.blogjava.net/images/blogjava_net/swing/Swing/水晶/1-0.png" width="550" border="0" /><br />
&nbsp; </span></span></span>
<p class="MsoNormal"><span style="font-family: 华文楷体"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000">简单思路如下：先画矩形区域，然后画图标，然后设置<span lang="EN-US">clip</span>并画高亮反光区域，最后画外部边框。<span lang="EN-US"><o:p></o:p></span></span></span></span></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: 华文楷体"><o:p><span style="font-size: 12pt"><span style="font-size: 10pt"></span></span></o:p></span></p>
<p class="MsoNormal"><span style="font-family: 华文楷体"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000">具体实现比较简单，主要代码如下：<br />
</span></span></span><span lang="EN-US"><o:p></p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">Color&nbsp;color&nbsp;</span><span style="color: #000000">=</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">&nbsp;TWaverUtil.getRandomColor();&nbsp;<br />
&nbsp;RoundRectangle2D&nbsp;body&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;RoundRectangle2D.Float(x,&nbsp;y,&nbsp;size,&nbsp;size,&nbsp;size&nbsp;</span><span style="color: #000000">/</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">3</span><span style="color: #000000">,&nbsp;size&nbsp;</span><span style="color: #000000">/</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">3</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">);&nbsp;<br />
<br />
</span><span style="color: #008000">//</span><span style="color: #008000">draw&nbsp;body&nbsp;</span></span></span></span><span style="color: #008000"><br />
</span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">g2d.setColor(color);&nbsp;<br />
GradientPaint&nbsp;paint&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">&nbsp;GradientPaint(x,&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;y,&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;color.darker(),&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x,&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;y&nbsp;</span><span style="color: #000000">+</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">&nbsp;size,&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;color.brighter().brighter());&nbsp;<br />
g2d.setPaint(paint);&nbsp;<br />
g2d.fill(body);&nbsp;<br />
<br />
</span><span style="color: #008000">//</span><span style="color: #008000">draw&nbsp;image&nbsp;</span></span></span></span><span style="color: #008000"><br />
</span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">g2d.setClip(body);&nbsp;<br />
Image&nbsp;image&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;TWaverUtil.getImage(</span><span style="color: #000000">"</span><span style="color: #000000">/glass/</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;i&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">.png</span><span style="color: #000000">"</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">);&nbsp;<br />
g2d.drawImage(image,&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;(size&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;image.getWidth(</span><span style="color: #0000ff">null</span><span style="color: #000000">))&nbsp;</span><span style="color: #000000">/</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">2</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">,&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;y&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;(size&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;image.getHeight(</span><span style="color: #0000ff">null</span><span style="color: #000000">))&nbsp;</span><span style="color: #000000">/</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">2</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">,&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">null</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">);&nbsp;<br />
g2d.setClip(</span><span style="color: #0000ff">null</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">);&nbsp;<br />
<br />
</span><span style="color: #008000">//</span><span style="color: #008000">draw&nbsp;highlight.&nbsp;</span></span></span></span><span style="color: #008000"><br />
</span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">Shape&nbsp;highlightArea&nbsp;</span><span style="color: #000000">=</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">&nbsp;createHighlightShape(x,&nbsp;y,&nbsp;size,&nbsp;body);&nbsp;<br />
g2d.setColor(</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Color(</span><span style="color: #000000">255</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">255</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">255</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">150</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">));&nbsp;<br />
g2d.fill(highlightArea);&nbsp;<br />
<br />
</span><span style="color: #008000">//</span><span style="color: #008000">draw&nbsp;outline.&nbsp;</span></span></span></span><span style="color: #008000"><br />
</span><span style="color: #000000"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000">g2d.setColor(color.darkGray);&nbsp;<br />
g2d.draw(body);<br />
</span></span></span></span></div>
</o:p></span></span></span><span style="font-size: 10.5pt; font-family: 华文楷体; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><br />
<span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000">其中，对高亮区域的计算，可以用一个圆心在左上方的大圆形和矩形进行剪切：<br />
</span></span></span>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #0000ff">private</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;Shape&nbsp;createHighlightShape(</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;centerX,&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;centerY,&nbsp;</span><span style="color: #0000ff">int</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">&nbsp;size,&nbsp;Shape&nbsp;body)&nbsp;{&nbsp;<br />
</span><span style="color: #0000ff">double</span><span style="color: #000000">&nbsp;myRadius&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;size&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">4</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">;&nbsp;<br />
&nbsp;&nbsp;</span><span style="color: #0000ff">double</span><span style="color: #000000">&nbsp;x&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;centerX&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;size&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">2.3</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">;&nbsp;<br />
&nbsp;&nbsp;</span><span style="color: #0000ff">double</span><span style="color: #000000">&nbsp;y&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;centerY&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;size&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">3.2</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">;&nbsp;<br />
&nbsp;&nbsp;Ellipse2D.Double&nbsp;circle&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">&nbsp;Ellipse2D.Double(x,&nbsp;y,&nbsp;myRadius,&nbsp;myRadius);&nbsp;<br />
&nbsp;&nbsp;Area&nbsp;area&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">&nbsp;Area(circle);&nbsp;<br />
&nbsp;&nbsp;area.intersect(</span><span style="color: #0000ff">new</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">&nbsp;Area(body));&nbsp;<br />
&nbsp;&nbsp;</span><span style="color: #0000ff">return</span></span></span></span><span style="color: #000000"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000">&nbsp;area;&nbsp;<br />
}<br />
</span></span></span></span></div>
</span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000">&nbsp; </span></span></span>
<p class="MsoNormal"><span style="font-family: 华文楷体"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000">运行程序效果如下：<span lang="EN-US"><o:p></o:p></span></span></span></span></span></p>
<span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000">&nbsp; <img height="700" alt="" src="http://www.blogjava.net/images/blogjava_net/swing/Swing/水晶/1-1.png" width="700" border="0" /></span></span></span>
<p class="MsoNormal"><strong style="mso-bidi-font-weight: normal"><span style="font-family: 华文楷体"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><br />
三、更多变化</span></span></span></span></strong></p>
<span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="font-size: 10.5pt; font-family: 华文楷体; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">根据上面例子稍作形状变换，可以画出立体水晶球的按钮。</span><br />
</span></span></span>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">Color&nbsp;color&nbsp;</span><span style="color: #000000">=</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">&nbsp;TWaverUtil.getRandomColor();&nbsp;<br />
<br />
Ellipse2D.Double&nbsp;circle&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Ellipse2D.Double(centerX&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;radius,&nbsp;centerY&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;radius,&nbsp;radius&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">2</span><span style="color: #000000">,&nbsp;radius&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">2</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">);&nbsp;<br />
<br />
</span><span style="color: #008000">//</span><span style="color: #008000">draw&nbsp;body&nbsp;</span></span></span></span><span style="color: #008000"><br />
</span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">g2d.setColor(color);&nbsp;<br />
GradientPaint&nbsp;paint&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;GradientPaint(centerX,&nbsp;centerY,&nbsp;color,&nbsp;centerX,&nbsp;centerY&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;radius&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">2</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">,&nbsp;color.brighter().brighter());&nbsp;<br />
g2d.setPaint(paint);&nbsp;<br />
g2d.fill(circle);&nbsp;<br />
<br />
</span><span style="color: #008000">//</span><span style="color: #008000">draw&nbsp;image&nbsp;</span></span></span></span><span style="color: #008000"><br />
</span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">g2d.setClip(circle);&nbsp;<br />
Image&nbsp;image&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;TWaverUtil.getImage(</span><span style="color: #000000">"</span><span style="color: #000000">/glass/</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;i&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">.png</span><span style="color: #000000">"</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">);&nbsp;<br />
g2d.drawImage(image,&nbsp;<br />
centerX&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;image.getWidth(</span><span style="color: #0000ff">null</span><span style="color: #000000">)&nbsp;</span><span style="color: #000000">/</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">2</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">,&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;centerY&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;image.getHeight(</span><span style="color: #0000ff">null</span><span style="color: #000000">)&nbsp;</span><span style="color: #000000">/</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">2</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">,&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">null</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">);&nbsp;<br />
g2d.setClip(</span><span style="color: #0000ff">null</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">);&nbsp;<br />
<br />
</span><span style="color: #008000">//</span><span style="color: #008000">draw&nbsp;highlight.&nbsp;</span></span></span></span><span style="color: #008000"><br />
</span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">Shape&nbsp;highlightArea&nbsp;</span><span style="color: #000000">=</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">&nbsp;createHighlightShape(centerX,&nbsp;centerY,&nbsp;radius);&nbsp;<br />
g2d.setColor(</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Color(</span><span style="color: #000000">255</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">255</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">255</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">150</span></span></span></span><span style="color: #000000"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000">));&nbsp;<br />
g2d.fill(highlightArea);<br />
</span></span></span></span></div>
<br />
<p class="MsoNormal"><span style="font-family: 华文楷体"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000">唯一略有不同的部分是，水晶球的高亮区域要用两个圆形拼切：<span lang="EN-US"><o:p></o:p></span></span></span></span></span></p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #0000ff">private</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;Shape&nbsp;createHighlightShape(</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;centerX,&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;centerY,&nbsp;</span><span style="color: #0000ff">int</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">&nbsp;radius)&nbsp;{&nbsp;<br />
</span><span style="color: #0000ff">double</span><span style="color: #000000">&nbsp;myRadius&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;radius&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0.8</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">;&nbsp;<br />
&nbsp;&nbsp;</span><span style="color: #0000ff">double</span><span style="color: #000000">&nbsp;x&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;centerX&nbsp;</span><span style="color: #000000">-</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">&nbsp;myRadius;&nbsp;<br />
&nbsp;&nbsp;</span><span style="color: #0000ff">double</span><span style="color: #000000">&nbsp;y1&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;centerY&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;myRadius&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;myRadius&nbsp;</span><span style="color: #000000">/</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">5</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">;&nbsp;<br />
&nbsp;&nbsp;</span><span style="color: #0000ff">double</span><span style="color: #000000">&nbsp;y2&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;centerY&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;myRadius&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;myRadius&nbsp;</span><span style="color: #000000">/</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">5</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">2</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">;&nbsp;<br />
<br />
&nbsp;&nbsp;Ellipse2D.Double&nbsp;circle1&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Ellipse2D.Double(x,&nbsp;y1,&nbsp;myRadius&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">2</span><span style="color: #000000">,&nbsp;myRadius&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">2</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">);&nbsp;<br />
&nbsp;&nbsp;Ellipse2D.Double&nbsp;circle2&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Ellipse2D.Double(x,&nbsp;y2,&nbsp;myRadius&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">2</span><span style="color: #000000">,&nbsp;myRadius&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">2</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">);&nbsp;<br />
<br />
&nbsp;&nbsp;Area&nbsp;area&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">&nbsp;Area(circle1);&nbsp;<br />
&nbsp;&nbsp;area.intersect(</span><span style="color: #0000ff">new</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">&nbsp;Area(circle2));&nbsp;<br />
&nbsp;&nbsp;</span><span style="color: #0000ff">return</span></span></span></span><span style="color: #000000"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000">&nbsp;area;&nbsp;<br />
}<br />
</span></span></span></span></div>
<span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000">&nbsp; </span></span></span>
<p class="MsoNormal"><span style="font-family: 华文楷体"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000">运行效果如下：<br />
<img height="700" alt="" src="http://www.blogjava.net/images/blogjava_net/swing/Swing/水晶/1-2.png" width="700" border="0" /><br />
<br />
<span style="font-size: 10.5pt; font-family: 华文楷体; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">如果再来点儿循环、随机大小、随机位置、随机颜色，就可以做出绚丽的&#8220;吹肥皂泡&#8221;的效果</span><br />
</span></span></span><span lang="EN-US"><o:p><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><img height="538" alt="" src="http://www.blogjava.net/images/blogjava_net/swing/Swing/水晶/1_3.png" width="660" border="0" /><br />
<br />
&nbsp; </span></span></span></p>
<p class="MsoNormal"><strong style="mso-bidi-font-weight: normal"><span style="font-family: 华文楷体"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000">四、融入<span lang="EN-US">Swing</span>组件<span lang="EN-US"><o:p></o:p></span></span></span></span></span></strong></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: 华文楷体"><o:p><span style="font-size: 12pt"><span style="font-size: 10pt"></span></span></o:p></span></p>
<p class="MsoNormal"><span style="font-family: 华文楷体"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000">以上例子仅使用了<span lang="EN-US">Java2D</span>进行绘图。在实际使用中，需要将这些效果应用的<span lang="EN-US">Swing</span>组件中，例如按钮等。一个简单的方式是：将以上图形效果在内存中生成内存图片并封装到一个<span lang="EN-US">ImageIcon</span>中，然后将<span lang="EN-US">ImageIcon</span>图标作为<span lang="EN-US">JButton</span>的图标进行显示。<br />
</span></span></span><span lang="EN-US"><o:p></p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;Image&nbsp;createImageIcon(Image&nbsp;phantom,&nbsp;</span><span style="color: #0000ff">int</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">&nbsp;size)&nbsp;{<br />
BufferedImage&nbsp;bi&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">&nbsp;BufferedImage(size,&nbsp;size,&nbsp;BufferedImage.TYPE_INT_ARGB);<br />
&nbsp;&nbsp;Graphics2D&nbsp;g2d&nbsp;</span><span style="color: #000000">=</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">&nbsp;bi.createGraphics();<br />
&nbsp;&nbsp;g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,&nbsp;RenderingHints.VALUE_ANTIALIAS_ON);<br />
<br />
&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;center&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;size&nbsp;</span><span style="color: #000000">/</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">2</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">;<br />
&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;radius&nbsp;</span><span style="color: #000000">=</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">&nbsp;center;<br />
<br />
&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">此处进行画图</span></span></span></span><span style="color: #008000"><br />
</span><span style="color: #000000"><br />
<span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000">&nbsp;&nbsp;g2d.dispose();<br />
&nbsp;&nbsp;</span></span></span></span><span style="color: #0000ff"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000">return</span></span></span></span><span style="color: #000000"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000">&nbsp;bi;<br />
}<br />
</span></span></span></span></div>
</o:p></span></span></o:p></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000">&nbsp; </span></span></span>
<p class="MsoNormal"><span style="font-family: 华文楷体"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000">然后，用这些<span lang="EN-US">Icon</span>创建一些按钮并显示：<span lang="EN-US"><o:p></o:p></span></span></span></span></span></p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;main(String[]&nbsp;args)&nbsp;</span><span style="color: #0000ff">throws</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">&nbsp;Exception&nbsp;{<br />
JFrame&nbsp;frame&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">&nbsp;JFrame();<br />
&nbsp;&nbsp;frame.getContentPane().setLayout(</span><span style="color: #0000ff">new</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">&nbsp;FlowLayout());<br />
&nbsp;&nbsp;frame.getContentPane().add(</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;JButton(</span><span style="color: #000000">"</span><span style="color: #000000">按钮1</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;ImageIcon(createImageIcon(</span><span style="color: #0000ff">null</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">60</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">))));<br />
&nbsp;&nbsp;frame.getContentPane().add(</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;JButton(</span><span style="color: #000000">"</span><span style="color: #000000">按钮2</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;ImageIcon(createImageIcon(</span><span style="color: #0000ff">null</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">60</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">))));<br />
&nbsp;&nbsp;frame.getContentPane().add(</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;JButton(</span><span style="color: #000000">"</span><span style="color: #000000">按钮3</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;ImageIcon(createImageIcon(</span><span style="color: #0000ff">null</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">60</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">))));<br />
&nbsp;&nbsp;frame.getContentPane().add(</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;JButton(</span><span style="color: #000000">"</span><span style="color: #000000">使用Java2D创建的立体水晶风格的按钮</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;ImageIcon(createImageIcon(</span><span style="color: #0000ff">null</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">30</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">))));<br />
&nbsp;&nbsp;frame.setSize(</span><span style="color: #000000">500</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">300</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">);<br />
&nbsp;&nbsp;frame.setTitle(</span><span style="color: #000000">"</span><span style="color: #000000">Java也惊艳</span><span style="color: #000000">"</span></span></span></span><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span style="color: #000000">);<br />
&nbsp;&nbsp;frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);<br />
&nbsp;&nbsp;TWaverUtil.centerWindow(frame);<br />
&nbsp;&nbsp;frame.setVisible(</span><span style="color: #0000ff">true</span></span></span></span><span style="color: #000000"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000">);<br />
}<br />
</span></span></span></span></div>
<br />
<span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000">&nbsp;&nbsp;&nbsp; </span></span></span>
<p class="MsoNormal"><span style="font-family: 华文楷体"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000">效果如下图：<span lang="EN-US"><o:p></o:p></span></span></span></span></span></p>
<p class="MsoNormal"><span style="font-family: 华文楷体"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><img height="300" alt="" src="http://www.blogjava.net/images/blogjava_net/swing/Swing/水晶/1-4.png" width="500" border="0" /></span></span></span><span lang="EN-US"><o:p></p>
<p class="MsoNormal"><span style="font-family: 华文楷体"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000">本例子没有使用<span lang="EN-US">Look And Feel</span>。你也可以使用<span lang="EN-US">JGoodies</span>来美化一下，效果肯定更好。<span lang="EN-US"><o:p></o:p></span></span></span></span></span></p>
<p class="MsoNormal"><strong style="mso-bidi-font-weight: normal"><span lang="EN-US" style="font-family: 华文楷体"><o:p><span style="font-size: 12pt"><span style="font-size: 10pt"></span></span></o:p></span></strong></p>
<p class="MsoNormal"><strong style="mso-bidi-font-weight: normal"><span style="font-family: 华文楷体"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000">五、总结</span></span></span></span></strong></p>
<p class="MsoNormal"><span style="font-family: 华文楷体"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000">可以看出，画出这类立体水晶效果并不难，只需仔细观察这些效果的光学细节，并用<span lang="EN-US">Java2D</span>的<span lang="EN-US">API</span>来实现即可。这些例子稍作改进，就可以用来绘制<span lang="EN-US">JButton</span>等<span lang="EN-US">Swing</span>组件，并用在实际项目中。或者，也可以应用这些技巧来做一些复杂图形界面，如在<span lang="EN-US">TWaver</span>中做出的网络拓扑图效果：<span lang="EN-US"><o:p></o:p></span></span></span></span></span></p>
<span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000">&nbsp; <img alt="" src="http://www.blogjava.net/images/blogjava_net/swing/Swing/水晶/1_t.png" border="0" /></span></span></span>
<p class="MsoNormal"><strong style="mso-bidi-font-weight: normal"><span style="font-family: 华文楷体"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000">本文知识要点：<span lang="EN-US"><o:p></o:p></span></span></span></span></span></strong></p>
<p class="MsoNormal" style="margin-left: 42pt; text-indent: -21pt; mso-list: l0 level1 lfo1; tab-stops: list 42.0pt"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span lang="EN-US" style="font-family: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><span style="mso-list: Ignore">n<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family: 华文楷体">渐变填充：这个使用<span lang="EN-US">GradientPaint</span>就行了；<span lang="EN-US"><o:p></o:p></span></span></span></span></span></p>
<p class="MsoNormal" style="margin-left: 42pt; text-indent: -21pt; mso-list: l0 level1 lfo1; tab-stops: list 42.0pt"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span lang="EN-US" style="font-family: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><span style="mso-list: Ignore">n<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family: 华文楷体">使用<span lang="EN-US">Clip</span>：类似蒙版<span lang="EN-US">/</span>剪切的<span lang="EN-US">Java2D</span>技术。看看<span lang="EN-US">Graphics</span>的<span lang="EN-US">setClip</span>函数就明白了；<span lang="EN-US"><o:p></o:p></span></span></span></span></span></p>
<p class="MsoNormal" style="margin-left: 42pt; text-indent: -21pt; mso-list: l0 level1 lfo1; tab-stops: list 42.0pt"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span lang="EN-US" style="font-family: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><span style="mso-list: Ignore">n<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US" style="font-family: 华文楷体">Area</span><span style="font-family: 华文楷体">的使用：主要是<span lang="EN-US">Area</span>的相交、合并等几个常见图形处理手法。详细请看<span lang="EN-US">java.awt.geom.Area</span>类；<span lang="EN-US"><o:p></o:p></span></span></span></span></span></p>
<p class="MsoNormal" style="margin-left: 42pt; text-indent: -21pt; mso-list: l0 level1 lfo1; tab-stops: list 42.0pt"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000"><span lang="EN-US" style="font-family: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><span style="mso-list: Ignore">n<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family: 华文楷体">生成内存图片：主要是<span lang="EN-US">BufferedImage</span>类的使用；<span lang="EN-US"><o:p></o:p></span></span></span></span></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: 华文楷体"><o:p><span style="font-size: 12pt"><span style="font-size: 10pt"></span></span></o:p></span></p>
<span style="font-size: 10.5pt; font-family: 华文楷体; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><span style="font-size: 12pt"><span style="font-size: 10pt"><span style="color: #008000">如果大家感兴趣，可以尝试用上述<span lang="EN-US">Java2D</span>技巧实现下图效果：<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/swing/Swing/swing1/1_7.png" border="0" /><br />
<span style="color: #ff0000">以上内容转载请注明<br />
&nbsp;
<p class="MsoNormal"><strong style="mso-bidi-font-weight: normal"><span style="font-family: 华文楷体"><span style="color: #008000">六、参考资料</span></span></strong></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: 华文楷体"><a href="http://java.sun.com/j2se/1.4.2/docs/guide/2d/spec/j2d-bookTOC.html"><span style="color: #008000">http://java.sun.com/j2se/1.4.2/docs/guide/2d/spec/j2d-bookTOC.html</span></a><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: 华文楷体"><a href="http://java.sun.com/j2se/1.4.2/docs/guide/2d/spec.html"><span style="color: #008000">http://java.sun.com/j2se/1.4.2/docs/guide/2d/spec.html</span></a><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: 华文楷体"><a href="http://www.apl.jhu.edu/~hall/java/Java2D-Tutorial.html"><span style="color: #008000">http://www.apl.jhu.edu/~hall/java/Java2D-Tutorial.html</span></a><o:p></o:p></span></p>
</span></span></span></span></span></o:p></span></span>
<img src ="http://www.blogjava.net/Swing/aggbug/255676.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Swing/" target="_blank">zht</a> 2009-02-20 00:18 <a href="http://www.blogjava.net/Swing/archive/2009/02/20/255676.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>大话swing核心</title><link>http://www.blogjava.net/Swing/archive/2008/08/13/221835.html</link><dc:creator>zht</dc:creator><author>zht</author><pubDate>Wed, 13 Aug 2008 14:26:00 GMT</pubDate><guid>http://www.blogjava.net/Swing/archive/2008/08/13/221835.html</guid><wfw:comment>http://www.blogjava.net/Swing/comments/221835.html</wfw:comment><comments>http://www.blogjava.net/Swing/archive/2008/08/13/221835.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/Swing/comments/commentRss/221835.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Swing/services/trackbacks/221835.html</trackback:ping><description><![CDATA[<span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp; 首先swing是单线程的，这个是这篇文章的前提，也是意义所在，当swing界面程序启动的时候，会启动3个进程，<br />
1、主线程<br />
2、系统工具包线程:负责捕获操作系统事件，然后将事件转换成swing的事件，然后发送到事件派发线程EDT<br />
3、事件派发线程(EDT):将事件派发到各个组件，并负责调用绘制方法更新界面<br />
<br />
所有的事件，例如键盘，鼠标事件，都会由工具包线程转换成swing事件，然后放到事件队列EventQueue中，而这个EventQueue的派发机制是由EDT来管理的。<br />
<img height="358" alt="" src="http://www.blogjava.net/images/blogjava_net/swing/EDT.PNG" width="521" border="0" /><br />
所以任何修改组件状态的方法都应该在EDT中执行，包括构造方法。Swing这样的构造原理经常会造成的情况就是，在EDT中执行长时间的事件，使EDT不能及时响应更新界面的事件，就是所说的界面卡住，这种不光是新手就是比较熟练的程序员也会犯的一个错误。所以必须避免在EDT中执行长时间的操作，而避免的方法就是多线程，启动另外的线程来处理冗长的操作，比如操作数据库，读写文件等，在这过程中可能要更新界面来给用户以提示，比如显示一个进度条，过一段事件更新一下界面，但是在EDT以外的线程中更新界面都是无效的，这在前面已经说过，要更新界面就要将对界面的更新操作放到EDT中，但是事件又是在另外的线程中执行的，要解决这个问题就要使用SwingUtilities提供的一个方法了 invokeLater，<br />
public void actionPerformed(ActionEvent e){<br />
&nbsp;&nbsp;&nbsp;&nbsp;new Thread(new Runnable(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//do something<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SwingUtilities.invokeLater(new Runnable(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pulic void run(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//update the GUI<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});<br />
&nbsp;&nbsp;&nbsp;&nbsp;}).start;<br />
}<br />
这个方法的作用就是将一个更新界面的任务放到EDT中，EDT会在适当的时候进行调用以更新界面。invokeLater负责创建一个含有Runnable的特定事件，并让其在EDT中排队等待调用，当被调用时就会运行Runnable中的run方法进行派发。<br />
<br />
</span>
 <img src ="http://www.blogjava.net/Swing/aggbug/221835.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Swing/" target="_blank">zht</a> 2008-08-13 22:26 <a href="http://www.blogjava.net/Swing/archive/2008/08/13/221835.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用popmenu实现的toolbar更多按钮的例子</title><link>http://www.blogjava.net/Swing/archive/2008/08/13/221623.html</link><dc:creator>zht</dc:creator><author>zht</author><pubDate>Wed, 13 Aug 2008 02:12:00 GMT</pubDate><guid>http://www.blogjava.net/Swing/archive/2008/08/13/221623.html</guid><wfw:comment>http://www.blogjava.net/Swing/comments/221623.html</wfw:comment><comments>http://www.blogjava.net/Swing/archive/2008/08/13/221623.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/Swing/comments/commentRss/221623.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Swing/services/trackbacks/221623.html</trackback:ping><description><![CDATA[<span style="color: #008000">效果如下所示：<br />
<img height="401" alt="" src="http://www.blogjava.net/images/blogjava_net/swing/toolbar.PNG" width="378" border="0" /><br />
源码下载：<a href="http://www.blogjava.net/Files/Swing/toolbar.rar"><u><strong><em>download</em></strong></u></a><br />
<br />
声明：用到了一些网上的资源，非原创</span>
<img src ="http://www.blogjava.net/Swing/aggbug/221623.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Swing/" target="_blank">zht</a> 2008-08-13 10:12 <a href="http://www.blogjava.net/Swing/archive/2008/08/13/221623.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>控制Swing中ToolTip的显示与隐藏</title><link>http://www.blogjava.net/Swing/archive/2008/05/22/202176.html</link><dc:creator>zht</dc:creator><author>zht</author><pubDate>Thu, 22 May 2008 14:42:00 GMT</pubDate><guid>http://www.blogjava.net/Swing/archive/2008/05/22/202176.html</guid><wfw:comment>http://www.blogjava.net/Swing/comments/202176.html</wfw:comment><comments>http://www.blogjava.net/Swing/archive/2008/05/22/202176.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/Swing/comments/commentRss/202176.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Swing/services/trackbacks/202176.html</trackback:ping><description><![CDATA[<p><span style="color: #008000">&nbsp;</p>
<p>先给出两个控制方法<br />
1、显示tooltip <br />
public static void postToolTip(JComponent comp) {<br />
&nbsp; Action action = comp.getActionMap().get("postTip");<br />
&nbsp; if (action == null) // no tooltip<br />
&nbsp;&nbsp; return;<br />
&nbsp; ActionEvent ae = new ActionEvent(comp, ActionEvent.ACTION_PERFORMED, "postTip", EventQueue.getMostRecentEventTime(), 0);<br />
&nbsp; action.actionPerformed(ae);<br />
&nbsp;}</p>
<p>2、隐藏tooltip<br />
&nbsp;public static void hideToolTip(JComponent comp) {<br />
&nbsp; Action action = comp.getActionMap().get("hideTip");<br />
&nbsp; if (action == null) // no tooltip<br />
&nbsp;&nbsp; return;<br />
&nbsp; ActionEvent ae = new ActionEvent(comp, ActionEvent.ACTION_PERFORMED, "hideTip", EventQueue.getMostRecentEventTime(), 0);<br />
&nbsp; action.actionPerformed(ae);<br />
&nbsp;}</p>
<p>tooltip的显示与隐藏都是通过ToolTipManager这个类来控制的<br />
当componet.setToolTipText的时候java的内部处理为 <br />
public void setToolTipText(String text) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String oldText = getToolTipText();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; putClientProperty(TOOL_TIP_TEXT_KEY, text);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ToolTipManager toolTipManager = ToolTipManager.sharedInstance();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (text != null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp; if (oldText == null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; toolTipManager.registerComponent(this);<br />
&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; toolTipManager.unregisterComponent(this);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }</p>
<p>而在ToolTipManager 的registerComponent方法中将两个Action添加到了组件的actionMap 中，<br />
具体的acton实现可以参考ToolTipManager 。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; ActionMap actionMap = component.getActionMap();<br />
&nbsp;&nbsp;&nbsp;&nbsp; if (inputMap != null &amp;&amp; actionMap != null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; actionMap.put("postTip", postTipAction);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; actionMap.put("hideTip", hideTipAction);<br />
</p>
<p><br />
上述两个方法就是取得这两个Action，然后调用相应的Action方法来控制tooltip的显示与隐藏。</p>
<p>对于tooltip的显示时间可以通过ToolTipManager中的set**的方法进行设置。</p>
<p></span><span style="color: #008000"><br />
以下是测试代码<br />
</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;main(String[]&nbsp;args)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">final</span><span style="color: #000000">&nbsp;JPanel&nbsp;panel&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;JPanel();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">final</span><span style="color: #000000">&nbsp;JButton&nbsp;btn&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;JButton(</span><span style="color: #000000">"</span><span style="color: #000000">button</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;btn.setToolTipText(</span><span style="color: #000000">"</span><span style="color: #000000">button_tooltip</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;panel.add(btn);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">final</span><span style="color: #000000">&nbsp;JButton&nbsp;btn1&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;JButton(</span><span style="color: #000000">"</span><span style="color: #000000">button1</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;panel.add(btn1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;btn1.setToolTipText(</span><span style="color: #000000">"</span><span style="color: #000000">button1_tooltip</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;btn.addActionListener(</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;ActionListener()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;actionPerformed(ActionEvent&nbsp;e)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;postToolTip(btn1);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;btn1.addActionListener(</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;ActionListener()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;actionPerformed(ActionEvent&nbsp;e)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;postToolTip(btn);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});<br />
&nbsp;JFrame frame = new JFrame();<br />
&nbsp;&nbsp;frame.setContentPane(panel);<br />
&nbsp;&nbsp;frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);<br />
&nbsp;&nbsp;frame.setSize(500, 400);<br />
&nbsp;&nbsp;frame.setLocationRelativeTo(null);<br />
&nbsp;&nbsp;frame.setVisible(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
<p><br />
<br />
注：以上有些内容引用自网络，我加了一些个人理解。<br />
<br />
下一篇将介绍一下对tooltip显示的控制，ex)换行，颜色以及其它属性</span></p>
<img src ="http://www.blogjava.net/Swing/aggbug/202176.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Swing/" target="_blank">zht</a> 2008-05-22 22:42 <a href="http://www.blogjava.net/Swing/archive/2008/05/22/202176.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Swing深入学习</title><link>http://www.blogjava.net/Swing/archive/2007/10/18/153792.html</link><dc:creator>zht</dc:creator><author>zht</author><pubDate>Thu, 18 Oct 2007 03:03:00 GMT</pubDate><guid>http://www.blogjava.net/Swing/archive/2007/10/18/153792.html</guid><wfw:comment>http://www.blogjava.net/Swing/comments/153792.html</wfw:comment><comments>http://www.blogjava.net/Swing/archive/2007/10/18/153792.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.blogjava.net/Swing/comments/commentRss/153792.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Swing/services/trackbacks/153792.html</trackback:ping><description><![CDATA[<span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;做了很长时间的Swing了，感觉有很多知识还是一知半解，打算抽时间把Swing书再看一遍，加深一下理解，着重于Swing底层知识、JTable，JTree。<br />
<br />
</span>
<table cellspacing="2" cellpadding="2" width="500" border="0">
    <tbody>
        <tr>
            <td><span style="color: #008000"><span style="color: #993300"><span style="color: #ff6600">序号</span></span></span></td>
            <td><span style="color: #008000"><span style="color: #993300"><span style="color: #ff6600">目录</span></span></span></td>
            <td><font color="#ff6600"></font></td>
        </tr>
        <tr>
            <td><span style="color: #008000">1</span></td>
            <td><span style="color: #008000">Swing基础知识</span></td>
            <td></td>
        </tr>
        <tr>
            <td><span style="color: #008000">2</span></td>
            <td style="color: red"><span style="color: #ff0000">Swing组件的体系结构</span></td>
            <td></td>
        </tr>
        <tr>
            <td><span style="color: #008000">3</span></td>
            <td><span style="color: #ff0000">JComponent类</span></td>
            <td></td>
        </tr>
        <tr>
            <td><span style="color: #008000">4</span></td>
            <td><span style="color: #008000">边框图标和动作</span></td>
            <td></td>
        </tr>
        <tr>
            <td><span style="color: #008000">5</span></td>
            <td><span style="color: #008000">实用工具</span></td>
            <td></td>
        </tr>
        <tr>
            <td><span style="color: #008000">6</span></td>
            <td><span style="color: #ff0000">插入式界面样式</span></td>
            <td></td>
        </tr>
        <tr>
            <td><span style="color: #008000">7</span></td>
            <td>
            <p><span style="color: #008000">标签、按钮、反转按钮、<br />
            复选框、单选钮&nbsp;</span></p>
            </td>
            <td></td>
        </tr>
        <tr>
            <td><span style="color: #008000">8</span></td>
            <td><span style="color: #008000">菜单和工具条</span></td>
            <td></td>
        </tr>
        <tr>
            <td><span style="color: #008000">9</span></td>
            <td><span style="color: #008000">进度条、滑杆和分割条</span></td>
            <td></td>
        </tr>
        <tr>
            <td><span style="color: #008000">10</span></td>
            <td><span style="color: #008000">轻量容器</span></td>
            <td></td>
        </tr>
        <tr>
            <td><span style="color: #008000">11</span></td>
            <td><span style="color: #ff0000">滚动</span></td>
            <td></td>
        </tr>
        <tr>
            <td><span style="color: #008000">12</span></td>
            <td>
            <p><span style="color: #008000">窗口、对话框、内部窗格、</span></p>
            <p><span style="color: #008000">桌面窗格</span></p>
            </td>
            <td></td>
        </tr>
        <tr>
            <td><span style="color: #008000">13</span></td>
            <td><span style="color: #008000">选取器</span></td>
            <td></td>
        </tr>
        <tr>
            <td><span style="color: #008000">14</span></td>
            <td><span style="color: #008000">列表、组合框</span></td>
            <td></td>
        </tr>
        <tr>
            <td><span style="color: #008000">15</span></td>
            <td><span style="color: #ff0000">表格</span></td>
            <td></td>
        </tr>
        <tr>
            <td><span style="color: #008000">16</span></td>
            <td><span style="color: #ff0000">树</span></td>
            <td></td>
        </tr>
        <tr>
            <td><span style="color: #008000">17</span></td>
            <td><span style="color: #008000">文本</span></td>
            <td></td>
        </tr>
        <tr>
            <td></td>
            <td></td>
            <td></td>
        </tr>
    </tbody>
</table>
<div style="border-right: #666666 1px solid; border-top: #666666 1px solid; border-left: #666666 1px solid; border-bottom: #666666 1px solid">Type text here</div>
<img src ="http://www.blogjava.net/Swing/aggbug/153792.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Swing/" target="_blank">zht</a> 2007-10-18 11:03 <a href="http://www.blogjava.net/Swing/archive/2007/10/18/153792.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Swing框架之Model</title><link>http://www.blogjava.net/Swing/archive/2007/10/12/152370.html</link><dc:creator>zht</dc:creator><author>zht</author><pubDate>Fri, 12 Oct 2007 08:16:00 GMT</pubDate><guid>http://www.blogjava.net/Swing/archive/2007/10/12/152370.html</guid><wfw:comment>http://www.blogjava.net/Swing/comments/152370.html</wfw:comment><comments>http://www.blogjava.net/Swing/archive/2007/10/12/152370.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Swing/comments/commentRss/152370.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Swing/services/trackbacks/152370.html</trackback:ping><description><![CDATA[<span style="color: #008000">&nbsp;&nbsp; <font size="2">构建应用程序应该</font><font size="2">以数据为中心，而不是以用户界面为中心，这是一个良好的编程习惯。为支持这种编程范式，Swing为每种带有逻辑数据或值的组件定义了独立的模型接口，这种分割使程序可以选择向Swing组件中嵌入自己的模型实现。</font> </span>
<p><span style="color: #008000"><span style="font-family: Georgia"><span style="font-family: Georgia">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 下面表格列出Swing中组件及其模型的映射关系：</span></span></span></p>
<table cellspacing="0" cellpadding="0" border="1">
    <tbody>
        <tr>
            <td><span style="color: #008000">组件</span></td>
            <td><span style="color: #008000">Model接口</span></td>
            <td><span style="color: #008000">Model类型</span></td>
        </tr>
        <tr>
            <td><span style="color: #008000">JButton</span></td>
            <td><span style="color: #008000">ButtonModel</span></td>
            <td><span style="color: #008000">GUI状态</span></td>
        </tr>
        <tr>
            <td><span style="color: #008000">JToggleButton</span></td>
            <td><span style="color: #008000">ButtonModel</span></td>
            <td><span style="color: #008000">GUI状态/应用数据</span></td>
        </tr>
        <tr>
            <td><span style="color: #008000">JCheckBox</span></td>
            <td><span style="color: #008000">ButtonModel</span></td>
            <td><span style="color: #008000">GUI状态/应用数据</span></td>
        </tr>
        <tr>
            <td><span style="color: #008000">JRadioButton</span></td>
            <td><span style="color: #008000">ButtonModel</span></td>
            <td><span style="color: #008000">GUI状态/应用数据</span></td>
        </tr>
        <tr>
            <td><span style="color: #008000">JMenu</span></td>
            <td><span style="color: #008000">ButtonModel</span></td>
            <td><span style="color: #008000">GUI状态</span></td>
        </tr>
        <tr>
            <td><span style="color: #008000">JMenuItem</span></td>
            <td><span style="color: #008000">ButtonModel</span></td>
            <td><span style="color: #008000">GUI状态</span></td>
        </tr>
        <tr>
            <td><span style="color: #008000">JCheckBoxMenuItem</span></td>
            <td><span style="color: #008000">ButtonModel</span></td>
            <td><span style="color: #008000">GUI状态/应用数据</span></td>
        </tr>
        <tr>
            <td><span style="color: #008000">JRadioButtonMenuItem</span></td>
            <td><span style="color: #008000">ButtonModel</span></td>
            <td><span style="color: #008000">GUI状态/应用数据</span></td>
        </tr>
        <tr>
            <td><span style="color: #008000">JComboBox</span></td>
            <td><span style="color: #008000">ComboBoxModel</span></td>
            <td><span style="color: #008000">应用数据</span></td>
        </tr>
        <tr>
            <td><span style="color: #008000">JProgressBar</span></td>
            <td><span style="color: #008000">BoundedRangeModel</span></td>
            <td><span style="color: #008000">GUI状态/应用数据</span></td>
        </tr>
        <tr>
            <td><span style="color: #008000">JScrollBar</span></td>
            <td><span style="color: #008000">BoundedRangeModel</span></td>
            <td><span style="color: #008000">GUI状态/应用数据</span></td>
        </tr>
        <tr>
            <td><span style="color: #008000">JSlider</span></td>
            <td><span style="color: #008000">BoundedRangeModel</span></td>
            <td><span style="color: #008000">GUI状态/应用数据</span></td>
        </tr>
        <tr>
            <td><span style="color: #008000">JTabbedPane</span></td>
            <td><span style="color: #008000">SingleSelectionModel</span></td>
            <td><span style="color: #008000">GUI状态</span></td>
        </tr>
        <tr>
            <td><span style="color: #008000">JList</span></td>
            <td><span style="color: #008000">ListModel</span></td>
            <td><span style="color: #008000">应用数据</span></td>
        </tr>
        <tr>
            <td><span style="color: #008000">JList</span></td>
            <td><span style="color: #008000">ListSelectionModel</span></td>
            <td><span style="color: #008000">GUI状态</span></td>
        </tr>
        <tr>
            <td><span style="color: #008000">JTable</span></td>
            <td><span style="color: #008000">TableModel</span></td>
            <td><span style="color: #008000">应用数据</span></td>
        </tr>
        <tr>
            <td><span style="color: #008000">JTable</span></td>
            <td><span style="color: #008000">TableColumnModel</span></td>
            <td><span style="color: #008000">GUI状态</span></td>
        </tr>
        <tr>
            <td><span style="color: #008000">JTree</span></td>
            <td><span style="color: #008000">TreeModel</span></td>
            <td><span style="color: #008000">应用数据</span></td>
        </tr>
        <tr>
            <td><span style="color: #008000">JTree</span></td>
            <td><span style="color: #008000">TreeSelectionModel</span></td>
            <td><span style="color: #008000">GUI状态</span></td>
        </tr>
        <tr>
            <td><span style="color: #008000">JEditorPane</span></td>
            <td><span style="color: #008000">Document</span></td>
            <td><span style="color: #008000">应用数据</span></td>
        </tr>
        <tr>
            <td><span style="color: #008000">JTextPane</span></td>
            <td><span style="color: #008000">Document</span></td>
            <td><span style="color: #008000">应用数据</span></td>
        </tr>
        <tr>
            <td><span style="color: #008000">JTextArea</span></td>
            <td><span style="color: #008000">Document</span></td>
            <td><span style="color: #008000">应用数据</span></td>
        </tr>
        <tr>
            <td><span style="color: #008000">JTextField</span></td>
            <td><span style="color: #008000">Document</span></td>
            <td><span style="color: #008000">应用数据</span></td>
        </tr>
        <tr>
            <td><span style="color: #008000">JPasswordField</span></td>
            <td><span style="color: #008000">Document</span></td>
            <td><span style="color: #008000">应用数据</span></td>
        </tr>
    </tbody>
</table>
<p style="font-weight: bold; font-family: Georgia"><span style="color: #008000">Swing模型分类</span></p>
<p style="font-family: Georgia"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Swing提供的模型分为两大类：GUI状态模型和应用数据模型。</span></p>
<p style="font-family: Georgia"><span style="color: #008000"><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GUI状态模型是描述GUI控件可视化状态的接口，如按钮是否按下，或列表中那一项被选中。GUI状态模型通常仅在图形用户界面(GUI)环境中用到。</font><font size="2">通常来说，虽然</font><font size="2">编写使用GUI状态模型分离程序，</font><font size="2">尤其是当多个GUI控件共享状态</font><font size="2">，或当操作一个控件自动更新另一个的值时</font><font size="2">比较有用</font><font size="2">，但GUI状态模型在Swing中并不是必需的，完全可以通过组件顶层方法操作GUI控件的状态，而不必和模型直接交互。</font></span></p>
<p style="font-family: Georgia"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 应用数据模型是描述具有应用程序含义数据的接口，比如表格中的数据，或列表显示的选项。这些数据模型为Swing提供了一个清晰分割应用程序界面和数据逻辑的强大编程模式。对于以数据为核心的Swing组件，比如JTree和JTable，强烈推荐使用数据模型进行交互。</span></p>
<p style="font-family: Georgia"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当然一些组件的模型根据应用场景的不同其分类介于GUI状态模型和应用数据模型之间，比如JSlider和JProgressBar 的BoundedRangeModel。</span></p>
<p style="font-family: Georgia"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Swing的可分离模型接口并没有明确界定GUI状态模型和应用数据模型。这儿所以做此说明，目的是让你更好的理解何时以及为何要需要使用分离的模型。</span></p>
<p style="font-family: Georgia"><font size="2"><span style="color: #008000"><span style="font-weight: bold">共享模型定义</span><br />
</span></font></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 值得注意的是，上文中表格中，许多组件的数据抽象相似，只需一个接口而不用过分泛化时，组件可以共享同一模型定义。共享模型定义允许在不同组件之间自动连接。比如，JSlider和JScrollBar都使用BoundedRangeModel接口，因此可以在一个JScrollBar和一个JSlider之间共享同一个BoundedRangeModel实例，这样它们之间的状态就总是同步的。</span></p>
<p><a href="http://blog.sina.com.cn/main/html/showpic.html#url=http://s6.album.sina.com.cn/pic/4b6047bc02000kt5" target="_blank"></a><img height="139" alt="" src="http://www.blogjava.net/images/blogjava_net/swing/1.png" width="288" border="0" /><br />
</p>
<p style="font-weight: bold"><span style="color: #008000"><span style="font-family: Georgia">分离模型编程接口</span></span></p>
<p><span style="color: #008000"><span style="font-family: Georgia">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 使用模型的Swing组件必须提供访问修改模型的set/get方法，即模型必须是该组件的限定性属性。比如，JSlider使用BoundedRangeModel接口作为它的模型定义，因此它必须提供下面方法：</span></span></p>
<address><font color="#006666"><span style="color: #008000"><span style="font-family: Arial">&nbsp;&nbsp; public BoundedRangeModel getModel()</span><br />
<span style="font-family: Arial">&nbsp;&nbsp; publicvoidsetModel(BoundedRangeModelmodel)</span></span></font></address>
<p><span style="color: #008000"><span style="font-family: Georgia">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 所有Swing组件有一个共同点：如果你不设置它的模型，组件会在内部创建/安装一个缺省模型。这些缺省模型类的命名习惯是在接口名称之前加上&#8220;Default&#8221;，比如JSlider的构造函数中初始化一个DefaultBoundedModel对象。</span></span></p>
<address><font style="font-family: Arial" size="2"><span style="color: #008000"><font color="#006666">public JSlider(int orientation, int min, int max, intvalue){<br />
&nbsp; checkOrientation(orientation);<br />
&nbsp;&nbsp; this.orientation = orientation;<br />
&nbsp;&nbsp; this.model = newDefaultBoundedRangeModel(value, 0, min, max);<br />
&nbsp;&nbsp; this.model.addChangeListener(changeListener);<br />
&nbsp; updateUI();<br />
}</font><br />
</span></font></address>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果程序接着调用setModel()，缺省的模型就被替换了，比如下面例子：</span></p>
<address style="font-family: Arial"><span style="color: #008000"><font color="#006666">JSlider slider = new JSlider();<br />
BoundedRangeModel myModel = new DefaultBoundedRangeModel() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void setValue(int n){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("SetValue: "+ n);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super.setValue(n);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp; });<br />
slider.setModel(myModel);</font><br />
</span></address>
<p style="font-family: Georgia"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 对于更复杂的模型（如JTable和JList），Swing还提供一个抽象模型实现，让开发者不需要从头开始创建自己的模型。</span></p>
<p style="font-family: Georgia"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如JList的模型接口是ListModel，Swing同时提供了DefaultListModel和AbstractListModel两个类来协助开发者创建自定义的列表模型。</span></p>
<p style="font-weight: bold; font-family: Georgia"><span style="color: #008000">模型改变通知</span></p>
<p style="font-family: Georgia"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当数据或者发生变动时，模型必须通知所有相关方（比如视图）。Swing模型使用前面文章所讲述的事件模型来实现这种触发。Swing中有两种方法发送这种通知：</span></p>
<p style="font-family: Georgia"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 发送轻量级通知，表明状态已经改变，需要Listener通过查询模型，发现什么改变了并做出响应。此方法的优点是单独事件实例能用作该模型的所有通知，同时对于需要频繁通知的事件非常有用（比如JScrollBar被拖动时)。</span></p>
<p style="font-family: Georgia"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 发送状态化通知，详细描述模型如何改变。这种方法需要为每个通知创建一个新的事件实例。当通知通过查询模型不能有效地给Listener提供足够的信息时，此方法非常有用。比如当JTable的一列表格数据发生改变时。</span></p>
<img src ="http://www.blogjava.net/Swing/aggbug/152370.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Swing/" target="_blank">zht</a> 2007-10-12 16:16 <a href="http://www.blogjava.net/Swing/archive/2007/10/12/152370.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Swing框架之Component </title><link>http://www.blogjava.net/Swing/archive/2007/10/12/152280.html</link><dc:creator>zht</dc:creator><author>zht</author><pubDate>Fri, 12 Oct 2007 03:39:00 GMT</pubDate><guid>http://www.blogjava.net/Swing/archive/2007/10/12/152280.html</guid><wfw:comment>http://www.blogjava.net/Swing/comments/152280.html</wfw:comment><comments>http://www.blogjava.net/Swing/archive/2007/10/12/152280.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/Swing/comments/commentRss/152280.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Swing/services/trackbacks/152280.html</trackback:ping><description><![CDATA[<span style="color: #008000">&nbsp;昨天晚上写完Swing的模型和渲染器之后，觉得对Swing的体系结构还是没有说清楚。Swing的基础体系结构中的四大基本对象Component、 Model、UI Delegate以及Renderer都值得详细解释。Swing的树状组件结构（虽然这是用户界面工具通有的特征）也值得详细解释，因为这是完成某些复杂Swing组件，尤其像JTable、JTree、JList和JComboBox这种复杂组件中编辑功能得关键。此外，Swing / AWT的事件模型如Event Dispatching和Propagation和事件处理线程模型也需要详细解释，理解这部份是编写高效率Swing界面的关键。 </span>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 今天从Swing的四大基本对象Component说起。</span></p>
<p><span style="color: #008000">＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝</span></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Component在Swing的MVC模型中担任Controller的角色，同时它也是Swing API中代表具体组件的对象。Component在Swing中对外负责提供API接口，对内负责协调控制Model和UI Delegate（有时可能还包括Renderer）的操作，可以说是整个Swing结构的中心角色。为了方便你回忆Swing的MVC模型，特地将上一篇文章中的Swing模型示意图引了过来：</span></p>
<p><span style="color: #008000"><img alt="" src="http://s3.album.sina.com.cn/pic/4b6047bc02000kk2" /></span></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Component代表Swing对应用程序提供了如下几类编程接口：</span></p>
<ol>
    <li><span style="color: #008000"><font size="2">用户界面的组件树的创建和修改的方法。这包括组件的添加和删除等操作。</font> </span>
    <li><span style="color: #008000"><font size="2">组件属性访问的方法，比如组件位置、组件前后背景色、组件字体等等。</font> </span>
    <li><span style="color: #008000"><font size="2">组件状态及生命周期的管理的方法，比如隐藏和显示、创建和销毁等等。</font> </span>
    <li><span style="color: #008000"><font size="2">组件位置、大小的管理，包括通过布局管理器的方法。</font> </span>
    <li><span style="color: #008000"><font size="2">组件事件处理接口的管理，包括添加、删除等操作。</font> </span></li>
</ol>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 从开发者的角度来看，Component是组件树上的节点、是控制外观和行为的入口、是组件事件的发源地。从Swing组件实现者的角度来看， Component是协调Model和UI Delegate的操作的地方，是低层次事件处理的地方，是高层事件发生的地方，是同父组件和子组件交互的地方。掌握的这些角度，Swing程序员完全可以实现自己的自定义简单组件，当然如需要实现类似于JTable和JTree等复杂的矢量组件，还需要进一步了解Swing的Model和UI Delegate以及Renderer模型。</span></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 对于复合型(Composite)组件很简单，这儿要讲述的是如何实现自定义的组件，比如表盘，比如温度计这些没有标准组件可以使用的组件，那么如何自己实现这种自定义组件呢？</span></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不考虑Model分隔和UI Delegate皮肤分离问题，能够简化自定义Component的模型。总的来说自定义组件需要完成两样基本任务：第一侦听并处理低层事件，根据具体情况改变组件状态，如需要还要发出高级事件；第二，根据当前组件的状态画出当前组件的外观。</span></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 侦听底层的事件是指侦听类似于mouse、keyboard、focus等事件，然后处理此事件，如果发现此事件带有特定语义，表达某种组件行为，则改变当前的组件状态以记录，并触发某种事件通知应用程序进行处理。举例说明，想象你准备实现一个简单的按钮，你可以通过继承JComponent来完成。你可以在按钮初始化时，注册此按钮的鼠标事件侦听器，以侦听发生自己组件上的鼠标事件。当按钮捕获到鼠标按下时，检查鼠标按下的点是否在按钮有效区域内。如果是，则认为当前是一个按钮按下动作，那么改变按钮的状态为按下去，调用repaint方法通知按钮重画成按下去的状态，然后发出 ActionPerformed的事件，通知注册在此按钮上的应用程序的ActionListener处理这个动作。下面是一个简单示意代码：</span></p>
<address><font color="#006666"><span style="color: #008000"><font size="2">public class MyButton extends Jcomponent implements MouseListener{</font><br />
<font size="2">&nbsp;&nbsp;&nbsp; private String text;</font><br />
<font size="2">&nbsp;&nbsp;&nbsp; private boolean pressed=false;</font><br />
<font size="2">&nbsp;&nbsp;&nbsp; private ArrayList&lt;ActionListener&gt; listeners=new ArrayList&lt;ActionListener&gt;();</font><br />
<font size="2">&nbsp;&nbsp;&nbsp; public MyButton(){</font><br />
<font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; addMouseListener(this);//将自己注册为自己的鼠标事件侦听器，监听鼠标事件</font><br />
<font size="2">&nbsp;&nbsp;&nbsp; }</font><br />
<font size="2">&nbsp;&nbsp;&nbsp; ....</font><br />
<font size="2">&nbsp;&nbsp; public void mousePressed(MouseEvent evt){</font><br />
<font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Point p=evt.getPoint();</font><br />
<font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(getBounds().contains(p)){//判断鼠标落点是否在有效区域内。</font><br />
<font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pressed=true; //鼠标点击的含义是按钮被按下！改表按钮状态。</font><br />
<font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; repaint();&nbsp;&nbsp;&nbsp; //通知按钮重画，由原来的抬起状态改变成按下状态。</font><br />
<font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fireActionPerformed(new ActionEvent(this)); //这是一个按钮动作事件，触发它。</font><br />
<font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</font><br />
<font size="2">&nbsp;&nbsp; }</font><br />
<font size="2">&nbsp;&nbsp; public void addActionListener(ActionListener listener){</font><br />
<font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; listeners.add(listener);</font><br />
<font size="2">&nbsp;&nbsp; }</font><br />
<font size="2">&nbsp;&nbsp; public void removeActionListener(ActionListener listener){</font><br />
<font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; listeners.remove(listener);</font><br />
<font size="2">&nbsp;&nbsp; }</font><br />
<font size="2">&nbsp;&nbsp; protected fireActionPerformed(ActionEvent evt){</font><br />
<font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(ActionListener listener:listeners){</font><br />
<font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; listener.actionPerformed(evt);</font><br />
<font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</font><br />
<font size="2">&nbsp;&nbsp; }</font><br />
<font size="2">&nbsp;&nbsp; ...</font><br />
<font size="2">&nbsp;&nbsp; //这儿你要覆盖paint方法，实现按钮状态的重画</font><br />
<font size="2">&nbsp;&nbsp; public void paint(Graphics g){</font><br />
<font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(pressed){</font><br />
<font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //画出按下的样子</font><br />
<font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }else{</font><br />
<font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //画出抬起的样子</font><br />
<font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</font><br />
<font size="2">&nbsp;&nbsp; }</font><br />
<font size="2">}</font></span></font></address>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 上面要注意的是你要自己管理自定义组件的事件监听器，包括addListener和removeListener方法，以及如何触发。这个过程很简单，基本上就是上面的模板来实现添加删除和触发。</span></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 除了要负责事件的处理和新事件的触发，自定义组件第二个要完成的任务就是要根据组件当前的状态改变重画组件的外观。重画组件的外观只需要覆盖public void paint(Graphics g)方法即可以，在这个方法里，你只需要根据当前的组件状态分别画出当前的组件即可。</span></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当然除了上面两个基本准则外，不要忘了添加访问你的组件属性的方法，比如，如果上面的按钮是个二元按钮（相当于 JCheckbox/JToggleButton的那种按钮），你可能需要提供isPressed或者setPressed来获取和设置当前按钮的状态。注意，在设置状态按钮变化的访问方法中，比如setPressed，你需要使用repaint方法通知按钮重新渲染(复杂的实现可能包括触发propertyChange事件，这儿从简)：</span></p>
<address><font color="#006666"><span style="color: #008000"><font size="2">public void setPressed(boolean p){</font><br />
<font size="2">&nbsp;&nbsp;&nbsp; pressed=p;</font><br />
<font size="2">&nbsp;&nbsp;&nbsp; repaint();</font><br />
<font size="2">}</font></span></font></address>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 到此为止，你已经能根据上面的两条准则简单的实现你想要的组件了。但是你发现没有，你的按钮状态和外观行为都被堆到了Component （MyButton)中实现了，而且，对于各个平台都是一个样子，不能换皮肤。这对于比较简单、不想要皮肤的组件，可能没有什么，但是对于复杂的组件，比如JTable或者甚至Excel类似的电子表格的那种组件，你把数据（组件状态)和外观堆在这儿实现就严重违反了MVC原则。</span></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如何简化这种组件的实现呢？使你实现的此种组件容易维护、扩展以及重用，皮肤容易换呢？这就需要Swing结构中的另外三个元素：Model、UI Delegate和Renderer，后面的几个文章将讲述Model、UI Delegate和Renderer帮你逐步实现一个复杂、灵活、可扩展、高效的矢量组件。</span></p>
<p><span style="color: #008000">=====================================================</span></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 今天这样讲，不知道讲明白没有。当初刚开始学习Swing的时候，还不了解Swing的这种MVC结构，因此当时自己做的自定义组件都是这样写的，没有单独的Model和可以定制的UI Delegate，更不用说Renderer了。但是我觉得自己的这个学习过程，恰恰是人们学习Swing的最佳途径，先简化模型，然后逐步扩展，直到了解Swing模型的全部图像。</span></p>
<font color="#008000">=====================================================================================<br />
昨晚回去后还是觉得Component对象本身说的太简单，想来想去，觉得内容实在是太多，有必要补充两个续文说明Component的其它概念。今天介绍Swing组件paint方法的处理流程，这个流程能使我们理解许多Swing机制。明天续文讲述Swing事件处理器、双缓冲和布局管理器等原理。
<p><font face="Georgia" size="2">＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝</font></p>
<p><font face="Georgia" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Swing组件的paint方法是内部接口方法，一般用户不要直接调用这个方法，它总是在事件调度线程中调用。一般说来除了系统刷新事件触发这个方法，Component的repaint也触发这个方法的调用。repaint方法常用于当组件状态发生变化时刷新界面使用。repaint方法是Swing中少数几个线程安全的方法，可以在任何线程中调用它。它的原理是往事件队列中post一个PAINT事件。由于事件队列的事件是被事件调度线程同步执行的，所以这个方法总是线程安全的。事件调度线程从PAINT事件中获取事件源组件，从系统申请到图形设备资源后，调用该组件的update方法。update是AWT时代遗留下来的产物，本意是AWT组件画好组件背景后，再调用paint方法画出组件的前景。Swing出现后这个方法就被弃用了，所有逻辑都转到paint方法里。Update只是简单地调用paint方法来完成组件的渲染。老的Java教材上经常可以看到，所谓repaint调度update方法，update接着调用paint方法，自定义组件需要重载paint方法等话语，就是因为这个历史造成的。</font></p>
<p><font face="Georgia" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 上篇文章中的MyButton的paint方法实现是一个非常老式的做法。现在JComponent的实现已经把paint方法改造成可以嵌套多重机制地方，这些机制包括层次渲染、边框、透明背景、双缓冲以及皮肤等。这些机制分别实现不同目的的组件提供了方便。</font></p>
<p><font face="Georgia" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 图形用户界面的组件按照其在组件树上的角色可以分为容器组件和叶组件。Swing模型把叶组件当作是特殊、没有子组件的容器组件，只是JComponent继承Container类，所有Swing组件继承JComponent的原因。</font></p>
<p><font face="Georgia" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JComponent在paint方法中首先根据组件是否需要使用双缓冲，封装好图形设备对象，然后经过一番处理后调用paintComponent方法画出自身，然后调用paintBorder画出边框，最后调用paintChildren来完成子组件的渲染。</font></p>
<p><font face="Georgia" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; paintComponent意思是画出组件自身，不包括子组件。因此前一文章中的MyButton可以通过覆盖paintComponent方法来完成MyButton的重画。在JComponent实现中，JDK 6的paintComponent的代码为：</font></p>
<address><font face="Arial" color="#006666" size="2">&nbsp;&nbsp;&nbsp; protected void paintComponent(Graphics g) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (ui != null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Graphics scratchGraphics = (g == null) ? null : g.create();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ui.update(scratchGraphics, this);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; finally {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; scratchGraphics.dispose();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }</font></address>
<p><font face="Georgia" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这个方法首先检测组件是否安装了UI Delegate，如果安装了就将渲染过程代理给UI Delegate。这儿是嵌入皮肤的地方。JDK 6中JComponent对应的UI Delegate的update方法缺省的实现是：</font></p>
<address><font face="Arial" size="2"><font color="#006666">public void update(Graphics g, JComponent c) {<br />
&nbsp;if (c.isOpaque()) {<br />
&nbsp;&nbsp;&nbsp;&nbsp; g.setColor(c.getBackground());<br />
&nbsp;&nbsp;&nbsp;&nbsp; g.fillRect(0, 0, c.getWidth(),c.getHeight());<br />
&nbsp;}<br />
&nbsp;paint(g, c);<br />
</font>}</font></address>
<p><font face="Georgia" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 可以看出，背景透明机制在这儿实现。首先UI Delegate对象判断Component是否背景透明的，如果不是透明的，则使用背景色填充整个Component区域，然后调用paint(g, c)来完成组件在这种LookAndFeel种的渲染。了解了这些后，我们几乎就明白了Swing如何实现背景透明和如何切换皮肤。由于后面的文章还会对UI Delegate和皮肤机制详细描述，这儿就到此为止。</font></p>
<p style="font-family: Georgia"><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 目前还不要求实现皮肤，在这种情况下只需要重载paintComponent方法就行了，如果需要背景透明机制，可以模仿上面代码，MyButton的paintComponent可以这样写：</font></p>
<address><font face="Arial" color="#006666">public void paintComponent(Graphics g) {<br />
&nbsp;if (isOpaque()) {<br />
&nbsp;&nbsp;&nbsp;&nbsp; g.setColor(getBackground());<br />
&nbsp;&nbsp;&nbsp;&nbsp; g.fillRect(0, 0, getWidth(), getHeight());<br />
&nbsp;}<br />
&nbsp;if(pressed){//按钮按下去了<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //画出按下的样子<br />
&nbsp;}else{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //画出抬起的样子<br />
&nbsp;}<br />
}</font></address>
<p style="font-family: Georgia"><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; paintBorder意思是画出组件的边框。Swing所有组件都有边框的概念，就是说可以为任何组件添加各种边框，包括自定义的边框。JDK 6中JComponent的paintBorder的实现是这样的：</font></p>
<address><font face="Arial" color="#006666">protected void paintBorder(Graphics g) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Border border = getBorder();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (border != null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; border.paintBorder(this, g, 0, 0, getWidth(), getHeight());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
}</font></address>
<p style="font-family: Georgia"><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 非常直接，如果自己有border，就将画自己边框的任务代理给了这个border，并传给它图形设备和边界参数。Swing缺省提供了大量的各种各样的边框。同样可以定义自己的边框，实现方法就是继承Border类，Border类中有三个方法要实现，它们的含义如下：</font></p>
<address><font face="Arial" color="#006666">public interface Border<br />
{<br />
&nbsp;&nbsp;&nbsp; //这儿是画出组件边框的地方。<br />
&nbsp;&nbsp;&nbsp; void paintBorder(Component c, Graphics g, int x, int y, int width, int height);<br />
&nbsp; //这儿是定义边框边界的地方，组件可以根据这信息，安排它的内容。<br />
&nbsp;&nbsp;&nbsp; Insets getBorderInsets(Component c);<br />
//边框的背景是不是透明的？不是透明的要负责画出边框的背景。是透明的使用组件的背景。<br />
&nbsp;&nbsp;&nbsp; boolean isBorderOpaque();<br />
}</font></address>
<p style="font-family: Georgia"><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这儿实现一个简单的红线边框作为演示：</font></p>
<address><font face="Arial" color="#006666">public class RedLineBorder implements Border{<br />
&nbsp;&nbsp;&nbsp; public void paintBorder(Component c, Graphics g, int x, int y, int width, int height){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g.setColor(Color.red);//设置为红色<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g.drawRect(x,y, width, height);//画出边框<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; public Insets getBorderInsets(Component c){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return new Insets(1,1,1,1); //四周都是1<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; public boolean isBorderOpaque(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false; //背景透明<br />
&nbsp;&nbsp;&nbsp; }<br />
}</font></address>
<p style="font-family: Georgia"><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; paintChildren完成容器类组件的子组件的渲染。JDK缺省的实现是调用各个自组件的paint方法。一般来说不需要重载这个方法。如果想改变诸如组件Z-order遮挡顺序，可以覆盖这个方法，从相反顺序调用组件的paint方法。</font></p>
<p><font size="2"><span style="font-family: Georgia">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 到这儿我们对Swing的结构有了更深化的理解，UI Delegate机制也已经初露倪端。还有几个重要Swing Component概念或者机制没有讲，明天的续文再对它们做出说明。</span></font></p>
<br />
=================================================================================<br />
<div class="middleSize" id="articleContent">
<p style="margin-bottom: 0cm"><font face="Georgia" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Swing的事件处理过程为：事件调度线程(Event Dispatch Thread)从事件队列(EventQueue)中获取底层系统捕获的原生事件，如鼠标、键盘、焦点、PAINT事件等。接着调用该事件源组件的dispachEvent。该方法过滤出特殊事件后，调用processEvent进行处理。processEvent方法根据事件类型调用注册在这个组件上的相应事件处理器函数。事件处理器函数根据这些事件的特征，判断出用户的期望行为，然后根据期望行为改变组件的状态，然后根据需要刷新组件外观，触发带有特定语义的高级事件。此事件继续传播下去，直至调用应用程序注册在该组件上的处理器函数。下图是这个过程的示意图：</font></p>
<div><a href="http://blog.sina.com.cn/main/html/showpic.html#url=http://s9.album.sina.com.cn/pic/4b6047bc02000knw" target="_blank"></a></div>
<div>&nbsp; <a href="http://blog.sina.com.cn/main/html/showpic.html#url=http://s9.album.sina.com.cn/pic/4b6047bc02000kp8" target="_blank"><img alt="" src="http://s9.album.sina.com.cn/pic/4b6047bc02000kp8" border="0" /></a></div>
<p style="margin-bottom: 0cm"><font face="Georgia" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 上图所示意的过程简要说就是：</font></p>
<p style="margin-bottom: 0cm"><font face="Georgia" size="2">Pump an Event-&gt;Dispatch &amp; Process Event-&gt;MouseListener.mousePressed-&gt;fireActionPerformed-&gt;ActionListener.actionPeformed-&gt;Do database query and display result to a table-&gt;Return from actionPerformed-&gt;Return from fireActionPerformed-&gt;Return from MouseListener.mousePressed-&gt;Pump another Event.</font></p>
<p style="margin-bottom: 0cm"><font face="Georgia" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 事件调度线程在应用程序事件处理函数actionPerformed没有完成之前是不能处理下一个事件的，如果应用程序处理函数是一个时间复杂的任务(比如查询数据库并将结果显示到表格中)，后面包括PAINT事件将在长时间内得不到执行。由于PAINT事件负责将界面更新，所以这就使用户界面失去响应。</font></p>
<p style="margin-bottom: 0cm"><font face="Georgia" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 打一个比方，事件处理线程就像进入某城唯一的单行道一样，事件相当于汽车。有种PAINT汽车负责为城市运输非常重要的生活物资。但是有一天，PAINT前面有一辆汽车突然坏掉了，司机下来修车。但是这车太难修，一修就是几天，结果后面的PAINT汽车无法前进，物资无法按时运到城里。市民急了，市长虽然不停的打电话催PAINT公司，但即使PAINT公司多添加几辆车也没用。由于进城的唯一条路被那辆车给占着，所以再多的PAINT车也只能堵在路上。<br />
</font></p>
<p style="margin-bottom: 0cm"><font face="Georgia" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不了解Swing的这种事件处理模型的人往往将时间复杂的任务放在处理函数中完成，这是造成Swing应用程序速度很慢的原因。用户触发这个动作，用户界面就失去了响应，于是给用户的感觉就是Swing太慢了。其实这个错误是程序员造成的，并不是Swing的过失。</font></p>
<blockquote dir="ltr" style="margin-right: 0px">
<p style="margin-bottom: 0cm; font-family: Georgia"><font color="#006666" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 说点题外话，所有采用这种事件模型的用户界面工具都会产生这种问题，包括SWT、GTK、MFC等流行的用户界面工具。之所以只有Swing被误解，主要是和Swing的历史、市场时机、商业宣传策略和心理学相关的。</font></p>
<p style="margin-bottom: 0cm; font-family: Georgia"><font color="#006666" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 首先Swing的历史和市场时机极差。Swing出现早期性能也差、错误也多，而Java程序员脱身于传统图形界面工具，对于Swing这种新的事件处理模型并不太了解，而此时正处于Java第一轮狂热的时期，大家都满怀希望做了大量的Swing应用程序，而这些程序中大量存在这种错误方法。于是市场上涌现了大批的这种程序。自从那个时代，因为这些程序，Swing被贴上了慢的标签。又由于当时的Swing界面也丑，和一般的Windows程序风格炯异，更加深人们的这种印象。这种印象一直持续到现在，像烙印一样深深的刻在人们的脑海里。</font></p>
<p style="margin-bottom: 0cm; font-family: Georgia"><font color="#006666" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 其次，Swing还有一个致命的问题，就是没有涌现出一个具有标识性的好程序，这是造成它比SWT印象惨的原因。为什么SWT采用相同的事件处理模型，而获得了速度快的声誉呢？这是因为人们当时对于Java做桌面应用的期望心理达到了低谷，而SWT的出现恰恰是伴随Eclipse出现的，早期的Eclipse的确是在速度快、界面漂亮，这一扫当时人们认为Java慢，Java界面丑陋，Java无法做桌面应用的印象，继而这个印象被加在SWT身上，人们认为Eclipse速度快、漂亮是因为SWT，其实如果你知道Swing/SWT事件处理模型的话，你就明白功劳是Eclipse开发者的，Eclipse界面漂亮其实要归功于Eclipse界面设计专家，他们的高水平造就了这个好的IDE，从而也抬起了SWT的声誉。而Swing的名誉恰恰就被早期Swing低水平开发者给毁了。</font></p>
<p style="margin-bottom: 0cm; font-family: Georgia"><font color="#006666" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 再次, 这和商业宣传策略有关。IBM和Eclipse很懂得市场宣传，人们不是认为Java慢吗，就宣传SWT使用原生组件，人们不是认为Swing丑陋、风格炯异吧，就宣传SWT风格一致性，人们不是认为Java不能做桌面应用吗，就宣传基于SWT的Eclipse。其实这一切的背后原因只是&#8220;人&#8221;的不同，Eclipse的开发者和Swing应用程序的开发者，Swing和SWT技术差异并没有造成那么大的差别，如果是相近能力的人使用他们开发的话，应该能做出相近的产品。这可以从现在Eclipse和NetBeans、Intellij IDEA、JDeveloper和JBuilder看的出来。</font></p>
<p style="margin-bottom: 0cm"><font color="#006666"><font style="font-family: Georgia" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 最后，人类有一个心理学现象，就是一旦形成对某种事物的印象，很难摆脱旧的认识，有时甚至人们不愿意承认摆在眼前的事实。总而言之，Swing和SWT不同遭遇是因为历史、市场时机、商业宣传策略、心理学的种种原因造成的。</font><br />
</font></p>
</blockquote>
<p style="margin-bottom: 0cm"><font face="Georgia" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 那么如何避免这个问题，编写响应速度快的Swing应用程序呢？在SwingWorker的javadoc中有这样两条原则：</font></p>
<p style="margin-bottom: 0cm"><font face="Georgia" size="2">Time-consuming tasks should not be run on the Event Dispatch Thread. Otherwise the application becomes unresponsive. 耗时任务不要放到事件调度线程上执行，否则程序就会失去响应。</font></p>
<p style="margin-bottom: 0cm"><font face="Georgia" size="2">Swing components should be accessed on the Event Dispatch Thread only. Swing组件只能在事件调度线程上访问。</font></p>
<p style="margin-bottom: 0cm"><font face="Georgia" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 因此处理耗时任务时，首先要启动一个专门线程，将当前任务交给这个线程处理，而当前处理函数立即返回，继续处理后面未决的事件。这就像前面塞车的例子似的，那个司机只要简单的把车开到路边或者人行道上修理，整个公路系统就会恢复运转。</font></p>
<p style="margin-bottom: 0cm"><font face="Georgia" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 其次，在为耗时任务启动的线程访问Swing组件时，要使用SwingUtilties. invokeLater或者SwingUtilities.invokeAndWait来访问，invokeLater和invokeAndWait的参数都是一个Runnable对象，这个Runnable对象将被像普通事件处理函数一样在事件调度线程上执行。这两个函数的区别是，invokeLater不阻塞当前任务线程，invokeAndWait阻塞当前线程，直到Runnable对象被执行返回才继续。在前面塞车的例子中，司机在路边修车解决了塞车问题，但是他突然想起来要家里办些事情，这时他就可以打个电话让家里开车来。假如修车不受这件事情的影响，比如叫家人送他朋友一本书，他可以继续修车，这时就相当于invokeLater；假如修车受影响，比如缺少某个汽车零件，叫家人给他送过来，那么在家人来之前，他就没法继续修车，这时就相当于invokeAndWait。</font></p>
<p style="margin-bottom: 0cm"><font face="Georgia" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 下面举一个例子说明这两点，比如按下查询按钮，查询数据量很大的数据库，并显示在一个表中，这个过程需要给用户一个进度提示，并且能动态显示表格数据动态增加的过程。假设按钮的处理函数是myButton_actionPerformed，则：</font></p>
<address style="margin-bottom: 0cm"><font face="Arial" color="#006666">void myButton_actionPerformed(ActionEvent evt){<br />
&nbsp;&nbsp;&nbsp;&nbsp; new MyQueryTask().start();<br />
}<br />
public class MyQueryTask extends Thread{<br />
&nbsp;&nbsp;&nbsp; public void run(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //查询数据库<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; final ResultSet result=...;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; / /显示记录<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(;result.next();){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //往表的Model中添加一行数据，并更新进度条，注意这都是访问组件<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SwingUtilities.invokeLater(new Runnable(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void run(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; addRecord(result);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp; ....<br />
&nbsp;&nbsp; }<br />
&nbsp;&nbsp; void addRecord(ResultSet result){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //往表格中添加数据<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jTable.add....<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //更新进度条<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jProgress.setValue(....);<br />
&nbsp;&nbsp;&nbsp; }<br />
}</font></address>
<p style="margin-bottom: 0cm"><font face="Georgia" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JDK1.6以后，Swing提供了一个专门的类SwingWorker能帮你解决这个编程范式，你所需要做的就是继承这个类，重载doInBackground，然后在actionPeformed中调用它的execute方法，并通过publish/process方法来更新界面。SwingWorker的主要方法和它们的作用在下面的示意图：</font></p>
<p style="margin-bottom: 0cm"><a href="http://blog.sina.com.cn/main/html/showpic.html#url=http://s10.album.sina.com.cn/pic/4b6047bc02000knx" target="_blank"><img alt="" src="http://s10.album.sina.com.cn/pic/4b6047bc02000knx" border="0" /></a></p>
<p style="margin-bottom: 0cm"><font face="Georgia" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 从上面示意图可以看出，SwingWorker实际上不过是封装了前面我所说的例子中的MyQueryTask，并做了更详尽的考虑。execute方法相当于MyQueryTask线程start，它启动这个后台线程并立刻返回。SwingWorker可以注册PropertyChangeListener，这些listener都被在事件调度线程上执行，相当于MyQueryTask中的那些访问组件的Runnable对象。另外，publish、setProgress只不过是特殊的property事件吧，process和done不过是响应publish和PropertyChangeEvent.DONE这个事件的方法罢了。因此我们很容易将上面的例子改成SwingWorker的版本：</font></p>
<address style="margin-bottom: 0cm"><font face="Arial" color="#006666">void myButton_actionPerformed(ActionEvent evt){<br />
&nbsp;&nbsp;&nbsp; new MyQueryTask().execute();<br />
}<br />
<br />
public class MyQueryTask extends SwingWorker{<br />
&nbsp;&nbsp;&nbsp; public void doInBackground(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //查询数据库<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; final ResultSet result=...;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //显示记录<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(;result.next();){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //往表的Model中添加一行数据，并更新进度条，注意这都是访问组件<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; publish(result);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ....<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; public void process(Object ... result){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //往表格中添加数据<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jTable.add....<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //更新进度条<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jProgress.setValue(....);<br />
&nbsp;&nbsp;&nbsp; }<br />
}</font></address>
<p style="margin-bottom: 0cm"><font face="Georgia" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 对于一般的耗时任务这样做是比较普遍的，但是有一些任务是一旦触发之后，会周期性的触发，如何做处理这种任务呢?JDK中提供了两个Timer类帮你完成定时任务，一个是javax.swing.Timer，一个java.util.Timer。使用它们的方法很简单，对于Swing的timer，使用方法如下：</font></p>
<address style="margin-bottom: 0cm"><font face="Arial" color="#006666">public void myActionPerformed(){<br />
&nbsp;&nbsp;&nbsp; //假设点击了某个按钮开始记时<br />
&nbsp;&nbsp;&nbsp; Action myAction=new AbstractAction(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void actionPerformed(ActionEvent e){<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //做周期性的活动，比如显示当前时间<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; Date date=new Date();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jMyDate.setDate(date);//jMyDate是个假想的组件，能显示日期时间<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; };<br />
&nbsp;&nbsp;&nbsp; new Timer(1000, myAction).start();<br />
}</font></address>
<p style="margin-bottom: 0cm"><font face="Georgia" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; java.util.Timer类似，只不过使用TimerTask完成动作封装。注意这两个Timer有一个关键的区别：Swing的Timer的事件处理都是在事件调度线程上进行的，因而它里面的操作可以直接访问Swing组件。而java.util.Timer则可能在其他线程上，因而访问组件时要使用SwingUtilities.invokeLater和invokeAndWait来进行。这一点要记住。</font></p>
<p style="margin-bottom: 0cm"><font face="Georgia" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果要了解更详细的信息，可以查阅SwingWorker、Swing Timer和util Timer这些类javadoc文档和其他网上资料。最重要的是要记住了那两条原则。<br />
<br />
============================================================================<br />
</p>
<p style="margin-bottom: 0cm"><font face="Georgia" size="3"><strong>Swing事件与事件处理器模型</strong></font></p>
<p style="margin-bottom: 0cm"><font face="Georgia" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Component在Swing模型中是事件触发源。前一篇文章在描述Swing的事件处理模型时就已经提到了这个事件处理过程。简单来说，Swing组件在侦听到原生事件并处理后，往往产生新的逻辑事件。逻辑事件是某些组件所特有的、具有特定语义的事件，比如JButton按下时产生ActionEvent、JComboBox一项被选中时产生ItemEvent，等等。和原生事件不同，它们并不被派发到系统事件队列中，而是由组件直接触发。事件处理器作为组件的观察者添加到组件上并侦听触发的事件。假设事件名叫XXX，Swing中实现这个模式的一般模式是：</font></p>
<p style="margin-bottom: 0cm"><font face="Georgia" size="2">1.定义一个XXXEvent</font></p>
<address style="margin-bottom: 0cm"><font color="#006666"><font face="Arial" size="2">public class XXXEvent extends Event{</font><br />
<font face="Arial" size="2">&nbsp;&nbsp;&nbsp; ...</font><br />
<font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">public void XXXEvent(Object src){</font><br />
<font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">super(src);</font><br />
<font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">...</font><br />
<font face="Arial" size="2">&nbsp;&nbsp;&nbsp;&nbsp;</font><font face="Arial" size="2">}</font><br />
<font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font face="Arial" color="#006666" size="2">...<br />
}</font></address>
<blockquote dir="ltr" style="margin-right: 0px">
<blockquote dir="ltr" style="margin-right: 0px"></blockquote></blockquote>
<p style="margin-bottom: 0cm"><font face="Georgia" size="2">2.定义一个事件处理器接口XXXListener，声明所有和该事件相关的处理方法：</font></p>
<address style="margin-bottom: 0cm"><font color="#006666"><font face="Arial" size="2">public interface XXXListener extends EventListener{</font><br />
</font><font color="#006666"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; void action1(XXXEvent evt);</font></font> <font face="Arial" size="2"><br />
</font><font color="#006666"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">void action2(XXXEvent evt);</font></font> <font face="Arial" size="2"><br />
</font><font color="#006666"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font face="Arial" color="#006666" size="2">...<br />
}</font></address>
<blockquote dir="ltr" style="margin-right: 0px"></blockquote>
<p style="margin-bottom: 0cm"><font face="Georgia" size="2">3.在触发它的组件中定义一下方法：</font></p>
<blockquote dir="ltr" style="margin-right: 0px">
<blockquote dir="ltr" style="margin-right: 0px"></blockquote>
<blockquote dir="ltr" style="margin-right: 0px"></blockquote>
<blockquote dir="ltr" style="margin-right: 0px">
<blockquote dir="ltr" style="margin-right: 0px"></blockquote></blockquote>
<blockquote dir="ltr" style="margin-right: 0px">
<blockquote dir="ltr" style="margin-right: 0px"></blockquote></blockquote>
<blockquote dir="ltr" style="margin-right: 0px">
<blockquote dir="ltr" style="margin-right: 0px"></blockquote>
<blockquote dir="ltr" style="margin-right: 0px"></blockquote></blockquote></blockquote>
<address style="margin-bottom: 0cm"><font color="#006666"><font face="Arial" size="2">public class MyComponent extends Jcomponent{<br />
</font><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font face="Arial" size="2">...<br />
</font><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font face="Arial" size="2">//存放事件处理器的队列<br />
</font><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font face="Arial" size="2">private ArrayList&lt;XXXListener&gt;xxxListeners=new ArrayList&lt;XXXListener&gt;();<br />
</font><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font face="Arial" size="2">//定义以下各种方法，访问符号用public，以方便添加删除处理器<br />
</font><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font face="Arial" size="2">public void addXXXListener(XXXListener listener){<br />
</font><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font face="Arial" size="2">xxxListeners.add(listener);<br />
</font><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font face="Arial" size="2">}<br />
</font><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font face="Arial" size="2">public void removeXXXListener(XXXListener listener){<br />
</font><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font face="Arial" size="2">xxxListeners.remove(listener);<br />
</font><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font face="Arial" size="2">}<br />
</font><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font face="Arial" size="2">//定义各种触发(fire)action1、action2...的方法，注意一般使用protected，以便继承和扩展<br />
</font><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font face="Arial" size="2">//每一个action都要定义一个相应触发(fire)的方法<br />
</font><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font face="Arial" size="2">protected void fireAction1(XXXEvent evt){<br />
</font><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font face="Arial" size="2">for(XXXListener listener:xxxListeners){<br />
</font><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font face="Arial" size="2">listener.action1(evt);<br />
</font><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font face="Arial" size="2">}<br />
</font><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font face="Arial" size="2">}<br />
</font><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font face="Arial" size="2">protected void fireAction2(XXXEvent evt){<br />
</font><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font face="Arial" size="2">for(XXXListener listener:xxxListeners){<br />
</font><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font face="Arial" size="2">listener.action2(evt);<br />
</font><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font face="Arial" size="2">}<br />
</font><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font face="Arial" size="2">}<br />
</font><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font face="Arial" size="2">...<br />
</font><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font face="Arial" size="2">//在某些地方，比如鼠标处理函数中触发相应的动作<br />
</font><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font face="Arial" size="2">void myMouseReleased(MouseEvent evt){<br />
</font><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font face="Arial" size="2">...<br />
</font><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font face="Arial" size="2">if(应该触发action1)<br />
</font><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font face="Arial" size="2">fireAction1(new XXXEvent(this));<br />
</font><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font face="Arial" size="2">...<br />
</font><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font face="Arial" size="2">if(应该触发action2)<br />
</font><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font face="Arial" size="2">fireAction2(new XXXEvent(this));<br />
</font><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font> <font face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font face="Arial" size="2">...<br />
</font><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;&nbsp;</font></font><font face="Arial" color="#006666" size="2">}<br />
}</font></address>
<p style="margin-bottom: 0cm"><font face="Georgia" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XXXEvent、XXXListener、addXXXListener、removeXXXListener以及各种fireAction函数多是重复性代码，有些Java IDE如JBuilder中能够根据开发者的指定参数的自动生成这些代码。</font></p>
<p style="margin-bottom: 0cm"><font face="Georgia" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 实际上这个观察者模式的编程范式可以推广到任何JavaBeans，不一定是可视化的Swing组件。以前曾经见过JBuilder做的一个所谓数据库操作的JavaBeans，它没有界面，但它和Swing组件完全一样添加删除处理器。它的功能是异步操作数据库，在数据操作完了之后触发注册在上面的事件处理器，该事件处理器就可以将查询结果展现在表格中，或者输出成报表等等。</font></p>
<p style="margin-bottom: 0cm"><font face="Georgia" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在这个模型中，JavaBeans本身既可以是事件源（被观察对象），也可以是事件处理器（观察者），JavaBeans也可以侦听自身的事件并且处理。比如前面文章所提的MyButton在处理鼠标事件时就是自己侦听自己发出的鼠标事件，自己既是事件源，又是事件处理器，形成自反系统。各种各样的JavaBeans通过这种机制联系成一张事件网，各种JavaBeans就是这个网上的节点，而它们之间的事件触发与事件处理关系就是这张网络上的线。当某个节点被外界或自身发出的事件所触发时，行成了事件的传播。这个过程很像网络上节点的振动引起周围周围节点振动的模型。下图示意了这种JavaBeans之间的事件网：</font></p>
<p style="margin-bottom: 0cm"><a href="http://blog.sina.com.cn/main/html/showpic.html#url=http://s11.album.sina.com.cn/pic/4b6047bc02000kqm" target="_blank"><font face="Georgia" size="2"><img src="http://s11.album.sina.com.cn/pic/4b6047bc02000kqm" border="0"  alt="" /></font></a></p>
<p style="margin-bottom: 0cm"><font face="Georgia" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 例如new JscrollPane(new JtextArea())这个系统，它里面包括两个JScrollBar和一个JTextArea，当鼠标拖动事件触发JScrollBar时，JScrollBar处理了这个鼠标拖动事件，并发出滚动条拖动事件，这个事件传播给JTextArea，JTextArea处理这个拖动事件，相应的更新自己显示的内容，如果JTextArea之后又根据更新发出了一个新的事件，这个事件便会继续传播下去。</font></p>
<p style="margin-bottom: 0cm"><font face="Georgia" size="3"><strong>Swing布局管理器</strong></font></p>
<p style="margin-bottom: 0cm"><font face="Georgia" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 现在高级图形用户界面工具一般都包括布局管理器机制。什么叫做布局管理器？如果所有窗口的大小是不变的，那么我们在往窗口中添加组件时，只要将组件的拖放到固定位置、调整好尺寸就可以了，就像VB的界面工具一样。可大多数情况并非如此，用户经常需要调整窗口的大小，以便和其他程序协同工作。这种情况下，在传统界面工具中，比如VB，就需要显式的侦听窗口尺寸调整事件，根据当前窗口的大小重新计算并调整各个组件的大小和位置。AWT/SWT/Swing将这个过程自动化、模块化了，抽象出一个布局管理器来负责管理界面组件的布局。</font></p>
<p style="margin-bottom: 0cm"><font face="Georgia" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 它们实现原理是相似的：容器类组件侦听初始化、invalide/validate以及容器尺寸调整等事件，一旦发生这些事件，容器类组件检查自己是否配置了布局管理器，如果没有，则不做任何事情；如果有，则将容器内组件的布局代理给布局管理器，让它来完成容器内组件的重新布局。</font></p>
<p style="margin-bottom: 0cm"><font face="Georgia" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 容器管理器对象对实现两类接口：LayoutManager和LayoutManager2，LayoutManager2是LayoutManager的一个扩展，允许组件在添加时指定位置参数。它们的定义和含义如下：</font></p>
<blockquote dir="ltr" style="margin-right: 0px"></blockquote>
<blockquote dir="ltr" style="margin-right: 0px"></blockquote>
<address style="margin-bottom: 0cm"><font color="#006666"><font style="font-family: Arial" face="Georgia" size="2">public interface LayoutManager {<br />
</font><font style="font-family: Arial" face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font style="font-family: Arial" face="Georgia" size="2">//添加组件comp，并和name关联起来，name可以作为位置等特殊含义参数来使用<br />
</font><font style="font-family: Arial" face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font style="font-family: Arial" face="Georgia" size="2">void addLayoutComponent(String name, Component comp);<br />
</font><font style="font-family: Arial" face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font style="font-family: Arial" face="Georgia" size="2">//删除组件comp<br />
</font><font style="font-family: Arial" face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font style="font-family: Arial" face="Georgia" size="2">void removeLayoutComponent(Component comp);<br />
</font><font style="font-family: Arial" face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font style="font-family: Arial" face="Georgia" size="2">//根据容器内的当前组件，计算容器parent的最优尺寸。<br />
</font><font style="font-family: Arial" face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font style="font-family: Arial" face="Georgia" size="2">Dimension preferredLayoutSize(Container parent);<br />
</font><font style="font-family: Arial" face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font style="font-family: Arial" face="Georgia" size="2">//根据容器内的当前组件，计算容器parent的最小尺寸。<br />
</font><font style="font-family: Arial" face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font style="font-family: Arial" face="Georgia" size="2">Dimension minimumLayoutSize(Container parent);<br />
</font><font style="font-family: Arial" face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font style="font-family: Arial" face="Georgia" size="2">//重新布局容器parent，这儿是主要布局逻辑所在。<br />
</font><font style="font-family: Arial" face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font style="font-family: Arial" face="Georgia" size="2">void layoutContainer(Container parent);<br />
}<br />
public interface LayoutManager2 extends LayoutManager {<br />
</font><font style="font-family: Arial" face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font style="font-family: Arial" face="Georgia" size="2">//添加组件comp，constraints用作指定如何以及位置的参数，这个函数主要是弥补LayoutManager版的addLayoutComponent表达能力欠缺而添加。<br />
</font><font style="font-family: Arial" face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font style="font-family: Arial" face="Georgia" size="2">void addLayoutComponent(Component comp, Object constraints);<br />
</font><font style="font-family: Arial" face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font style="font-family: Arial" face="Georgia" size="2">//根据容器内的当前组件，计算容器parent的最大尺寸。看来除了最优、最小，某些情况下还是需要知道最大。<br />
</font><font style="font-family: Arial" face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font style="font-family: Arial" face="Georgia" size="2">public Dimension maximumLayoutSize(Container target);<br />
</font><font style="font-family: Arial" face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font style="font-family: Arial" face="Georgia" size="2">//指定水平方向上组件之间的相对对齐方式，0表示和源组件对齐，1表示远离源组件。<br />
</font><font style="font-family: Arial" face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font style="font-family: Arial" face="Georgia" size="2">public float getLayoutAlignmentX(Container target);<br />
</font><font style="font-family: Arial" face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font style="font-family: Arial" face="Georgia" size="2">//指定垂直方向上组件之间的相对对齐方式，0表示和源组件对齐，1表示远离源组件。<br />
</font><font style="font-family: Arial" face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font style="font-family: Arial" face="Georgia" size="2">public float getLayoutAlignmentY(Container target);<br />
</font><font style="font-family: Arial" face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font color="#006666"><font style="font-family: Arial" face="Georgia" size="2">//invalidate这个布局管理器，有时布局管理器为了计算迅速，可能第一次计算之后就将一些数据给缓冲，但是后容器内的组件数目发生变化，这儿的缓冲值就需要调用这个方法通知更新<br />
</font><font style="font-family: Arial" face="Arial" size="2">&nbsp;&nbsp;&nbsp;</font></font> <font face="Georgia" size="2"><font color="#006666"><span style="font-family: Arial">public void invalidateLayout(Container target);</span><br style="font-family: Arial" />
<br />
<br />
<span style="font-family: Arial">}</span></font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Swing在java.awt和javax.swing中都分别提供大量的布局管理器，这些布局管理器有简单的如FlowLayout，有复杂的如GridBadLayout。用户还可以自己定义自己的布局管理器，由于篇幅原因，这儿略去例子。</font></address>
<p style="margin-bottom: 0cm"><font face="Georgia" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Java 6中在布局管理中引入了BaseLine / Anchor的概念，能协助Java IDE的用户界面设计工具，方便用户来设计布局组件。NetBeans的Matisse组件首先引入了一个GroupLayout布局管理器，结合Matisse使用，提供了非常方便的布局管理和界面设计。GroupLayout和BaseLine/Anchor概念以及Matisse可以说是Java界面设计工具的一大进步，可以说足以成为Java桌面应用史上的一个里程碑。在这之前，缺乏有力的界面设计工具是Java在桌面应用失败的一个重要原因。虽然Anchor概念早就在Delphi界面设计工具出现过，但是这个工具的出现还是Java界面设计史上的一大事件。随着Java 6桌面应用支持的增强，以及NetBeans Matisse之类界面设计工具的出现，使得Java桌面应用时代已经到来。Seeing is believing，你不妨试一下就知道了。</font></p>
<p style="margin-bottom: 0cm"><font face="Georgia" size="2">＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝</font></p>
<p style="margin-bottom: 0cm"><font face="Georgia" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 本想再加一节讲述Swing双缓冲机制，但是想到双缓冲并不是Swing模型的核心概念，没有它并不影响理解Swing的总体模型，因此打算把它作为以后的一篇专门技术文章来写。</font></p>
<p style="margin-bottom: 0cm"><font face="Georgia" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这样Swing模型中的Component部分就算是描述完了，从明天开始，讲述Swing模型中的另外三个重要概念：Model、UI Delegate和Renderer。</font></p>
<p style="margin-bottom: 0cm"><br />
</font></font></p>
<br />
</div>
<img src ="http://www.blogjava.net/Swing/aggbug/152280.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Swing/" target="_blank">zht</a> 2007-10-12 11:39 <a href="http://www.blogjava.net/Swing/archive/2007/10/12/152280.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>AWT/SWT/Swing大比较之一：模型设计与实现 </title><link>http://www.blogjava.net/Swing/archive/2007/10/12/152244.html</link><dc:creator>zht</dc:creator><author>zht</author><pubDate>Fri, 12 Oct 2007 02:10:00 GMT</pubDate><guid>http://www.blogjava.net/Swing/archive/2007/10/12/152244.html</guid><wfw:comment>http://www.blogjava.net/Swing/comments/152244.html</wfw:comment><comments>http://www.blogjava.net/Swing/archive/2007/10/12/152244.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/Swing/comments/commentRss/152244.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Swing/services/trackbacks/152244.html</trackback:ping><description><![CDATA[<span style="color: #008000">&nbsp; 前几天由于网络问题，访问不了新浪网，现在准备重新开始博客写作。最近打算写的内容主要包括Java性能、Swing和SWT的比较、Swing方面的一些技术。 </span>
<p style="font-family: Georgia"><span style="color: #008000">=====================================================</span></p>
<p style="font-family: Georgia"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 总的来说Swing/AWT和SWT在事件处理机制上是类似的，窗口组件的树状结构也是类似的。图形用户界面系统在事件处理设计上有两大类，一类是单线程模型，一类是多线程模型。在事件处理机制上，三者都是遵循单线程规则。</span></p>
<p style="font-family: Georgia"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 单线成模型对于事件处理不保证线程安全性(Thread Safety)，所有的事件处理都在Event Dispatch Thread(EDT)上进行，此一类事件模型通常叫做单线程模型。这种模型规定所有对组件的访问操作必须在EDT上完成。为什么对于组件的访问需要在EDT上完成？这主要是为了保证对于组件状态的改变是同步的，保证了界面组件的可确定性。这中模型是大部分图形用户界面工具采用的模型，包括Swing/AWT、SWT、GTK、WinForm等等。</span></p>
<p style="font-family: Georgia"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这种模型的好处是，结构设计和代码实现都比较简单，避免了为了实现线程同步的复杂处理。但是也带来了一些问题，最常见的问题是，程序员容易将长时间复杂任务的处理放在事件处理函数完成，造成EDT线程被阻塞，给用户造成界面失去响应的错觉。其实人们对于Swing速度慢和反映迟钝的感觉大部分来源于此，简单的说，是程序员的问题，而不是Swing自身的问题，是因为程序员没有理解这种事件处理机制造成的。其实在SWT、GTK、WinForm等任何以这种事件模型为基础的工具都会出现。重现的方法就是你简单的将长时间处理的任务放在事件处理函数中，你的用户界面就会失去响应。</span></p>
<p style="font-family: Georgia"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如何解决这种问题？通用的办法就是采用异步线程处理长时间任务。但是还要记住的是，在这种任务中对于界面的更新要采用SwingUtilities.invokeLater或者在SWT采用Synchronize方法，将访问操作放到EDT上进行。关于如何写一个有效处理长时间任务的Swing程序，将会在其他文章中描述。</span></p>
<p style="font-family: Georgia"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 多线程模型中，所有的事件处理都是在异步线程中进行，界面组件同步访问的操作需要程序员来保证。这种模型设计本身很复杂，而且对于程序员来说要求比较高，必须对线程同步编程很熟悉，而且花在同步上的操作影响了平台的性能。一般现在的图形界面工具都不再采用这种方式。</span></p>
<p style="font-family: Georgia"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 下面比较一下Swing/AWT/SWT在API、GUI特征以及实现方法的不同。</span></p>
<p style="font-family: Georgia"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在API上，Swing和AWT是兼容的，SWT是单独的一套接口。</span></p>
<p style="font-family: Georgia"><span style="color: #008000">1.Swing/AWT的组件在生成时可以脱离父组件独立存在，SWT必须有父组件存在。这主要是由于SWT的资源是自己管理，SWT程序必须负责释放不用的资源，为了避免这种释放资源的重复性，SWT父组件被设计成在析构时自动递归调用子组件的析构函数。</span></p>
<p style="font-family: Georgia"><span style="color: #008000">2.Swing/AWT的资源回收由垃圾收集器负责，SWT必须由SWT程序显式释放。</span></p>
<p style="font-family: Georgia"><span style="color: #008000">3.Swing/AWT的事件线程循环不需要程序员显式启动，SWT必须要程序员来显式启动。</span></p>
<p style="font-family: Georgia"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Swing/AWT和SWT在布局管理器上是类似的，没有太大区别。</span></p>
<p style="font-family: Georgia"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在GUI特征上，有两个比较层面，一个是组件种类，一个是组件本身特征。在理解这些特征时，一定要牢牢记住这样一个准则：Java是平台无关的语言，因此它对应用程序所提供的API一定要各个平台都相同，GUI特征其实也是API，所以GUI的特征必须在各个平台都相同。</span></p>
<p style="font-family: Georgia"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 组件类型上，AWT采用的是最大公约数方法，而Swing/SWT采用的是最小公倍数方法。简单的说AWT是各个平台所有组件集合的交集，而Swing和SWT则是各个平台组件的并集。下图所示，假设操作系统平台OS1上提供组件{C1, C2, C3, C4, C7}，而OS2提供{C1, C2,C3, C4, C6}，OS3提供{C1, C2, C3, C4, C5}，那么其中的阴影部分就是AWT所实现的组件，由于C5、C6和C7是各个平台所特有的，因此AWT中就不包含这些组件。比如Table和Tree在Java支持某些操作系统平台中不包含，所以在AWT中就没有Table和Tree。由于AWT的组件太贫乏，所以AWT在现在复杂应用程序几乎没有什么用。Swing和SWT提供的组件是各平台所有组件的并集，这样就解决AWT的组件贫乏的缺陷。也就是说，Swing和SWT提供的组件包括C1到C7的所有组件，而AWT只提供C1到C4的所有组件。</span></p>
<p style="font-family: Georgia"><a href="http://blog.sina.com.cn/main/html/showpic.html#url=http://s12.album.sina.com.cn/pic/4b6047bc02000kdb" target="_blank"><span style="color: #008000"><img title="http://s12.album.sina.com.cn/pic/4b6047bc02000kdb" alt="http://s12.album.sina.com.cn/pic/4b6047bc02000kdb" src="http://s12.album.sina.com.cn/pic/4b6047bc02000kdb" border="1" /></span></a></p>
<p style="font-family: Georgia"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 从组件本身的特征来看，SWT和AWT采用了相同的策略，即最大公约数，而Swing采用的是最小公倍数。如下图所示，假设对于同一个组件C，如果它在OS1上提供的特征包括{a,b,c,d,e}，而OS2上提供的特征包括{a,b,c}，而OS3包括的特征有{a,b,c,d}，那么SWT和AWT提供的组件特征只包括{a,b,c}，而Swing的包含的平台特征包括{a, b, c, d, e}。比如由于Solaris平台上的按钮不提供对于图标的支持，所以SWT和AWT的独立按钮就不提供对于按钮图标的支持，而Swing提供按钮图标的支持。</span></p>
<p style="font-family: Georgia"><a href="http://blog.sina.com.cn/main/html/showpic.html#url=http://s1.album.sina.com.cn/pic/4b6047bc02000kdc" target="_blank"><span style="color: #008000"><img title="http://s1.album.sina.com.cn/pic/4b6047bc02000kdc" alt="http://s1.album.sina.com.cn/pic/4b6047bc02000kdc" src="http://s1.album.sina.com.cn/pic/4b6047bc02000kdc" border="1" /></span></a></p>
<p style="margin-bottom: 0cm; font-family: Georgia"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在实现方法上，AWT采用Java+Native C Peer(一种JNI调用）方法，SWT根据各平台的不同情况，一部分组件使用Java+Java Peer+JNI Wrapper，一部分采用Java模拟的方法，而Swing则采用所有组件都纯粹Java模拟的方法。</span></p>
<p style="margin-bottom: 0cm; font-family: Georgia"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AWT的接口和各操作系统组件之间的差别采用Native C Peer实现的方法来填平，下面是它的结构示意图：</span></p>
<p style="font-family: Georgia"><a href="http://blog.sina.com.cn/main/html/showpic.html#url=http://s2.album.sina.com.cn/pic/4b6047bc02000kdd" target="_blank"><span style="color: #008000"><img title="http://s2.album.sina.com.cn/pic/4b6047bc02000kdd" alt="http://s2.album.sina.com.cn/pic/4b6047bc02000kdd" src="http://s2.album.sina.com.cn/pic/4b6047bc02000kdd" border="1" /></span></a></p>
<p style="font-family: Georgia"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 其中AWT Native Peer Impl部分都是C语言写的，在各种操作系统上是不同的，但是它们和AWT Component组件之间的AWT-Peer JNI调用接口是不变的，AWT Component的Java代码实现在各个平台上都是相同的，最后AWT Component向Application提供同一的API接口。</span></p>
<p style="font-family: Georgia"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SWT同AWT不同，它在Native Component上进行了一层薄薄的JNI封装，所有操作系统的API调用都被映射到一个JNI调用上，然后SWT通过Java代码组合这些JNI调用实现同一的API，下面是其结构示意图：</span></p>
<p style="font-family: Georgia"><a href="http://blog.sina.com.cn/main/html/showpic.html#url=http://s3.album.sina.com.cn/pic/4b6047bc02000kde" target="_blank"><span style="color: #008000"><img title="http://s3.album.sina.com.cn/pic/4b6047bc02000kde" alt="http://s3.album.sina.com.cn/pic/4b6047bc02000kde" src="http://s3.album.sina.com.cn/pic/4b6047bc02000kde" border="1" /></span></a></p>
<p style="font-family: Georgia"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 因此SWT的Java代码实现部分在各个平台是不同的，它的C代码部分即JNI Wrapper部分只是一个各平台GUI API的JNI简单映射，SWT通过Java Peer在各平台的不同实现填平了各平台差异，从而给Application提供同一的API接口。当然SWT对于某种平台上缺少的组件采用的方法和Swing基本类似。</span></p>
<p style="font-family: Georgia"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Swing和上两中方式完全不同，它直接调用Java2D，抛弃了本地操作系统平台组件的实现，完全自己画出来了整个组件，当然Java2D底层也是调用平台的图形系统。下面是它的示意图：</span></p>
<p style="font-family: Georgia"><a href="http://blog.sina.com.cn/main/html/showpic.html#url=http://s4.album.sina.com.cn/pic/4b6047bc02000kdf" target="_blank"><span style="color: #008000"><img title="http://s4.album.sina.com.cn/pic/4b6047bc02000kdf" alt="http://s4.album.sina.com.cn/pic/4b6047bc02000kdf" src="http://s4.album.sina.com.cn/pic/4b6047bc02000kdf" border="1" /></span></a></p>
<p style="font-family: Georgia"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当然Swing是建立在AWT基础上的，对于一些顶层容器类如Frame / Dialog / Window以及Applet是直接采用AWT的，这儿为了方便并没有画出。由于Java2D API是个平台无关的，因此Swing的Java实现代码在个平台都是一样的，都是一套，当然除了与Swing的Look And Feel相关的东西以外。</span></p>
<p style="font-family: Georgia"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 由于篇幅原因，今天就先谈到这儿，至于这三种不同架构、实现会对它们的性能和外观以及编程难度产生什么影响，我们以后的文章逐渐讨论。</span></p>
<div class="invisible" id="reference"><span style="color: #008000">文章引用自：</span><a href=" ?></a><span style=" target=" COLOR: #008000"> </span></div>
<img src ="http://www.blogjava.net/Swing/aggbug/152244.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Swing/" target="_blank">zht</a> 2007-10-12 10:10 <a href="http://www.blogjava.net/Swing/archive/2007/10/12/152244.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用Swing编写全屏程序 </title><link>http://www.blogjava.net/Swing/archive/2007/10/12/152240.html</link><dc:creator>zht</dc:creator><author>zht</author><pubDate>Fri, 12 Oct 2007 02:02:00 GMT</pubDate><guid>http://www.blogjava.net/Swing/archive/2007/10/12/152240.html</guid><wfw:comment>http://www.blogjava.net/Swing/comments/152240.html</wfw:comment><comments>http://www.blogjava.net/Swing/archive/2007/10/12/152240.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Swing/comments/commentRss/152240.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Swing/services/trackbacks/152240.html</trackback:ping><description><![CDATA[<span style="color: #008000">&nbsp;也许用到的机会很少，但JDK还是为我们提供了这个的功能。像许多软件中的打印预览功能，还有某些文本编辑器中为了获得更大的编辑画面，也用到了全屏幕模式，如果你有兴趣写一个像ACDSee这样的软件，使用全屏幕模式可以让用户看到更大的图片画面。 </span>
<p><span style="color: #008000"><span style="font-family: Georgia">　　如何使用全屏幕模式？</span></span></p>
<p><span style="color: #008000"><span style="font-family: Georgia">　　关键是java.awt.*里面的两个与显示设备有关的类：GraphicsEnvironment和GraphicsDevice。</span></span></p>
<p><span style="color: #008000"><span style="font-family: Georgia">　　GraphicsEnvironment为Java应用程序提供了特定平台的 GraphicsDevice对象和 Font 对象集合。这些GraphicsDevice可以是各种本机和远端机器的资源，如屏幕、打印机或者是Image Buffer,甚至是Graphics2D绘图方法的目标对象。</span></span></p>
<p><span style="color: #008000"><span style="font-family: Georgia">　　而GraphicsDevice就是指特定的图形环境了，如屏幕和打印设备等。这样，我们就可以用GraphicsDevice来操纵屏幕了。GraphicsDevice提供的setFullScreenWindow()方法就是设置全屏幕用的。</span></span></p>
<p><span style="color: #008000"><span style="font-family: Georgia">　　由于GraphicsEnvironment的构造器是受保护的(protected)，我们不能直接构造一个GraphicsEnvironment 对象来获得GraphicsDevice对象。幸好它提供了getLocalGraphicsEnvironment()方法，用来获得一个 GraphicsEnvironment实例：</span></span></p>
<p><span style="color: #008000"><span style="font-family: Georgia">　　GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();</span></span></p>
<p><span style="color: #008000"><span style="font-family: Georgia">　　有了GraphicsEnvironment可以调用getDefaultScreenDevice方法获得当前的屏幕设备了：</span></span></p>
<p><span style="color: #008000"><span style="font-family: Georgia">　　GraphicsDevice gd = ge.getDefaultScreenDevice();</span></span></p>
<p><span style="color: #008000"><span style="font-family: Georgia">　　自己动手体验一下</span></span></p>
<p><span style="color: #008000"><span style="font-family: Georgia">　　有了上面的简介，写一个实例来体验一下吧：</span></span></p>
<p><font size="2"><span style="color: #008000"><span style="font-family: Arial">import java.awt.Color;</span><br />
<span style="font-family: Arial">import java.awt.Font;</span><br />
<span style="font-family: Arial">import java.awt.Graphics;</span><br />
<span style="font-family: Arial">import java.awt.GraphicsDevice;</span><br />
<span style="font-family: Arial">import java.awt.GraphicsEnvironment;</span><br />
<span style="font-family: Arial">import java.awt.event.MouseAdapter;</span><br />
<span style="font-family: Arial">import java.awt.event.MouseEvent;</span><br />
<span style="font-family: Arial">import javax.swing.JWindow;</span><br />
<span style="font-family: Arial">public class FullScreenTest {</span><br />
<span style="font-family: Arial">&nbsp;&nbsp;&nbsp; public static void main(String[] args) {</span><br />
<span style="font-family: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GraphicsEnvironment ge =</span><br style="font-family: Arial" />
<br />
<span style="font-family: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GraphicsEnvironment.getLocalGraphicsEnvironment();</span><br style="font-family: Arial" />
<br />
<span style="font-family: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GraphicsDevice gd = ge.getDefaultScreenDevice();</span><br style="font-family: Arial" />
<br />
<span style="font-family: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FullScreenWindow myWindow = new FullScreenWindow();</span><br style="font-family: Arial" />
<br />
<span style="font-family: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ( gd.isFullScreenSupported() )</span><br style="font-family: Arial" />
<br />
<span style="font-family: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gd.setFullScreenWindow(myWindow);</span><br style="font-family: Arial" />
<br />
<span style="font-family: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else</span><br style="font-family: Arial" />
<br />
<span style="font-family: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Unsupported full screen.");</span><br style="font-family: Arial" />
<br />
<span style="font-family: Arial">&nbsp;&nbsp;&nbsp; }</span><br />
<span style="font-family: Arial">&nbsp;&nbsp;&nbsp; static class FullScreenWindow extends JWindow {</span><br style="font-family: Arial" />
<br />
<span style="font-family: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public FullScreenWindow() {</span><br style="font-family: Arial" />
<br />
<span style="font-family: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.addMouseListener(new MouseAdapter() {</span><br style="font-family: Arial" />
<br />
<span style="font-family: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void mousePressed(MouseEvent evt) {</span><br style="font-family: Arial" />
<br />
<span style="font-family: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; quit();</span><br style="font-family: Arial" />
<br />
<span style="font-family: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span><br style="font-family: Arial" />
<br />
<span style="font-family: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });</span><br style="font-family: Arial" />
<br />
<span style="font-family: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span><br style="font-family: Arial" />
<br />
<span style="font-family: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void quit() {</span><br style="font-family: Arial" />
<br />
<span style="font-family: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.dispose();</span><br style="font-family: Arial" />
<br />
<span style="font-family: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span><br />
<span style="font-family: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void paint(Graphics g) {</span><br style="font-family: Arial" />
<br />
<span style="font-family: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g.setFont(new Font("Arial",Font.BOLD,30));</span><br style="font-family: Arial" />
<br />
<span style="font-family: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g.setColor(Color.RED);</span><br style="font-family: Arial" />
<br />
<span style="font-family: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g.drawString("这是全屏幕模式",100,100);</span><br style="font-family: Arial" />
<br />
<span style="font-family: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span><br style="font-family: Arial" />
<br />
<span style="font-family: Arial">&nbsp;&nbsp;&nbsp; }</span><br style="font-family: Arial" />
<br />
<span style="font-family: Arial">}</span></span></font></p>
<div class="invisible" id="reference"><span style="color: #008000">文章引用自：</span><a href=" ?></a><span style=" target=" COLOR: #008000"> </span></div>
<img src ="http://www.blogjava.net/Swing/aggbug/152240.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Swing/" target="_blank">zht</a> 2007-10-12 10:02 <a href="http://www.blogjava.net/Swing/archive/2007/10/12/152240.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一些小例子(Ing)</title><link>http://www.blogjava.net/Swing/archive/2007/09/14/145073.html</link><dc:creator>zht</dc:creator><author>zht</author><pubDate>Fri, 14 Sep 2007 02:49:00 GMT</pubDate><guid>http://www.blogjava.net/Swing/archive/2007/09/14/145073.html</guid><wfw:comment>http://www.blogjava.net/Swing/comments/145073.html</wfw:comment><comments>http://www.blogjava.net/Swing/archive/2007/09/14/145073.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/Swing/comments/commentRss/145073.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Swing/services/trackbacks/145073.html</trackback:ping><description><![CDATA[<span style="color: #008000"><span style="color: #ff0000">平时别人问得一些小例子，做出来放在这，以后不断添加<br />
需要的也可以留言提出。<br />
</span><br />
1、使用Insert来判断JTextField是插入模式还是修改模式<br />
</span>
<p><span style="color: #008000">public class InsertTextField extends JPanel {</span></p>
<p><span style="color: #008000">&nbsp;/**<br />
&nbsp; * @param args<br />
&nbsp; */<br />
&nbsp;public static void main(String[] args) {<br />
&nbsp;&nbsp;JFrame jf = new JFrame();<br />
&nbsp;&nbsp;jf.setContentPane(new InsertTextField());<br />
&nbsp;&nbsp;jf.pack();<br />
&nbsp;&nbsp;jf.setVisible(true);<br />
&nbsp;}<br />
&nbsp;public InsertTextField() {<br />
&nbsp;&nbsp;this.setLayout(new FlowLayout());<br />
&nbsp;&nbsp;final JTextField jtf = new JTextField(10);<br />
&nbsp;&nbsp;final IntegerDocument id = new IntegerDocument(10);<br />
&nbsp;&nbsp;jtf.addKeyListener(new KeyListener() {<br />
&nbsp;&nbsp;&nbsp;@Override<br />
&nbsp;&nbsp;&nbsp;public void keyPressed(KeyEvent e) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;if (e.getKeyCode() == KeyEvent.VK_INSERT) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id.setFlag();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;@Override<br />
&nbsp;&nbsp;&nbsp;public void keyReleased(KeyEvent e) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;jtf.setCaretPosition(jtf.getText().length());<br />
&nbsp;&nbsp;&nbsp;}</span></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp;@Override<br />
&nbsp;&nbsp;&nbsp;public void keyTyped(KeyEvent e) {</span></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp;}</span></p>
<p><span style="color: #008000">&nbsp;&nbsp;});<br />
&nbsp;&nbsp;jtf.setDocument(id);<br />
&nbsp;&nbsp;this.add(jtf);<br />
&nbsp;}</span></p>
<p><span style="color: #008000">&nbsp;class IntegerDocument extends PlainDocument {</span></p>
<p><span style="color: #008000">&nbsp;&nbsp;private boolean flag = false;</span></p>
<p><span style="color: #008000">&nbsp;&nbsp;public IntegerDocument(int n) {<br />
&nbsp;&nbsp;&nbsp;super();<br />
&nbsp;&nbsp;}</span></p>
<p><span style="color: #008000">&nbsp;&nbsp;public void setFlag() {<br />
&nbsp;&nbsp;&nbsp;boolean f = flag ? flag = false : (flag = true);<br />
&nbsp;&nbsp;}</span></p>
<p><span style="color: #008000">&nbsp;&nbsp;public void insertString(int offset, String s, AttributeSet ats)<br />
&nbsp;&nbsp;&nbsp;&nbsp;throws BadLocationException {</span></p>
<p><span style="color: #008000">&nbsp;&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;super.insertString(offset, s, ats);<br />
&nbsp;&nbsp;&nbsp;&nbsp;if (flag) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;remove(offset - 1, 1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;} catch (Exception ex) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;Toolkit.getDefaultToolkit().beep();<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
&nbsp;}<br />
}<br />
2、拖动JPanel，还有一些小bug，以后有空再改<br />
</p>
<p>/**<br />
&nbsp;* DragPanel Class<br />
&nbsp;* <br />
&nbsp;* author:zhangtao<br />
&nbsp;* mail:zht_dream@hotmail.com<br />
&nbsp;* 2007-9-26<br />
&nbsp;*/<br />
public class DragPanel extends JPanel implements MouseListener,<br />
&nbsp;&nbsp;MouseMotionListener {</p>
<p>&nbsp;JPanel north_JP;</p>
<p>&nbsp;JScrollPane cen_JP;</p>
<p>&nbsp;/**<br />
&nbsp; * @param args<br />
&nbsp; */<br />
&nbsp;public static void main(String[] args) {<br />
&nbsp;&nbsp;JFrame jf = new JFrame();<br />
&nbsp;&nbsp;jf.setContentPane(new DragPanel());<br />
&nbsp;&nbsp;jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);<br />
&nbsp;&nbsp;jf.pack();<br />
&nbsp;&nbsp;jf.setVisible(true);<br />
&nbsp;}</p>
<p>&nbsp;public DragPanel() {<br />
&nbsp;&nbsp;this.setLayout(new BorderLayout());<br />
&nbsp;&nbsp;north_JP = new JPanel();<br />
&nbsp;&nbsp;north_JP.add(new JButton("1"));<br />
&nbsp;&nbsp;north_JP.add(new JButton("2"));<br />
&nbsp;&nbsp;north_JP.add(new JButton("3"));<br />
&nbsp;&nbsp;north_JP.add(new JButton("4"));<br />
&nbsp;&nbsp;this.add("North", north_JP);<br />
&nbsp;&nbsp;cen_JP = new JScrollPane();<br />
&nbsp;&nbsp;cen_JP.setViewportView(new JTree());<br />
&nbsp;&nbsp;this.add(cen_JP);<br />
&nbsp;&nbsp;north_JP.addMouseListener(this);<br />
&nbsp;&nbsp;north_JP.addMouseMotionListener(this);</p>
<p>&nbsp;}</p>
<p>&nbsp;public void mouseClicked(MouseEvent e) {</p>
<p>&nbsp;}</p>
<p>&nbsp;public void mouseEntered(MouseEvent e) {<br />
&nbsp;&nbsp;// TODO Auto-generated method stub</p>
<p>&nbsp;}</p>
<p>&nbsp;public void mouseExited(MouseEvent e) {<br />
&nbsp;&nbsp;System.out.println("exit");<br />
&nbsp;&nbsp;this.setCursor(Cursor.getDefaultCursor());<br />
&nbsp;}</p>
<p>&nbsp;public void mousePressed(MouseEvent e) {<br />
&nbsp;&nbsp;// TODO Auto-generated method stub</p>
<p>&nbsp;}</p>
<p>&nbsp;public void mouseReleased(MouseEvent e) {<br />
&nbsp;&nbsp;this.setCursor(Cursor.getDefaultCursor());<br />
&nbsp;}</p>
<p>&nbsp;boolean dragFlag = false;</p>
<p>&nbsp;public void mouseDragged(MouseEvent e) {<br />
&nbsp;&nbsp;dragFlag = true;<br />
&nbsp;&nbsp;if (flag) {<br />
&nbsp;&nbsp;&nbsp;this.setCursor(new Cursor(Cursor.N_RESIZE_CURSOR));<br />
&nbsp;&nbsp;&nbsp;Point po = e.getPoint();<br />
&nbsp;&nbsp;&nbsp;Dimension di = north_JP.getPreferredSize();<br />
&nbsp;&nbsp;&nbsp;north_JP.setPreferredSize(new Dimension(di.width,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(north_JP.getY() + po.y)));<br />
&nbsp;&nbsp;&nbsp;north_JP.revalidate();<br />
&nbsp;&nbsp;&nbsp;north_JP.repaint();<br />
&nbsp;&nbsp;}<br />
&nbsp;}</p>
<p>&nbsp;boolean flag = false;</p>
<p>&nbsp;public void mouseMoved(MouseEvent e) {<br />
&nbsp;&nbsp;Point point = e.getPoint();<br />
&nbsp;&nbsp;this.setCursor(Cursor.getDefaultCursor());<br />
&nbsp;&nbsp;flag = false;<br />
&nbsp;&nbsp;dragFlag = false;<br />
&nbsp;&nbsp;if (((north_JP.getY() + north_JP.getHeight() - point.y) &lt; 5)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&amp;&amp; ((north_JP.getY() + north_JP.getHeight() - point.y) &gt; -5)) {<br />
&nbsp;&nbsp;&nbsp;this.setCursor(new Cursor(Cursor.N_RESIZE_CURSOR));<br />
&nbsp;&nbsp;&nbsp;flag = true;<br />
&nbsp;&nbsp;} else {<br />
&nbsp;&nbsp;&nbsp;this.setCursor(Cursor.getDefaultCursor());<br />
&nbsp;&nbsp;}<br />
&nbsp;}</p>
<p>}<br />
<br />
3、载入修改properties的例子<br />
</p>
<p>package proper;</p>
<p>import java.awt.BorderLayout;<br />
import java.awt.FlowLayout;<br />
import java.awt.event.ActionEvent;<br />
import java.awt.event.ActionListener;<br />
import java.io.File;<br />
import java.io.FileInputStream;<br />
import java.io.FileNotFoundException;<br />
import java.io.FileOutputStream;<br />
import java.io.IOException;<br />
import java.util.Iterator;<br />
import java.util.Map;<br />
import java.util.Properties;<br />
import java.util.Vector;<br />
import java.util.Map.Entry;</p>
<p>import javax.swing.JButton;<br />
import javax.swing.JFrame;<br />
import javax.swing.JPanel;<br />
import javax.swing.JScrollPane;<br />
import javax.swing.JTable;<br />
import javax.swing.table.DefaultTableModel;</p>
<p>/**<br />
&nbsp;* <br />
&nbsp;* Test Class<br />
&nbsp;* <br />
&nbsp;* author:zht<br />
&nbsp;* mail:zht_dream@hotmail.com<br />
&nbsp;* 2007-10-31<br />
&nbsp;*/<br />
public class Test extends JPanel implements ActionListener {</p>
<p>&nbsp;/**<br />
&nbsp; * @param args<br />
&nbsp; */<br />
&nbsp;public static void main(String[] args) {<br />
&nbsp;&nbsp;// TODO Auto-generated method stub<br />
&nbsp;&nbsp;Test test = new Test();<br />
&nbsp;&nbsp;JFrame jf = new JFrame();<br />
&nbsp;&nbsp;jf.setContentPane(test);<br />
&nbsp;&nbsp;jf.pack();<br />
&nbsp;&nbsp;jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);<br />
&nbsp;&nbsp;jf.setVisible(true);<br />
&nbsp;}</p>
<p>&nbsp;JTable jt;</p>
<p>&nbsp;JButton modify_JBn;</p>
<p>&nbsp;Properties props = null;</p>
<p>&nbsp;public Test() {<br />
&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;props = loadPro();<br />
&nbsp;&nbsp;} catch (FileNotFoundException e) {<br />
&nbsp;&nbsp;&nbsp;// TODO Auto-generated catch block<br />
&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;} catch (IOException e) {<br />
&nbsp;&nbsp;&nbsp;// TODO Auto-generated catch block<br />
&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;this.setLayout(new BorderLayout());<br />
&nbsp;&nbsp;String[] tn = { "名称", " 值", };<br />
&nbsp;&nbsp;String[][] data = {};<br />
&nbsp;&nbsp;DefaultTableModel defaultModel = new DefaultTableModel(data, tn) {<br />
&nbsp;&nbsp;&nbsp;@Override<br />
&nbsp;&nbsp;&nbsp;public boolean isCellEditable(int row, int column) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;if (column == 0) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return false;<br />
&nbsp;&nbsp;&nbsp;&nbsp;} else<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return true;<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;};<br />
&nbsp;&nbsp;jt = new JTable(defaultModel);<br />
&nbsp;&nbsp;this.add(new JScrollPane(jt));<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;Iterator itor = props.entrySet().iterator();<br />
&nbsp;&nbsp;&nbsp;while (itor.hasNext()) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;Map.Entry vEntry = (Entry) itor.next();<br />
&nbsp;&nbsp;&nbsp;&nbsp;Vector&lt;Object&gt; vv = new Vector&lt;Object&gt;();<br />
&nbsp;&nbsp;&nbsp;&nbsp;vv.add(vEntry.getKey());<br />
&nbsp;&nbsp;&nbsp;&nbsp;vv.add(vEntry.getValue());<br />
&nbsp;&nbsp;&nbsp;&nbsp;//做一些其他的事&#8230;&#8230;<br />
&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(vEntry.getKey());<br />
&nbsp;&nbsp;&nbsp;&nbsp;defaultModel.addRow(vv);<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;modify_JBn = new JButton("modify");<br />
&nbsp;&nbsp;modify_JBn.addActionListener(this);<br />
&nbsp;&nbsp;JPanel jp = new JPanel();<br />
&nbsp;&nbsp;jp.setLayout(new FlowLayout());<br />
&nbsp;&nbsp;jp.add(modify_JBn);<br />
&nbsp;&nbsp;this.add("South", jp);<br />
&nbsp;}</p>
<p>&nbsp;public Properties loadPro() throws FileNotFoundException, IOException {<br />
&nbsp;&nbsp;Properties props = new Properties();<br />
&nbsp;&nbsp;props.load(new FileInputStream(new File("config/config.properties")));<br />
&nbsp;&nbsp;return props;<br />
&nbsp;}</p>
<p>&nbsp;@Override<br />
&nbsp;public void actionPerformed(ActionEvent e) {<br />
&nbsp;&nbsp;for (int i = 0; i &lt; jt.getRowCount(); i++) {<br />
&nbsp;&nbsp;&nbsp;String name = jt.getValueAt(i, 0).toString();<br />
&nbsp;&nbsp;&nbsp;String value = jt.getValueAt(i, 1).toString();<br />
&nbsp;&nbsp;&nbsp;props.setProperty(name, value);<br />
&nbsp;&nbsp;&nbsp;System.out.println("==");<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;FileOutputStream fos;<br />
&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;fos = new FileOutputStream(new File("config/config.properties"));<br />
&nbsp;&nbsp;&nbsp;props.store(fos, "");<br />
&nbsp;&nbsp;} catch (Exception e1) {<br />
&nbsp;&nbsp;&nbsp;// TODO Auto-generated catch block<br />
&nbsp;&nbsp;&nbsp;e1.printStackTrace();<br />
&nbsp;&nbsp;}<br />
&nbsp;}<br />
}<br />
</p>
</span>
<img src ="http://www.blogjava.net/Swing/aggbug/145073.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Swing/" target="_blank">zht</a> 2007-09-14 10:49 <a href="http://www.blogjava.net/Swing/archive/2007/09/14/145073.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SwingUtilities中invokeLater和invokeAndWait的介绍</title><link>http://www.blogjava.net/Swing/archive/2007/07/10/129338.html</link><dc:creator>zht</dc:creator><author>zht</author><pubDate>Tue, 10 Jul 2007 06:28:00 GMT</pubDate><guid>http://www.blogjava.net/Swing/archive/2007/07/10/129338.html</guid><wfw:comment>http://www.blogjava.net/Swing/comments/129338.html</wfw:comment><comments>http://www.blogjava.net/Swing/archive/2007/07/10/129338.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Swing/comments/commentRss/129338.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Swing/services/trackbacks/129338.html</trackback:ping><description><![CDATA[<p style="COLOR: #008000">SwingUtilities中invokeLater和invokeAndWait介绍<br>&nbsp; &nbsp;在Java中Swing是线程不安全的，是单线程的设计，这样的造成结果就是：只能从事件派发线程访问将要在屏幕上绘制的Swing组件。事件派发线程是调用paint和update等回调方法的线程，它还是事件监听器接口中定义的事件处理方法，例如，ActionListener中的actionPerformed方法在事件派发线程中调用。<br>&nbsp; &nbsp;Swing是事件驱动的，所以在回调函数中更新可见的GUI是很自然的事情，比如，有一个按钮被按下，项目列表需要更新时，则通常在与该按钮相关联的事件监听器的actionPerformed方法中来实现该列表的更新，从事件派发线程以外的线程中更新Swing组件是不正常的。<br>&nbsp; &nbsp;有时需要从事件派发线程以外的线程中更新Swing组件，例如，在actionPerformed中有很费时的操作，需要很长时间才能返回，按钮激活后需要很长时间才能看到更新的列表，按钮会长时间保持按下的状态只到actionPerformed返回，一般说来耗时的操作不应该在事件处理方法中执行，因为事件处理返回之前，其他事件是不能触发的，界面类似于卡住的状况，所以在独立的线程上执行比较耗时的操作可能更好，这会立即更新用户界面和释放事件派发线程去派发其他的事件。<br>&nbsp; &nbsp;SwingUtilities类提供了两个方法：invokeLate和invoteAndWait，它们都使事件派发线程上的可运行对象排队。当可运行对象排在事件派发队列的队首时，就调用其run方法。其效果是允许事件派发线程调用另一个线程中的任意一个代码块。<br>&nbsp; &nbsp;只有从事件派发线程才能更新组件。<br>&nbsp; &nbsp;程序示例：更新组件的错误方法<br>&nbsp; &nbsp;startButton.addActionListener(new ActionListener() {<br>&nbsp;&nbsp;&nbsp;public void actionPerformed(ActionEvent e) {<br>&nbsp;&nbsp;&nbsp;&nbsp;GetInfoThread t = new GetInfoThread(Test.this);<br>&nbsp;&nbsp;&nbsp;&nbsp;t.start();<br>&nbsp;&nbsp;&nbsp;&nbsp;startButton.setEnabled(false);<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;});<br>&nbsp;&nbsp;<br>&nbsp;&nbsp;class GetInfoThread extends Thread {<br>&nbsp;Test applet;</p>
<p style="COLOR: #008000">&nbsp;public GetInfoThread(Test applet) {<br>&nbsp;&nbsp;this.applet = applet;<br>&nbsp;}</p>
<p style="COLOR: #008000">&nbsp;&nbsp;public void run() {<br>&nbsp;&nbsp;&nbsp;while (true) {<br>&nbsp;&nbsp;&nbsp;&nbsp;try {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread.sleep(500);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;applet.getProgressBar().setValue(Math.random() * 100);<br>&nbsp;&nbsp;&nbsp;&nbsp;} catch (InterruptedException e) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;}<br>&nbsp;}<br>&nbsp;错误分析：在actionPerformed中，监听器把按钮的允许状态设置为false，由于是在事件派发线程上调用actionPerformed，所以setEnabled是一个有效的操作，但是在GetInfoThread中设置进度条是一个危险的做法，因为事件派发线程以外的线程更新了进度条，所以运行是不正常的。</p>
<p style="COLOR: #008000">&nbsp; &nbsp;1、invokeLater使用<br>&nbsp; &nbsp; class GetInfoThread extends Thread {<br>&nbsp;&nbsp;Test applet;<br>&nbsp;<br>&nbsp;&nbsp;Runnable runx;<br>&nbsp;<br>&nbsp;&nbsp;int value;</p>
<p style="COLOR: #008000">&nbsp;&nbsp;public GetInfoThread(final Test applet) {<br>&nbsp;&nbsp;&nbsp;this.applet = applet;<br>&nbsp;&nbsp;&nbsp;runx = new Runnable() {<br>&nbsp;&nbsp;&nbsp;&nbsp;public void run() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JProgressBar jpb = applet.getProgressBar();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;jpb.setValue(value);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;};<br>&nbsp;&nbsp;}</p>
<p style="COLOR: #008000">&nbsp;&nbsp;&nbsp;public void run() {<br>&nbsp;&nbsp;&nbsp;&nbsp;while (true) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread.sleep(500);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value = (int) (Math.random() * 100);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(value);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SwingUtilities.invokeLater(runx);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} catch (InterruptedException e) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;}<br>&nbsp; &nbsp;<br>&nbsp; &nbsp;2、invokeAndWait<br>&nbsp; &nbsp;与invoikeLater一样，invokeAndWait也把可运行对象排入事件派发线程的队列中，invokeLater在把可运行的对象放入队列后就返回，而invokeAndWait一直等待知道已启动了可运行的run方法才返回。如果一个操作在另外一个操作执行之前必须从一个组件获得信息，则invokeAndWait方法是很有用的。<br>&nbsp; &nbsp;class GetInfoThread extends Thread {<br>&nbsp; &nbsp;Runnable getValue,setValue;<br>&nbsp; &nbsp;int value,currentValue;<br>&nbsp; &nbsp;public GetInfoThread(final Test applet){<br>&nbsp; &nbsp;getValue=new Runnable(){<br>&nbsp; &nbsp;public void run(){<br>&nbsp; &nbsp;&nbsp;JProgressBar pb=applet.getProgressBar();<br>&nbsp; &nbsp;&nbsp;currentValue=pb.getValue();<br>&nbsp; &nbsp;&nbsp;}<br>&nbsp; &nbsp;};<br>&nbsp; &nbsp;setValue=new Runnable(){<br>&nbsp; &nbsp;&nbsp;public void run(){<br>&nbsp; &nbsp;&nbsp;&nbsp;JProgressBar pb=applet.getProgressBar();<br>&nbsp; &nbsp;&nbsp;&nbsp;pb.setValue(value);<br>&nbsp; &nbsp;&nbsp;}<br>&nbsp; &nbsp;}<br>&nbsp; &nbsp;}<br>&nbsp; &nbsp;public void run(){<br>&nbsp; &nbsp;&nbsp;while(true){<br>&nbsp; &nbsp;&nbsp;try{<br>&nbsp; &nbsp;&nbsp;Thread.currentThead().sleep(500);<br>&nbsp; &nbsp;&nbsp;value=(int)(Math.random()*100);<br>&nbsp; &nbsp;&nbsp;try{<br>&nbsp; &nbsp;&nbsp;SwingUtilities.invokeAndWait(getValue);//直到getValue可运行的run方法返回后才返回<br>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;}catch(Exception ex){<br>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;if(currentValue!=value){<br>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;SwingUtilities.invokeLater(setValue);<br>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp; &nbsp;&nbsp;&nbsp;}<br>&nbsp; &nbsp;&nbsp;&nbsp;}catch(Exception ex){<br>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp; &nbsp;&nbsp;}<br>&nbsp; &nbsp;}<br>&nbsp; &nbsp;invokeLater和invoikeAndWait的一个重要区别：可以从事件派发线程中调用invokeLater，却不能从事件派发线程中调用invokeAndWait，从事件派发线程调用invokeAndWait的问题是：invokeAndWait锁定调用它的线程，直到可运行对象从事件派发线程中派发出去并且该可运行的对象的run方法激活，如果从事件派发线程调用invoikeAndWait，则会发生死锁的状况，因为invokeAndWait正在等待事件派发，但是，由于是从事件派发线程中调用invokeAndWait，所以直到invokeAndWait返回后事件才能派发。<br>&nbsp; &nbsp;ex）actionPerformed();返回的时候事件派发线程才能派发线程，而在actionPerformed中使用invokeAndWait则会导致actionPerformed不能返回。所以也就无法派发invokeAndWait中的线程。<br><br>由于Swing是线程不安全的，所以，从事件派发线程之外的线程访问Swing组件是不安全的，SwingUtilities类提供这两种方法用于执行事件派发线程中的代码</p>
<img src ="http://www.blogjava.net/Swing/aggbug/129338.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Swing/" target="_blank">zht</a> 2007-07-10 14:28 <a href="http://www.blogjava.net/Swing/archive/2007/07/10/129338.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计模式Observer的应用</title><link>http://www.blogjava.net/Swing/archive/2007/07/09/128970.html</link><dc:creator>zht</dc:creator><author>zht</author><pubDate>Mon, 09 Jul 2007 01:22:00 GMT</pubDate><guid>http://www.blogjava.net/Swing/archive/2007/07/09/128970.html</guid><wfw:comment>http://www.blogjava.net/Swing/comments/128970.html</wfw:comment><comments>http://www.blogjava.net/Swing/archive/2007/07/09/128970.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Swing/comments/commentRss/128970.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Swing/services/trackbacks/128970.html</trackback:ping><description><![CDATA[<div style="COLOR: #008000">Java深入到一定程度,就不可避免的碰到设计模式(design pattern)这一概念,了解设计模式,将使自己对java中的接口或抽象类应用有更深的理解.设计模式在java的中型系统中应用广泛,遵循一定的编程模式,才能使自己的代码便于理解,易于交流,Observer(观察者)模式是比较常用的一个模式,尤其在界面设计中应用广泛,而本站所关注的是Java在电子商务系统中应用,因此想从电子商务实例中分析Observer的应用.</div>
<p style="COLOR: #008000">虽然网上商店形式多样,每个站点有自己的特色,但也有其一般的共性,单就"商品的变化,以便及时通知订户"这一点,是很多网上商店共有的模式,这一模式类似Observer patern.</p>
<p style="COLOR: #008000">具体的说,如果网上商店中商品在名称 价格等方面有变化,如果系统能自动通知会员,将是网上商店区别传统商店的一大特色.这就需要在商品product中加入Observer这样角色,以便product细节发生变化时,Observer能自动观察到这种变化,并能进行及时的update或notify动作.</p>
<p style="COLOR: #008000"></p>
<p style="COLOR: #008000">Java的API还为为我们提供现成的Observer接口Java.util.Observer.我们只要直接使用它就可以.</p>
<p style="COLOR: #008000">我们必须extends Java.util.Observer才能真正使用它:<br>1.提供Add/Delete observer的方法;<br>2.提供通知(notisfy) 所有observer的方法;</p>
<table cellSpacing=3 cellPadding=0 width="80%" bgColor=#cccccc border=0>
    <tbody>
        <tr>
            <td style="COLOR: #008000">
            <p style="COLOR: #008000">import java.util.Observable;</p>
            <p style="COLOR: #008000">public class product extends Observable {</p>
            <p style="COLOR: #008000">&nbsp;private String name;</p>
            <p style="COLOR: #008000">&nbsp;private float price;<br>&nbsp;public product(){<br>&nbsp;}</p>
            <p style="COLOR: #008000">&nbsp;public String getName() {<br>&nbsp;&nbsp;return name;<br>&nbsp;}</p>
            <p style="COLOR: #008000">&nbsp;public void setName(String name) {<br>&nbsp;&nbsp;this.name = name;<br>&nbsp;&nbsp;//设置变化点 <br>&nbsp;&nbsp;setChanged();<br>&nbsp;&nbsp;notifyObservers(name);</p>
            <p style="COLOR: #008000">&nbsp;}</p>
            <p style="COLOR: #008000">&nbsp;public float getPrice() {<br>&nbsp;&nbsp;return price;<br>&nbsp;}</p>
            <p style="COLOR: #008000">&nbsp;public void setPrice(float price) {<br>&nbsp;&nbsp;this.price = price;<br>&nbsp;&nbsp;//设置变化点<br>&nbsp;&nbsp;setChanged();<br>&nbsp;&nbsp;notifyObservers(new Float(price));</p>
            <p style="COLOR: #008000">&nbsp;}</p>
            <p style="COLOR: #008000">&nbsp;//以下可以是数据库更新 插入命令.<br>&nbsp;public void saveToDb() {<br>&nbsp;&nbsp;//&nbsp; .....................</p>
            <p style="COLOR: #008000">&nbsp;}</p>
            <p style="COLOR: #008000">&nbsp;public static void main(String[] args) {<br>&nbsp;&nbsp;product p=new product();<br>&nbsp;&nbsp;p.addObserver(new NameObserver());<br>&nbsp;&nbsp;p.addObserver(new PriceObserver());<br>&nbsp;&nbsp;p.setPrice(100);<br>&nbsp; p.setName("name");<br>&nbsp;}<br>}</p>
            </td>
        </tr>
    </tbody>
</table>
<p style="COLOR: #008000"><br>我们注意到,在product类中 的setXXX方法中,我们设置了 notify(通知)方法, 当调用setXXX,实际上就触发了notisfyObservers方法,这将通知相应观察者应该采取行动了.</p>
<p style="COLOR: #008000">下面看看这些观察者的代码,他们究竟采取了什么行动:</p>
<table cellSpacing=3 cellPadding=0 width="99%" border=0>
    <tbody>
        <tr>
            <td style="COLOR: #008000">
            <p style="COLOR: #008000">//观察者NameObserver主要用来对产品名称(name)进行观察的<br>public class NameObserver implements Observer{</p>
            <p style="COLOR: #008000">　　private String name=null;</p>
            <p style="COLOR: #008000">　　public void update(Observable obj,Object arg){<br><br>　　　　if (arg <a href="http://www-900.ibm.com/developerWorks/java/l-leditor/index.shtml" target=_blank>instanceof</a> String){</p>
            <p style="COLOR: #008000">　　　　 name=(String)arg;<br>　　　　 //产品名称改变值在name中<br>　　　　 System.out.println("NameObserver :name changet to "+name);</p>
            <p style="COLOR: #008000">　　　　}</p>
            <p style="COLOR: #008000">　　}</p>
            <p style="COLOR: #008000">}</p>
            <p style="COLOR: #008000">//观察者PriceObserver主要用来对产品价格(price)进行观察的<br>public class PriceObserver implements Observer{</p>
            <p style="COLOR: #008000">　　private float price=0;</p>
            <p style="COLOR: #008000">　　public void update(Observable obj,Object arg){<br><br>　　　　if (arg instanceof Float){</p>
            <p style="COLOR: #008000">　　　　 price=((Float)arg).floatValue();<br>　　<br>　　　　 System.out.println("PriceObserver :price changet to "+price);</p>
            <p style="COLOR: #008000">　　　　}</p>
            <p style="COLOR: #008000">　　}</p>
            <p style="COLOR: #008000">}</p>
            </td>
        </tr>
    </tbody>
</table>
<span style="COLOR: #008000">输出结果如下：<br>PriceObserver :price changet to 100.0<br>NameObserver :name changet to name<br></span><br><span style="COLOR: #008000">Swing中的事件驱动就是使用<font style="COLOR: #008000" color=#56b6e9>的Observer模式</font></span>
<img src ="http://www.blogjava.net/Swing/aggbug/128970.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Swing/" target="_blank">zht</a> 2007-07-09 09:22 <a href="http://www.blogjava.net/Swing/archive/2007/07/09/128970.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Swing对JTextPane中字体颜色的设置</title><link>http://www.blogjava.net/Swing/archive/2007/07/09/128965.html</link><dc:creator>zht</dc:creator><author>zht</author><pubDate>Mon, 09 Jul 2007 00:50:00 GMT</pubDate><guid>http://www.blogjava.net/Swing/archive/2007/07/09/128965.html</guid><wfw:comment>http://www.blogjava.net/Swing/comments/128965.html</wfw:comment><comments>http://www.blogjava.net/Swing/archive/2007/07/09/128965.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/Swing/comments/commentRss/128965.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Swing/services/trackbacks/128965.html</trackback:ping><description><![CDATA[<span style="COLOR: #008000">import java.awt.BorderLayout;<br>import java.awt.Color;<br>import java.awt.event.ActionEvent;<br>import java.awt.event.ActionListener;</span>
<p style="COLOR: #008000">import javax.swing.JButton;<br>import javax.swing.JEditorPane;<br>import javax.swing.JPanel;<br>import javax.swing.JScrollPane;<br>import javax.swing.JTextPane;<br>import javax.swing.UIManager;<br>import javax.swing.WindowConstants;<br>import javax.swing.text.AttributeSet;<br>import javax.swing.text.DefaultStyledDocument;<br>import javax.swing.text.Document;<br>import javax.swing.text.EditorKit;<br>import javax.swing.text.MutableAttributeSet;<br>import javax.swing.text.SimpleAttributeSet;<br>import javax.swing.text.StyleConstants;<br>import javax.swing.text.StyledDocument;<br>import javax.swing.text.StyledEditorKit;</p>
<p style="COLOR: #008000">public class NewJFrame extends javax.swing.JFrame implements ActionListener {<br>&nbsp;private JPanel jp1;</p>
<p style="COLOR: #008000">&nbsp;private JButton color;</p>
<p style="COLOR: #008000">&nbsp;private JTextPane jep;</p>
<p style="COLOR: #008000">&nbsp;private JScrollPane jsp;</p>
<p style="COLOR: #008000">&nbsp;private JButton font;</p>
<p style="COLOR: #008000">&nbsp;/**<br>&nbsp; * Auto-generated main method to display this JFrame<br>&nbsp; */<br>&nbsp;public static void main(String[] args) {<br>&nbsp;&nbsp;NewJFrame inst = new NewJFrame();<br>&nbsp;&nbsp;inst.setVisible(true);<br>&nbsp;}</p>
<p style="COLOR: #008000">&nbsp;public NewJFrame() {<br>&nbsp;&nbsp;super();<br>&nbsp;&nbsp;initGUI();<br>&nbsp;}</p>
<p style="COLOR: #008000">&nbsp;private void initGUI() {<br>&nbsp;&nbsp;try {<br>&nbsp;&nbsp;&nbsp;BorderLayout thisLayout = new BorderLayout();<br>&nbsp;&nbsp;&nbsp;getContentPane().setLayout(thisLayout);<br>&nbsp;&nbsp;&nbsp;setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);<br>&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;jp1 = new JPanel();<br>&nbsp;&nbsp;&nbsp;&nbsp;getContentPane().add(jp1, BorderLayout.NORTH);<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;font = new JButton();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;font.addActionListener(this);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;jp1.add(font);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;font.setText("font");<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;color = new JButton();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;jp1.add(color);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;color.addActionListener(this);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;color.setText("color");<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;jsp = new JScrollPane();<br>&nbsp;&nbsp;&nbsp;&nbsp;getContentPane().add(jsp, BorderLayout.CENTER);<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;jep = new JTextPane();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;jsp.setViewportView(jep);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;jep.setDocument(new DefaultStyledDocument());<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;pack();<br>&nbsp;&nbsp;&nbsp;setSize(400, 300);<br>&nbsp;&nbsp;} catch (Exception e) {<br>&nbsp;&nbsp;&nbsp;e.printStackTrace();<br>&nbsp;&nbsp;}<br>&nbsp;}</p>
<p style="COLOR: #008000">&nbsp;public static void setFontSize(JEditorPane editor, int size) {<br>&nbsp;&nbsp;if (editor != null) {<br>&nbsp;&nbsp;&nbsp;if ((size &gt; 0) &amp;&amp; (size &lt; 512)) {<br>&nbsp;&nbsp;&nbsp;&nbsp;MutableAttributeSet attr = new SimpleAttributeSet();<br>&nbsp;&nbsp;&nbsp;&nbsp;StyleConstants.setFontSize(attr, size);<br>&nbsp;&nbsp;&nbsp;&nbsp;setCharacterAttributes(editor, attr, false);<br>&nbsp;&nbsp;&nbsp;} else {<br>&nbsp;&nbsp;&nbsp;&nbsp;UIManager.getLookAndFeel().provideErrorFeedback(editor);<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;}<br>&nbsp;}</p>
<p style="COLOR: #008000">&nbsp;public static void setForeground(JEditorPane editor, Color fg) {<br>&nbsp;&nbsp;if (editor != null) {<br>&nbsp;&nbsp;&nbsp;if (fg != null) {<br>&nbsp;&nbsp;&nbsp;&nbsp;MutableAttributeSet attr = new SimpleAttributeSet();<br>&nbsp;&nbsp;&nbsp;&nbsp;StyleConstants.setForeground(attr, fg);<br>&nbsp;&nbsp;&nbsp;&nbsp;setCharacterAttributes(editor, attr, false);<br>&nbsp;&nbsp;&nbsp;} else {<br>&nbsp;&nbsp;&nbsp;&nbsp;UIManager.getLookAndFeel().provideErrorFeedback(editor);<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;}<br>&nbsp;}</p>
<p style="COLOR: #008000">&nbsp;public static final void setCharacterAttributes(JEditorPane editor,<br>&nbsp;&nbsp;&nbsp;AttributeSet attr, boolean replace) {<br>&nbsp;&nbsp;int p0 = editor.getSelectionStart();<br>&nbsp;&nbsp;int p1 = editor.getSelectionEnd();<br>&nbsp;&nbsp;if (p0 != p1) {<br>&nbsp;&nbsp;&nbsp;StyledDocument doc = getStyledDocument(editor);<br>&nbsp;&nbsp;&nbsp;doc.setCharacterAttributes(p0, p1 - p0, attr, replace);<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;StyledEditorKit k = getStyledEditorKit(editor);<br>&nbsp;&nbsp;MutableAttributeSet inputAttributes = k.getInputAttributes();<br>&nbsp;&nbsp;if (replace) {<br>&nbsp;&nbsp;&nbsp;inputAttributes.removeAttributes(inputAttributes);<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;inputAttributes.addAttributes(attr);<br>&nbsp;}</p>
<p style="COLOR: #008000">&nbsp;protected static final StyledDocument getStyledDocument(JEditorPane e) {<br>&nbsp;&nbsp;Document d = e.getDocument();<br>&nbsp;&nbsp;if (d instanceof StyledDocument) {<br>&nbsp;&nbsp;&nbsp;return (StyledDocument) d;<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;throw new IllegalArgumentException("document must be StyledDocument");<br>&nbsp;}</p>
<p style="COLOR: #008000">&nbsp;protected static final StyledEditorKit getStyledEditorKit(JEditorPane e) {<br>&nbsp;&nbsp;EditorKit k = e.getEditorKit();<br>&nbsp;&nbsp;if (k instanceof StyledEditorKit) {<br>&nbsp;&nbsp;&nbsp;return (StyledEditorKit) k;<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;throw new IllegalArgumentException("EditorKit must be StyledEditorKit");<br>&nbsp;}</p>
<p style="COLOR: #008000">&nbsp;public void actionPerformed(ActionEvent e) {<br>&nbsp;&nbsp;Object obj = e.getSource();<br>&nbsp;&nbsp;if (obj == font) {<br>&nbsp;&nbsp;&nbsp;JEditorPane editor = jep;<br>&nbsp;&nbsp;&nbsp;setFontSize(editor, 20);<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;if (obj == color) {<br>&nbsp;&nbsp;&nbsp;JEditorPane editor = jep;<br>&nbsp;&nbsp;&nbsp;setForeground(editor, Color.red);<br>&nbsp;&nbsp;}<br>&nbsp;}</p>
<p style="COLOR: #008000">}<br>其他操作如下：<br>1、对字体的操作 <br>MutableAttributeSet attr = new SimpleAttributeSet();<br>&nbsp;&nbsp;&nbsp;&nbsp;StyleConstants.setFontFamily(attr, family);<br>&nbsp;&nbsp;&nbsp;&nbsp;setCharacterAttributes(editor, attr, false); <br>family为字体<br>2、对字体大小的操作<br>MutableAttributeSet attr = new SimpleAttributeSet();<br>&nbsp;&nbsp;&nbsp;&nbsp;StyleConstants.setFontSize(attr, size);<br>&nbsp;&nbsp;&nbsp;&nbsp;setCharacterAttributes(editor, attr, false);<br>size为字号<br>3、是否是粗体的操作<br>StyledEditorKit kit = getStyledEditorKit(editor);<br>&nbsp;&nbsp;&nbsp;MutableAttributeSet attr = kit.getInputAttributes();<br>&nbsp;&nbsp;&nbsp;boolean bold = (StyleConstants.isBold(attr)) ? false : true;<br>&nbsp;&nbsp;&nbsp;SimpleAttributeSet sas = new SimpleAttributeSet();<br>&nbsp;&nbsp;&nbsp;StyleConstants.setBold(sas, bold);<br>&nbsp;&nbsp;&nbsp;setCharacterAttributes(editor, sas, false);<br>4、是否是斜体的操作<br>StyledEditorKit kit = getStyledEditorKit(editor);<br>&nbsp;&nbsp;&nbsp;MutableAttributeSet attr = kit.getInputAttributes();<br>&nbsp;&nbsp;&nbsp;boolean italic = (StyleConstants.isItalic(attr)) ? false : true;<br>&nbsp;&nbsp;&nbsp;SimpleAttributeSet sas = new SimpleAttributeSet();<br>&nbsp;&nbsp;&nbsp;StyleConstants.setItalic(sas, italic);<br>&nbsp;&nbsp;&nbsp;setCharacterAttributes(editor, sas, false);<br>5、是否有下划线的操作<br>StyledEditorKit kit = getStyledEditorKit(editor);<br>&nbsp;&nbsp;&nbsp;MutableAttributeSet attr = kit.getInputAttributes();<br>&nbsp;&nbsp;&nbsp;boolean underline = (StyleConstants.isUnderline(attr)) ? false<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: true;<br>&nbsp;&nbsp;&nbsp;SimpleAttributeSet sas = new SimpleAttributeSet();<br>&nbsp;&nbsp;&nbsp;StyleConstants.setUnderline(sas, underline);<br>&nbsp;&nbsp;&nbsp;setCharacterAttributes(editor, sas, false);<br>6、左中右对齐的处理<br>MutableAttributeSet attr = new SimpleAttributeSet();<br>&nbsp;&nbsp;&nbsp;StyleConstants.setAlignment(attr, a);<br>&nbsp;&nbsp;&nbsp;setParagraphAttributes(editor, attr, false);<br>public static final void setParagraphAttributes(JEditorPane editor,<br>&nbsp;&nbsp;&nbsp;AttributeSet attr, boolean replace) {<br>&nbsp;&nbsp;int p0 = editor.getSelectionStart();<br>&nbsp;&nbsp;int p1 = editor.getSelectionEnd();<br>&nbsp;&nbsp;StyledDocument doc = getStyledDocument(editor);<br>&nbsp;&nbsp;doc.setParagraphAttributes(p0, p1 - p0, attr, replace);<br>&nbsp;}<br>a:0：左，1：中，2：右</p>
<span style="COLOR: #008000">7、文本字体颜色的设置<br>MutableAttributeSet attr = new SimpleAttributeSet();<br>&nbsp;&nbsp;&nbsp;&nbsp;StyleConstants.setForeground(attr, fg);<br>&nbsp;&nbsp;&nbsp;&nbsp;setCharacterAttributes(editor, attr, false);<br>fg：为color<br>8、文本背景颜色的设置<br>MutableAttributeSet attr = new SimpleAttributeSet();<br>&nbsp;&nbsp;&nbsp;&nbsp;StyleConstants.setBackground(attr, bg);<br>&nbsp;&nbsp;&nbsp;&nbsp;setCharacterAttributes(editor, attr, false);</span>
 <img src ="http://www.blogjava.net/Swing/aggbug/128965.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Swing/" target="_blank">zht</a> 2007-07-09 08:50 <a href="http://www.blogjava.net/Swing/archive/2007/07/09/128965.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java2d 特效：图像缩放</title><link>http://www.blogjava.net/Swing/archive/2007/05/30/120800.html</link><dc:creator>zht</dc:creator><author>zht</author><pubDate>Wed, 30 May 2007 01:37:00 GMT</pubDate><guid>http://www.blogjava.net/Swing/archive/2007/05/30/120800.html</guid><wfw:comment>http://www.blogjava.net/Swing/comments/120800.html</wfw:comment><comments>http://www.blogjava.net/Swing/archive/2007/05/30/120800.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/Swing/comments/commentRss/120800.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Swing/services/trackbacks/120800.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 将原始图形对象进行放大或缩小的操作&nbsp;&nbsp;<a href='http://www.blogjava.net/Swing/archive/2007/05/30/120800.html'>阅读全文</a><img src ="http://www.blogjava.net/Swing/aggbug/120800.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Swing/" target="_blank">zht</a> 2007-05-30 09:37 <a href="http://www.blogjava.net/Swing/archive/2007/05/30/120800.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java2d特效 文字旋转</title><link>http://www.blogjava.net/Swing/archive/2007/05/29/120591.html</link><dc:creator>zht</dc:creator><author>zht</author><pubDate>Tue, 29 May 2007 01:04:00 GMT</pubDate><guid>http://www.blogjava.net/Swing/archive/2007/05/29/120591.html</guid><wfw:comment>http://www.blogjava.net/Swing/comments/120591.html</wfw:comment><comments>http://www.blogjava.net/Swing/archive/2007/05/29/120591.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/Swing/comments/commentRss/120591.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Swing/services/trackbacks/120591.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 将图形围绕某点按照给定的角度进行旋转&nbsp;&nbsp;<a href='http://www.blogjava.net/Swing/archive/2007/05/29/120591.html'>阅读全文</a><img src ="http://www.blogjava.net/Swing/aggbug/120591.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Swing/" target="_blank">zht</a> 2007-05-29 09:04 <a href="http://www.blogjava.net/Swing/archive/2007/05/29/120591.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java键盘事件</title><link>http://www.blogjava.net/Swing/archive/2007/05/26/120141.html</link><dc:creator>zht</dc:creator><author>zht</author><pubDate>Sat, 26 May 2007 02:28:00 GMT</pubDate><guid>http://www.blogjava.net/Swing/archive/2007/05/26/120141.html</guid><wfw:comment>http://www.blogjava.net/Swing/comments/120141.html</wfw:comment><comments>http://www.blogjava.net/Swing/archive/2007/05/26/120141.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Swing/comments/commentRss/120141.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Swing/services/trackbacks/120141.html</trackback:ping><description><![CDATA[<p>最近看到有人问怎么模拟钢琴操作<br>想了想怎么实现 顺便看了下键盘事件<br>可以用两种方式<br>1、<br>&nbsp;public class KeystrokeTest extends JApplet {<br>&nbsp;private JButton button = new JButton("button");</p>
<p>&nbsp;public void init() {<br>&nbsp;&nbsp;Container contentPane = getContentPane();<br>&nbsp;&nbsp;JPanel panel = new JPanel();<br>&nbsp;&nbsp;JCheckBox checkbox = new JCheckBox("checkbox");<br>&nbsp;&nbsp;JButton southButton = new JButton("south button");<br>&nbsp;&nbsp;Listener listener = new Listener();</p>
<p>&nbsp;&nbsp;panel.setBorder(BorderFactory<br>&nbsp;&nbsp;&nbsp;&nbsp;.createTitledBorder(("Ancestor of button and checkbox")));</p>
<p>&nbsp;&nbsp;checkbox.registerKeyboardAction(listener, KeyStroke.getKeyStroke(<br>&nbsp;&nbsp;&nbsp;&nbsp;KeyEvent.VK_F, 0, false), JComponent.WHEN_FOCUSED);</p>
<p>&nbsp;&nbsp;panel.registerKeyboardAction(listener, KeyStroke.getKeyStroke(<br>&nbsp;&nbsp;&nbsp;&nbsp;KeyEvent.VK_A, InputEvent.ALT_MASK, false),<br>&nbsp;&nbsp;&nbsp;&nbsp;JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);</p>
<p>&nbsp;&nbsp;southButton.registerKeyboardAction(listener, KeyStroke.getKeyStroke(<br>&nbsp;&nbsp;&nbsp;&nbsp;KeyEvent.VK_W, 0, true), JComponent.WHEN_IN_FOCUSED_WINDOW);</p>
<p>&nbsp;&nbsp;panel.add(button);<br>&nbsp;&nbsp;panel.add(checkbox);</p>
<p>&nbsp;&nbsp;contentPane.add(panel, "Center");<br>&nbsp;&nbsp;contentPane.add(southButton, "South");<br>&nbsp;}<br>}</p>
<p>class Listener implements ActionListener {<br>&nbsp;public void actionPerformed(ActionEvent e) {<br>&nbsp;&nbsp;Object src = e.getSource();<br>&nbsp;&nbsp;String cname = src.getClass().getName();</p>
<p>&nbsp;&nbsp;if (src instanceof JCheckBox) {<br>&nbsp;&nbsp;&nbsp;System.out.print("'f' key PRESSED when checkbox");<br>&nbsp;&nbsp;&nbsp;System.out.println(" had focus");<br>&nbsp;&nbsp;} else if (src instanceof JPanel) {<br>&nbsp;&nbsp;&nbsp;System.out.print("'ALT-a' key PRESSED when ancestor");<br>&nbsp;&nbsp;&nbsp;System.out.println(" of titled panel had focus");<br>&nbsp;&nbsp;} else if (src instanceof JButton) {<br>&nbsp;&nbsp;&nbsp;System.out.print("'w' key RELEASED when any");<br>&nbsp;&nbsp;&nbsp;System.out.println(" component in window had focus");<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;System.out.println("Source: " + cname);<br>&nbsp;&nbsp;System.out.println();<br>&nbsp;}<br>}<br><br>2、<br>public class T {<br>&nbsp;public static void main(String[] args) {<br>&nbsp;&nbsp;try {<br>&nbsp;&nbsp;&nbsp;UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());<br>&nbsp;&nbsp;} catch (Exception e) {<br>&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;final JTextField tf = new JTextField();<br>&nbsp;&nbsp;tf.setEnabled(false);</p>
<p>&nbsp;&nbsp;JPanel p = new JPanel(new GridLayout(0, 3, 5, 5));<br>&nbsp;&nbsp;for (int i = 0; i &lt;= 9; i++) {<br>&nbsp;&nbsp;&nbsp;final JButton btn = new JButton(String.valueOf(i));<br>&nbsp;&nbsp;&nbsp;p.add(btn);</p>
<p>&nbsp;&nbsp;&nbsp;btn.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;KeyStroke.getKeyStroke((char) (i + '0')), "PressKeyAction");<br>&nbsp;&nbsp;&nbsp;btn.getActionMap().put("PressKeyAction", new AbstractAction() {<br>&nbsp;&nbsp;&nbsp;&nbsp;public void actionPerformed(ActionEvent e) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;btn.doClick();<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;});</p>
<p>&nbsp;&nbsp;&nbsp;btn.addActionListener(new ActionListener() {<br>&nbsp;&nbsp;&nbsp;&nbsp;public void actionPerformed(ActionEvent e) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tf.setText(tf.getText() + btn.getText());<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;});<br>&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;JFrame f = new JFrame();<br>&nbsp;&nbsp;JComponent contentPane = (JComponent) f.getContentPane();<br>&nbsp;&nbsp;contentPane.setLayout(new BorderLayout(0, 5));<br>&nbsp;&nbsp;contentPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));</p>
<p>&nbsp;&nbsp;f.getContentPane().add(p, BorderLayout.CENTER);<br>&nbsp;&nbsp;f.getContentPane().add(tf, BorderLayout.NORTH);<br>&nbsp;&nbsp;f.pack();<br>&nbsp;&nbsp;f.setLocationRelativeTo(null);<br>&nbsp;&nbsp;f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);<br>&nbsp;&nbsp;f.setVisible(true);<br>&nbsp;}<br>}<br><br>看了下java的源代码发现registerKeyboardAction方法其实就是把<br>btn.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;KeyStroke.getKeyStroke((char) (i + '0')), "PressKeyAction");<br>&nbsp;&nbsp;&nbsp;btn.getActionMap().put("PressKeyAction", new AbstractAction() {<br>&nbsp;&nbsp;&nbsp;&nbsp;public void actionPerformed(ActionEvent e) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;btn.doClick();<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;});封装了一下<br><br><br>&nbsp;&nbsp;&nbsp; public void registerKeyboardAction(ActionListener anAction,String aCommand,KeyStroke aKeyStroke,int aCondition) {</p>
<p>&nbsp;InputMap inputMap = getInputMap(aCondition, true);</p>
<p>&nbsp;if (inputMap != null) {<br>&nbsp;&nbsp;&nbsp;&nbsp; ActionMap actionMap = getActionMap(true);<br>&nbsp;&nbsp;&nbsp;&nbsp; ActionStandin action = new ActionStandin(anAction, aCommand);<br>&nbsp;&nbsp;&nbsp;&nbsp; inputMap.put(aKeyStroke, action);<br>&nbsp;&nbsp;&nbsp;&nbsp; if (actionMap != null) {<br>&nbsp;&nbsp;actionMap.put(action, action);<br>&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;}<br>&nbsp;&nbsp;&nbsp; }<br>不过api中提到<br>registerKeyboardAction方法现在已过时，对于类似的操作，请结合使用 <code>getActionMap()</code> 和 <code>getInputMap()，即第二种方法为java推荐的方法</code><br>好像在哪看到过java中不提倡使用addKeyListener();<br>知道的可以说以下<br></p>
<img src ="http://www.blogjava.net/Swing/aggbug/120141.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Swing/" target="_blank">zht</a> 2007-05-26 10:28 <a href="http://www.blogjava.net/Swing/archive/2007/05/26/120141.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java Web Start 学习</title><link>http://www.blogjava.net/Swing/archive/2007/05/08/115898.html</link><dc:creator>zht</dc:creator><author>zht</author><pubDate>Tue, 08 May 2007 03:50:00 GMT</pubDate><guid>http://www.blogjava.net/Swing/archive/2007/05/08/115898.html</guid><wfw:comment>http://www.blogjava.net/Swing/comments/115898.html</wfw:comment><comments>http://www.blogjava.net/Swing/archive/2007/05/08/115898.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/Swing/comments/commentRss/115898.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Swing/services/trackbacks/115898.html</trackback:ping><description><![CDATA[<p><font face="verdana, arial, helvetica" size=2><span class=javascript id=text4886453 style="FONT-SIZE: 12px">Java Web Start（以下简称JWS）是SUN提供的一种通过Web来部署和发布Java 程序的新技术，它既可以用来发布Application，也可以用来发布Applet，它获去年全球Java技术最佳创意奖。它仅在第一次运行时下载程序，以后的事情，就全全交给JWS,包括版本的自动更新和维护。这是我们曾经梦寐以求的事情，程序运行在客户端（本地运行，当然有足够的速度），但不用去安装配置客户端，也不用去考虑版本升级后对客户端的维护，这就是JWS提供给我们的好处之一。OK，下面我们就来看看如何玩转JWS，本文仅用发布Application来做说明。<br>系统环境：Win2000Professional+Tomcat3.2.1+JDK1.3。<br>一：JWS简介<br>JWS主要用来通过网络部署你的应用程序，它具有安全、稳定、易维护、易使用的特点。用户访问用JWS部署应用程序的站点，下载发布的应用程序，既可以在线运行，也可以通过JWS的客户端离线运行已下载的应用程序。对同一个应用程序，在第一次运行时下载，以后每次运行时，JWS的客户端会自动去探测是否有版本更新，有更新就自动下载新版本，没有更新就直接运行本地当前版本，所有的麻烦全由JWS去承担。好，下面我们就一步一步来搭建JWS<br>二：搭建支持JWS的Web站点<br>第一步：你的Tomcat3.2.1已经正常运转<br>第二步：找到TomcatHOME/conf下的web.xml文件，在其中添加&lt;mime-type&gt;<br>application/x-java-jnlp-file<br>&lt;/mime-type&gt;<br>以支持JNLP文件。<br>三：部署应用程序<br>第一步：开发你希望发布的应用程序<br>第二步：把应用程序及所用到的所有资源打成一个或多个jar包<br>第三步：如果你的应用程序不会用到任何运行这个应用程序的机器的本地资源，那么，你的应用程序就可以部署了。<br>第四步：如果你的应用程序用到了运行这个应用程序的机器的本地资源，那么，你的应用程序就必须先签名然后才可以发布。<br>第五步：如何给应用程序签名<br>1：首先确保你已经完全安装了Java2的环境，有keytool工具，它位于J2SE SDk的bin目录下。这一般不会有问题。<br>2：到Dos状态下，进入你需发布应用程序的jar包所在的目录，运行下面这句话<br>keytool -genkey -keystore myKeystore -alias jwstest<br>它将会提示你输入用户名、密码等，不用理它，按照提示随便输入即可，但一定要记住密码。运行结束它将会在当前路径下创建名为myKeystore的文件。<br>3：如果你想察看一下刚才生成的myKeystore文件的内容，可以使用下面这句话：<br>keytool -list -keystore myKeystore<br>显示出来应该类似如下：<br>Keystore type: jks<br>Keystore provider: SUN<br>Your keystore contains 1 entry:<br>jwstest, Tue Nov 23 19:29:32 PST 2001, keyEntry,<br>Certificate fingerprint (Test):<br>C3:A9:CD:F3:D3:AC:4D:3F:3C:5B:AF:9E:CF:0D:46:5C<br>4：对你需发布应用程序的jar包进行签名，运行下面这句话：<br>jarsigner -keystore myKeystore yourtest.jar jwstest<br>其中yourtest.jar是你的jar包名，你需要修改它，别的就不必修改了。运行时会提示你输入密码，就是你刚才在生成myKeystore文件时设定的密码。<br>第六步：部署应用程序的jar包。<br>1：在Tomcat的webapps中新建目录JWSTest<br>2：在JWSTest下新建目录apps,META-INF，WEB-INF<br>3：在apps下新建目录images和lib<br>4：在META-INF中拷入MANIFEST.MF<br>5：在WEB-INF中拷入web.xml<br>6：把已经准备好的jar包拷入lib目录下<br>四：Jsp页面<br>第一步：编写用于Web访问的页面index.jsp如下：<br>&lt;%@page contentType="text/html;charset=gb2312"%&gt;<br>&lt;html&gt;<br>&lt;title&gt;JWS Test&lt;/title&gt;<br>&lt;head&gt;<br>&lt;SCRIPT LANGUAGE="Javascript"&gt;<br>function insertLink(url, name) {<br>document.write("&lt;a href=" + url + "&gt;" + name + "&lt;/a&gt;&lt;br&gt;&lt;br&gt;");<br>}<br>insertLink("http://你的IP:8080/ JWSTest /apps/JWSTest.jnlp"," JWSTest ");<br>&lt;/SCRIPT&gt;<br>&lt;/head&gt;<br>&lt;body&gt;<br>&lt;/body&gt;<br>&lt;/html&gt;<br>第二步：在jsp中添加检测访问的客户端是否已经安装了JWS的客户端的代码，示例如下：<br>&lt;%@page contentType="text/html;charset=gb2312"%&gt;<br>&lt;html&gt;<br>&lt;title&gt; JWS Test &lt;/title&gt;<br>&lt;head&gt;<br>&lt;SCRIPT LANGUAGE="Javascript"&gt;<br>var javawsInstalled = 0;<br>isIE = "false";<br>if (navigator.mimeTypes &amp;&amp; navigator.mimeTypes.length) {<br>x = navigator.mimeTypes['application/x-java-jnlp-file'];<br>if (x) javawsInstalled = 1;<br>} else {<br>isIE = "true";<br>}<br>function insertLink(url, name) {<br>if (javawsInstalled) {<br>document.write("&lt;a href=" + url + "&gt;" + name + "&lt;/a&gt;&lt;br&gt;&lt;br&gt;");<br>} else {<br>document.write("&lt;a href=" + url + "&gt;"+ name +"&lt;/a&gt;&lt;br&gt;&lt;br&gt;");<br>}<br>}<br>&lt;/SCRIPT&gt;<br>&lt;SCRIPT LANGUAGE="VBScript"&gt;<br>on error resume next<br>If isIE = "true" Then<br>If Not(IsObject(CreateObject("JavaWebStart.IsInstalled"))) Then<br>javawsInstalled = 0<br>Else<br>javawsInstalled = 1<br>End If<br>End If<br>&lt;/SCRIPT&gt;<br>&lt;SCRIPT LANGUAGE="Javascript"&gt;<br>if(javawsInstalled){<br>insertLink("http://你的IP:8080/ JWSTest /apps/JWSTest.jnlp"," JWSTest ");<br>}else{<br>//通知用户要先安装JWS的客户端，你可以自己提供下载或是直接链接到Sun的JWS下载。<br>//分为两种，如果客户端已经安装了Java运行环境，则只要下载javaws-1_0_1_01-win-int.exe即可。<br>//如果客户端没有安装Java运行环境，则要下载完整的javaws-1_0_1_01-win-int-rt.exe。<br>}<br>&lt;/SCRIPT&gt;<br>&lt;/head&gt;<br>&lt;body&gt;<br>&lt;/body&gt;<br>&lt;/html&gt;<br>五：JNLP文件<br>第一步：下面我们来编写JWS的核心配置文件JNLP，有了它，才能将以上各部分联系起来，真正让JWS运转起来。JNLP文件符合标准的XML语法，实质就是一个XML文件。当然，编写它的最好方式是对已写好的JNLP进行改写。JWSTest.jnlp示例如下：<br>&lt;?xml version="1.0" encoding="utf-8"?&gt;<br>&lt;!-- JNLP File for SwingSet2 Demo Application --&gt;<br>&lt;jnlp<br>spec="1.0+"<br>codebase="http://你的IP:8080/JWSTest/apps"<br>href=" JWSTest.jnlp"&gt;<br>&lt;information&gt;<br>&lt;title&gt; JWS Test &lt;/title&gt;<br>&lt;vendor&gt;YOUR Name&lt;/vendor&gt;<br>&lt;homepage href=" JWSTest.html"/&gt;<br>&lt;description&gt; JWS Test &lt;/description&gt;<br>&lt;icon href="images/ JWSTest.jpg"/&gt;<br>&lt;offline-allowed/&gt;<br>&lt;/information&gt;<br>&lt;security&gt;<br>&lt;all-permissions/&gt;<br>&lt;/security&gt;<br>&lt;resources&gt;<br>&lt;j2se version="1.3"/&gt;<br>&lt;jar href="lib/ JWSTest.jar"/&gt;<br>&lt;/resources&gt;<br>&lt;application-desc main-class="运行启动的主类"/&gt;<br>&lt;/jnlp&gt;<br>第二步：部分JNLP的关键语法<br>&lt;jnlp&gt;元素<br>spec：必须是1.0及以上版本，这里用1.0+，不需修改。<br>codebase：资源的URL，是JNLP指向各连接的起始处，需自行修改。<br>Href：JNLP文件相对codebase的存放位置，和JNLP文件的全名，需自行修改。<br>&lt;infomation&gt;元素<br>Title：发布的应用程序简单标题，需自行修改。<br>Vendor：发行商信息，可以写上你的大名，需自行修改。<br>Homepage：存放有关应用程序的相关文档的URL，如help文件等，可有可无。<br>Description：对应用程序的描述，可以有多对&lt;description&gt;&lt;/description&gt;，可有可无。<br>Icon：用户下载你的应用程序后，在JWS里显示的图标的URL，应是gif或jpeg格式。需自行修改。<br>Offline-allowed：选择项，允许用户离线运行应用程序，一般都会有，不用修改。<br>&lt;security&gt;元素<br>选择项，如果没有指明&lt;security&gt;，默认是不允许应用程序访问用户的本地资源，即应用程序是沙箱运行。<br>如果设定为&lt;all-permissions/&gt;，则表示允许应用程序访问用户的本地资源。一般都会设定此值。<br>&lt;resource&gt;元素<br>&lt;j2se version = 指定jdk版本&gt;<br>&lt;jar href = 指定需发布的应用程序的jar包存放的位置&gt;<br>&lt;application-desc&gt;元素<br>main-class：应用程序运行启动的主类<br>&lt;argument&gt;：应用程序运行时的参数，可以有多个，每一个参数用一对&lt;argument&gt;参数&lt;/argument&gt;。<br>至此，你已经完全构建了运转JWS的各部件。<br>六：完整发布和测试<br>前面我们已经准备好了需发布的应用程序的jar包，也写好了用来访问的jsp文件和服务器端的核心jnlp文件。<br>第一步：在JWSTest下新建目录jsp。把index.jsp拷入jsp目录。<br>第二步：把jnlp文件直接拷入apps目录下。<br>第三步：在浏览器里输入:<a href="http://localhost:8080/JWSTest/jsp/index.jsp" target=_blank><u><font color=#56b6e9>http://localhost:8080/JWSTest/jsp/index.jsp</font></u></a> 即可访问到jsp页面。页面应出现JWSTest字样。<br>第四步：点击JWSTest，连接到apps下的JWSTest.jnlp文件，JWS启动，开始下载你发布的应用程序。<br>第五步：下载完毕，直接运行即可。以后，你也可以直接运行JWS客户端里已下载的应用程序。<br>不出意外，应恭喜你已经开始享受JWS带来的乐趣了。<br>七：常见问题<br>通过上面的讲述，你一定能体会到JWS的易用性。或许事情并没有那么简单，以我的使用经验，还会有许多问题出现，在这里挑几个经常出现的问题，给出相应解决方法，让大家少走弯路，而享受更多的乐趣。<br>问题一：JWS不能运行，JNLP文件像普通XML文件一样显示在Browser里<br>解决办法：请修改tomcat里，发布程序的路径中的web.xml。<br>在其中添加&lt;mime-type&gt;<br>application/x-java-jnlp-file<br>&lt;/mime-type&gt;<br>以支持JNLP文件。<br>问题二：不能下载资源或下载资源失败<br>解决办法：请卸载JWS的客户端，并将注册表里有关JWS的项目都删除，并确保program Files下的Java Web Start目录已被删除，然后，重装JWS。<br>问题三：下载资源中有未签名文件<br>解决办法：1：确保所有的jar包及其他资源都进行过签名。<br>2：确保整个资源中，没有中文的命名。好像签名工具不支持中文命名的文件名，所以未签到名。这可让我郁闷了一下午哦。<br>3：察看已经签名的jar包中，meta-inf路径下的jwstest.sf（jwstest是你在进行签名时-alias后的命名）文件，他详细的列出了所有已签名的文件，以分析签名失败的原因。</span> <br><a href="http://www.itpub.net/595150.html"><u><font color=#56b6e9>http://www.itpub.net/595150.html</font></u></a> <br>&lt;?xml version="1.0" encoding="utf-8"?&gt;<br>&lt;!-- JNLP File for SwingSet2 Demo Application --&gt;<br>&lt;jnlp<br>spec="1.0+"<br>codebase="<a href="http://172.*.*.*:8080/JWSTest/apps"><u><font color=#56b6e9>http://172.*.*.*:8080/JWSTest/apps</font></u></a>"<br>href=" JWSTest.jnlp"&gt;<br>&lt;information&gt;<br>&lt;title&gt; JWS Test &lt;/title&gt;<br>&lt;vendor&gt;YOUR Name&lt;/vendor&gt;<br>&lt;description&gt; JWS Test &lt;/description&gt;<br>&lt;offline-allowed/&gt;<br>&lt;/information&gt;<br>&lt;security&gt;<br>&lt;all-permissions/&gt;<br>&lt;/security&gt;<br>&lt;resources&gt;<br>&lt;j2se version="1.4"/&gt;<br>&lt;jar href="lib/xx.jar"/&gt;<br>&lt;/resources&gt;<br>&lt;application-desc main-class="fullScreen.FullScreenTest"/&gt;<br>&lt;/jnlp&gt;</font> </p>
<br><br>
<script>function StorePage(){d=document;t=d.selection?(d.selection.type!='None'?d.selection.createRange().text:''):(d.getSelection?d.getSelection():'');void(keyit=window.open('http://www.365key.com/storeit.aspx?t='+escape(d.title)+'&u='+escape(d.location.href)+'&c='+escape(t),'keyit','scrollbars=no,width=475,height=575,left=75,top=20,status=no,resizable=yes'));keyit.focus();}</script>
<div class=post>
<div class=postTitle><a href="http://blog.csdn.net/sagely/archive/2005/05/01/370157.aspx"><img height=13 src="http://blog.csdn.net/images/authorship.gif" width=15 border=0><u><font color=#800080>&nbsp;JDK中keytool常用命令</font></u></a> </div>
<div class=postText>
<p>-genkey&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在用户主目录中创建一个默认文件".keystore",还会产生一个mykey的别名，mykey中包含用户的公钥、私钥和证书 <br>-alias&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 产生别名<br>-keystore&nbsp;&nbsp;&nbsp; 指定密钥库的名称(产生的各类信息将不在.keystore文件中<br>-keyalg&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 指定密钥的算法&nbsp;&nbsp;&nbsp; <br>-validity&nbsp;&nbsp;&nbsp; 指定创建的证书有效期多少天<br>-keysize&nbsp;&nbsp;&nbsp;&nbsp; 指定密钥长度<br>-storepass&nbsp;&nbsp; 指定密钥库的密码<br>-keypass&nbsp;&nbsp;&nbsp;&nbsp; 指定别名条目的密码<br>-dname&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 指定证书拥有者信息 例如：&nbsp; "CN=sagely,OU=atr,O=szu,L=sz,ST=gd,C=cn"<br>-list&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 显示密钥库中的证书信息&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; keytool -list -v -keystore sage -storepass ....<br>-v&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 显示密钥库中的证书详细信息<br>-export&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 将别名指定的证书导出到文件&nbsp; keytool -export -alias caroot -file caroot.crt<br>-file&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 参数指定导出到文件的文件名<br>-delete&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 删除密钥库中某条目&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; keytool -delete -alias sage -keystore sage<br>-keypasswd&nbsp;&nbsp; 修改密钥库中指定条目口令&nbsp;&nbsp;&nbsp; keytool -keypasswd -alias sage -keypass .... -new .... -storepass ... -keystore sage<br>-import&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 将已签名数字证书导入密钥库&nbsp; keytool -import -alias sage -keystore sagely -file sagely.crt <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 导入已签名数字证书用keytool -list -v 以后可以明显发现多了认证链长度，并且把整个CA链全部打印出来。</p>
</div>
<br>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>Keytool 是安全钥匙与证书的管理工具.它管理一个存储了私有钥匙和验证相应公共钥匙的与它们相关联的X.509 证书链的keystore(相当一个数据库).</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>Keytool 是一个有效的安全钥匙和证书的管理工具. 它能够使用户使用数字签名来管理他们自己的私有/公共钥匙对,管理用来作自我鉴定的相关的证书,管理数据完整性和鉴定服务.它还能使用户在通信时缓存它们的公共钥匙.</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>一个证书是某一实体(个人,公司等)的数字签名,指出其他实体的公共钥匙(或其他信息)的详细的值.当数据被签名后,这个签名信息被用来检验数据的完整性和真实性.完整性指数据没有被修改和篡改,真实性指数据从任何产生和签名的一方真正的传输到达.</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>Keytool 把钥匙和证书储存到一个keystore.默任的实现keystore的是一个文件.它用一个密码保护钥匙.</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>而另外的一个工具jarsigner用keystore中的信息产生或检验Java aRchive(jar文件)中的数字签名.</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>Keystore有两个不同的入口:</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>1.钥匙入口:保存了非常敏感的加密的钥匙信息,并且是用一个保护的格式存储以防止未被授权的访问.以这种形式存储的钥匙是秘密钥匙,或是一个对应证书链中公有钥匙的私有钥匙.</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>2.信任证书入口:包含一个属于其他部分的单一公共钥匙证书.它之所以被称为"信任证书",是因为keystore信任的证书中的公共钥匙真正属于证书所有者的身份识别.</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>Keystore的别名:</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>所有的keystore入口(钥匙和信任证书入口)是通过唯一的别名访问.别名是 不区分大小写的.如别名Hugo和hugo指向同一个keystore入口.</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>可以在加一个入口到keystore的时候使用-genkey参数来产生一个钥匙对(公共钥匙和私有钥匙)时指定别名.也可以用-import参数加一个证书或证书链到信任证书.</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>如:</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>keytool -genkey -alias duke -keypass dukekeypasswd</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>其中duke为别名,dukekeypasswd为duke别名的密码.这行命令的作用是产生一个新的公共/私有钥匙对.</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>假如你想修改密码,可以用:</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>keytool -keypasswd -alias duke -keypass dukekeypasswd -new newpass</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>将旧密码dukekeypasswd改为newpass.</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14></td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>Keystore的产生:</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>1.当使用-genkey 或-import或-identitydb命令添加数据到一个keystore,而当这个keystore不存在时,产生一个keystore.默认名是.keystore,存放到user-home目录.</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>2.当用-keystore指定时,将产生指定的keystore.</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>Keystore的实现:</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>Keytool 类位于java.security包下,提供一个非常好的接口去取得和修改一个keystore中的信息. 目前有两个命令行:keytool和jarsinger,一个GUI工具Policy 可以实现keystore.由于keystore是公开的,用户可以用它写一些额外的安全应用程序.</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>Keystore还有一个sun公司提供的內在实现.它把keystore作为一个文件来实现.利用了一个keystore类型(格式)"JKS".它用单独的密码保护每一个私有钥匙.也用可能不同的密码保护整个keystore的完整性.</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>支持的算法和钥匙大小:</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>keytool允许用户指定钥匙对和注册密码服务供应者所提供的签名算法.缺省的钥匙对产生算法是"DSA".假如私有钥匙是"DSA"类型,缺省签名算法是"SHA1withDSA",假如私有钥匙是"RSA"类型,缺省算法是"MD5withRSA".</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>当产生一个DSA钥匙对,钥匙必须在512-1024位之间.对任何算法的缺省钥匙大小是1024位.</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>证书:</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>一个证书是一个实体的数字签名,指出其他实体的公共钥匙有明确的值.</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>1.公共钥匙 :是同一个详细的实体的数字关联,并有意让所有想同这个实体发生信任关系的其他实体知道.公共钥匙用来检验签名;</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>2.数字签名:假如数据已被签名,并用身份存储在一个实体中,一个签名能够证明这个实体知道这个数据.这个数据用实体私有钥匙签名并递交;</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>3.身份:知道实体的方法.在一些系统中身份是公共钥匙,其他系统中可以是从一个X.509名字的邮件地址的Unix UID来的任何东西;</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>4.签名:一个签名用用实体私有钥匙来计算某些加密数据;</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>5.私有钥匙:是一些数字,每一个私有钥匙只能被特定的拥有该私有钥匙的实体知道.私有和公共钥匙存在所有用公共钥匙加密的系统的钥匙对中.一个公共钥匙加密(如DSA),一个私有钥匙与一个正确的公共钥匙通信.私有钥匙用来计算签名.</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>6.实体:一个实体可以是一个人,一个组织,一个程序,一台计算机,一个商业,一个银行,或其他你想信任的东西.</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14></td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>Keytool应用实例:</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>1.产生一个keystore:</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>keytool -genkey -alias User(keystore的别名) -keyalg RSA -validity 7 -keystore keystore(指定keystore).</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>运行这个命令,系统提示:</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>Enter keystore password:yourpassword(输入密码)</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>What is your first and last name?</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>[Unknown]: your name(输入你的名字)</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>What is the name of your organizational unit?</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>[Unknown]:your organizational(输入你所在组织单位的名字) </td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>What is the name of your organization?</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>[Unknown]:your organization name (输入你所在组织的名字) </td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>What is the name of your City or Locality?</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>[Unknown]:your city name(输入所在城市的名字)</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>What is the name of your State or Province?</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>[Unknown]:your provice name(输入所在省份名字)</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>What is the two-letter country code for this unit?</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>[Unknown]:cn(输入国家名字)</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>Is CN=your name, OU=your organizaion, O="your organization name",</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>L=your city name, ST=your province name, C=cn correct?</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>[no]: yes</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14></td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>2.检查一个keystore:</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>keytool -list -v -keystore keystore</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>Enter keystore password:your password(输入密码)</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>将显示keystore內容如:</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>Keystore type: jks</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>Keystore provider: SUN</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14></td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>Your keystore contains 1 entry</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14></td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>Alias name: yourname</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>Creation date: Dec 20, 2001</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>Entry type: keyEntry</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>Certificate chain length: 1</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>Certificate[1]:</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>Owner: CN=yourname, OU=your organization, O="your organization name", </td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>L=your city name, ST=your province name, C=CN</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>Issuer: CN=Duke, OU=Java Software, O="Sun Microsystems, Inc.", L=Palo Alto, ST=CA, C=US</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>Serial number: 3c22adc1</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>Valid from: Thu Dec 20 19:34:25 PST 2001 until: Thu Dec 27 19:34:25 PST 2001</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>Certificate fingerprints:</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>MD5: F1:5B:9B:A1:F7:16:CF:25:CF:F4:FF:35:3F:4C:9C:F0</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>SHA1: B2:00:50:DD:B6:CC:35:66:21:45:0F:96:AA:AF:6A:3D:E4:03:7C:74</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>3.输出keystore到一个文件:testkey:</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>keytool -export -alias duke -keystore keystore -rfc -file testkey</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>系统输出:</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>Enter keystore password:your password(输入密码)</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>Certificate stored in file <testkey&gt;< td></td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>4.输入证书到一个新的truststore:</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>keytool -import -alias dukecert -file testkey -keystore truststore</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>Enter keystore password:your new password.(输入truststore新密码)</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14></td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>5.检查truststore:</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>keytool -list -v -keystore truststore</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>系统将显示truststore的信息. </td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>现在可以用适当的keystore运行你的应用程序.如: </td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>java -Djavax.net.ssl.keyStore=keystore -Djavax.net.ssl.keyStorePassword=password Server</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>和: java -Djavax.net.ssl.trustStore=truststore</td>
        </tr>
    </tbody>
</table>
<table width="100%">
    <tbody>
        <tr>
            <td class=a14>-Djavax.net.ssl.trustStorePassword=trustword Client</td>
        </tr>
    </tbody>
</table>
</div>
<img src ="http://www.blogjava.net/Swing/aggbug/115898.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Swing/" target="_blank">zht</a> 2007-05-08 11:50 <a href="http://www.blogjava.net/Swing/archive/2007/05/08/115898.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于Swing</title><link>http://www.blogjava.net/Swing/archive/2007/04/26/113732.html</link><dc:creator>zht</dc:creator><author>zht</author><pubDate>Thu, 26 Apr 2007 03:59:00 GMT</pubDate><guid>http://www.blogjava.net/Swing/archive/2007/04/26/113732.html</guid><wfw:comment>http://www.blogjava.net/Swing/comments/113732.html</wfw:comment><comments>http://www.blogjava.net/Swing/archive/2007/04/26/113732.html#Feedback</comments><slash:comments>24</slash:comments><wfw:commentRss>http://www.blogjava.net/Swing/comments/commentRss/113732.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Swing/services/trackbacks/113732.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 做了一年多的Swing了，对Swing蛮有感情的，也非常喜欢Swing，可是现在上网看看招聘信息，几乎是清一色的J2ee，几乎都是Struts、Spring、Hibernate等等，现在搞得自己都很迷茫，很怀疑一直做Swing的前途，其实我个人觉着Swing还是很有技术含量的，有句话叫做只有你想不到，没有它做不到。相对于web程序，它不单单是java的应用，Swing程序更像一部作品，它里面包含了程序作者很多的创造性，随着JDK新版本的发布，都说Swing将会有更广泛的用途，但是至少目前，java还是主要用在web方面，也可能是自己的知识面和接触面太窄还没有看到Swing的未来，希望大家探讨一下，各抒己见。<img height="20" src="http://www.blogjava.net/Emoticons/QQ/lucky.gif" width="19" border="0"  alt="" /> <br />
<br />
<span style="color: #008000">07年的时候发的一个帖子，现在觉着不管做什么，关键是要做好了，做好了都有前途&nbsp;&nbsp;&nbsp;&nbsp; --2009.6.10</span>
<img src ="http://www.blogjava.net/Swing/aggbug/113732.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Swing/" target="_blank">zht</a> 2007-04-26 11:59 <a href="http://www.blogjava.net/Swing/archive/2007/04/26/113732.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>