﻿<?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-Pudgy's World</title><link>http://www.blogjava.net/Pudgy/</link><description>&lt;SCRIPT&gt;
var dict_width   = 'auto'
var dict_height  = '72px'
var dict_background = 'transparent'
var dict_border  = '0px dotted #000000'
var dict_textColor = '#6FBC4C'
var dict_fontSize = '100%'
var dict_encoding = 'Utf-8'
&lt;/SCRIPT&gt;
&lt;SCRIPT src="http://livid.cn/services/fortune"&gt;&lt;/SCRIPT&gt;
&lt;script src="http://www.google-analytics.com/urchin.js" type="text/javascript"&gt;
&lt;/script&gt;</description><language>zh-cn</language><lastBuildDate>Mon, 04 May 2026 19:50:00 GMT</lastBuildDate><pubDate>Mon, 04 May 2026 19:50:00 GMT</pubDate><ttl>60</ttl><item><title>2005.08.30</title><link>http://www.blogjava.net/Pudgy/archive/2005/08/30/11543.html</link><dc:creator>Pudgy's World</dc:creator><author>Pudgy's World</author><pubDate>Tue, 30 Aug 2005 05:09:00 GMT</pubDate><guid>http://www.blogjava.net/Pudgy/archive/2005/08/30/11543.html</guid><wfw:comment>http://www.blogjava.net/Pudgy/comments/11543.html</wfw:comment><comments>http://www.blogjava.net/Pudgy/archive/2005/08/30/11543.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Pudgy/comments/commentRss/11543.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Pudgy/services/trackbacks/11543.html</trackback:ping><description><![CDATA[<ol>
  <li>把SwingWorker 的Thread 参数弄明白</li>
  <li>线程组的调用.<br>
  </li>
</ol>
<img src ="http://www.blogjava.net/Pudgy/aggbug/11543.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Pudgy/" target="_blank">Pudgy's World</a> 2005-08-30 13:09 <a href="http://www.blogjava.net/Pudgy/archive/2005/08/30/11543.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Thumbnail.java - Load an image, scale it to thumbnail size and save it as JPEG</title><link>http://www.blogjava.net/Pudgy/archive/2005/08/29/11457.html</link><dc:creator>Pudgy's World</dc:creator><author>Pudgy's World</author><pubDate>Mon, 29 Aug 2005 08:12:00 GMT</pubDate><guid>http://www.blogjava.net/Pudgy/archive/2005/08/29/11457.html</guid><wfw:comment>http://www.blogjava.net/Pudgy/comments/11457.html</wfw:comment><comments>http://www.blogjava.net/Pudgy/archive/2005/08/29/11457.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Pudgy/comments/commentRss/11457.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Pudgy/services/trackbacks/11457.html</trackback:ping><description><![CDATA[<P class=topmenu><FONT face=Verdana size=2>From </FONT><A href="http://schmidt.devlib.org/java/save-jpeg-thumbnail.html"><FONT face=Verdana size=2>http://schmidt.devlib.org/java/save-jpeg-thumbnail.html</FONT></A></P>
<H1><FONT face=Verdana size=4>Thumbnail.java - Load an image, scale it to thumbnail size and save it as JPEG</FONT></H1>
<P><FONT face=Verdana>This programm loads an image via <CODE>java.awt.Toolkit</CODE>, scales it down to a user-defined resolution and saves it as a </FONT><A href="http://schmidt.devlib.org/file-formats/jpeg-image-file-format.html"><FONT face=Verdana>JPEG</FONT></A><FONT face=Verdana> file. The first part, the loading of the original image, is done the same way as in </FONT><A href="http://schmidt.devlib.org/java/load-image-toolkit.html"><FONT face=Verdana>Viewer</FONT></A><FONT face=Verdana>. So if you don't know yet how loading images with <CODE>Toolkit</CODE> works you might want to study that program first. </FONT></P>
<P><FONT face=Verdana>Different from <EM>Viewer</EM>, this program (Thumbnail) works on the command line. So you won't get any windows or other graphical user interface components. The only visual feedback is the word <CODE>Done.</CODE> after the program successfully terminated. </FONT></P>
<P><FONT face=Verdana>To use this program do the following: </FONT></P>
<UL>
<LI><FONT face=Verdana>Save the </FONT><A href="http://schmidt.devlib.org/java/save-jpeg-thumbnail.html#source"><FONT face=Verdana>program's source code</FONT></A><FONT face=Verdana> as <CODE>Thumbnail.java</CODE> (regard case). </FONT></LI>
<LI><FONT face=Verdana>Open a shell (prompt), go to the directory where <CODE>Thumbnail.java</CODE> is and compile it: </FONT><PRE><FONT face=Verdana>javac Thumbnail.java</FONT></PRE><FONT face=Verdana>You should now have a new class file <CODE>Thumbnail.class</CODE>.</FONT></LI>
<LI><FONT face=Verdana>Run the program with five parameters for image file, thumbnail file, thumbnail width and thumbnail height and quality (a value from 0 to 100, 100 being the best and 0 the worst quality), e.g.: </FONT><PRE><FONT face=Verdana>java Thumbnail c:\image.jpg c:\thumbnail.jpg 120 80 75</FONT></PRE><FONT face=Verdana>The file <CODE>image.jpg</CODE> must exist already, <CODE>thumbnail.jpg</CODE> will be created (and any existing file of that name overwritten).</FONT></LI></UL>
<P><FONT face=Verdana>You will need Java 1.2 or higher to successfully run this program. The <CODE>com.sun.image.codec.jpeg</CODE> package that will be used for saving the thumbnail is not available with all Java development kits, but as long as you are using a Sun JDK, it should be present. </FONT></P>
<P><FONT face=Verdana>With Java 1.4 a new way of writing JPEG files was introduced, the image I/O library in the package <CODE>javax.imageio</CODE>. See </FONT><A href="http://schmidt.devlib.org/java/save-screenshot.html"><FONT face=Verdana>the Screenshot.java example program</FONT></A><FONT face=Verdana>. It saves as PNG, but all you have to do is change the second argument of <CODE>ImageIO.write</CODE> from <CODE>png</CODE> to <CODE>jpg</CODE>. The advantage of <CODE>ImageIO</CODE>: It is available with each 1.4+ JDK and JRE, not only those coming from Sun. </FONT></P>
<H2><FONT face=Verdana size=3>Explanation</FONT></H2>
<P><FONT face=Verdana>Now let's see how this program works. First, it is checked that we have exactly five arguments. If this is not the case, an error message is printed to output and the program terminates. </FONT></P>
<P><FONT face=Verdana>Next, the input image is loaded via <CODE>Toolkit</CODE> and <CODE>MediaTracker</CODE> just as it was done in </FONT><A href="http://schmidt.devlib.org/java/load-image-toolkit.html"><FONT face=Verdana>Viewer</FONT></A><FONT face=Verdana>. </FONT></P>
<P><FONT face=Verdana>The third and fourth program argument contain the maximum size of the thumbnail to be created. The <EM>actual</EM> size of the thumbnail will be computed from that maximum size and the actual size of the image (all sizes are given as pixels). The code that does this is not really very readable, and also not essential to loading and saving image files. But it is necessary to create a thumbnail that is scaled correctly. </FONT></P>
<P><FONT face=Verdana>As an example, if the two arguments for the maximum thumbnail size are both <CODE>100</CODE> and the image that was loaded is <CODE>400</CODE> times <CODE>200</CODE> pixels large, we want the thumbnail to be <CODE>100</CODE> times <CODE>50</CODE> pixels large, not <CODE>100</CODE> times <CODE>100</CODE>, because the original image is twice as wide as it is high. A <CODE>100</CODE> times <CODE>100</CODE> pixel thumbnail would contain a very skewed version of the original image. </FONT></P>
<P><FONT face=Verdana>Now that we have determined the size of the thumbnail we create a <CODE>BufferedImage</CODE> of that size, named <CODE>thumbImage</CODE>. We ask for a <CODE>Graphics2D</CODE> object for that new thumbnail image and call its <CODE>drawImage</CODE> method to draw the original image on that new image. The call to <CODE>drawImage</CODE> does the actual scaling. The rendering hints for bilinear interpolation can be left out if quality is not that necessary and speed more important. For nicer results (at least in some cases) try <CODE>RenderingHints.VALUE_INTERPOLATION_BICUBIC</CODE> instead of <CODE>RenderingHints.VALUE_INTERPOLATION_BILINEAR</CODE>. </FONT></P>
<P><FONT face=Verdana>In order to save the scaled-down image to a JPEG file, we create a buffered <CODE>FileOutputStream</CODE> with the second argument as name and initialize the necessary objects from the <CODE>com.sun.image.codec.jpeg</CODE> package. The quality argument from the command line is converted from the interval <CODE>0</CODE> to <CODE>100</CODE> to the interval <CODE>0.0f</CODE> to <CODE>1.0f</CODE>, because that's what the codec expects (I mostly use <CODE>0.75f</CODE>). The higher that quality number is, the better the resulting thumbnail image quality, but also the larger the resulting file. </FONT></P>
<P><FONT face=Verdana>The call to <CODE>System.exit(0);</CODE> is unfortunately necessary for some Java runtime environments (because of a bug that keeps the AWT thread from terminating). </FONT></P>
<H2><A id=source><FONT face=Verdana size=3>Source code of Thumbnail.java</FONT></A></H2><PRE><FONT face=Verdana size=2>&nbsp;</FONT><DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid"><DIV><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">import&nbsp;com.sun.image.codec.jpeg.</SPAN><SPAN style="COLOR: #000000">*</SPAN></FONT></FONT><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">;<BR>import&nbsp;java.awt.</SPAN><SPAN style="COLOR: #000000">*</SPAN></FONT></FONT><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">;<BR>import&nbsp;java.awt.image.</SPAN><SPAN style="COLOR: #000000">*</SPAN></FONT></FONT><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">;<BR>import&nbsp;java.io.</SPAN><SPAN style="COLOR: #000000">*</SPAN></FONT></FONT><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">;<BR><BR></SPAN><SPAN style="COLOR: #008000">/*</SPAN></FONT></FONT><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #008000">*<BR>&nbsp;*&nbsp;Thumbnail.java&nbsp;(requires&nbsp;Java&nbsp;1.2+)<BR>&nbsp;*&nbsp;Load&nbsp;an&nbsp;image,&nbsp;scale&nbsp;it&nbsp;down&nbsp;and&nbsp;save&nbsp;it&nbsp;as&nbsp;a&nbsp;JPEG&nbsp;file.<BR>&nbsp;*&nbsp;@author&nbsp;Marco&nbsp;Schmidt<BR>&nbsp;</SPAN><SPAN style="COLOR: #008000">*/</SPAN></FONT></FONT><SPAN style="COLOR: #000000"><BR></SPAN><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN></FONT></FONT><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">&nbsp;Thumbnail&nbsp;{<BR>&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></FONT></FONT><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">&nbsp;main(String[]&nbsp;args)&nbsp;throws&nbsp;Exception&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">&nbsp;(args.length&nbsp;</SPAN><SPAN style="COLOR: #000000">!=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">5</SPAN></FONT></FONT><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.err.println(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">Usage:&nbsp;java&nbsp;Thumbnail&nbsp;INFILE&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">+</SPAN></FONT></FONT><SPAN style="COLOR: #000000"><BR><FONT face=Verdana size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT></SPAN><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">OUTFILE&nbsp;WIDTH&nbsp;HEIGHT&nbsp;QUALITY</SPAN><SPAN style="COLOR: #000000">"</SPAN></FONT></FONT><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.exit(</SPAN><SPAN style="COLOR: #000000">1</SPAN></FONT></FONT><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">);<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;load&nbsp;image&nbsp;from&nbsp;INFILE</SPAN></FONT></FONT><SPAN style="COLOR: #008000"><BR></SPAN><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;Image&nbsp;image&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;Toolkit.getDefaultToolkit().getImage(args[</SPAN><SPAN style="COLOR: #000000">0</SPAN></FONT></FONT><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">]);<BR>&nbsp;&nbsp;&nbsp;&nbsp;MediaTracker&nbsp;mediaTracker&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;MediaTracker(</SPAN><SPAN style="COLOR: #0000ff">new</SPAN></FONT></FONT><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">&nbsp;Container());<BR>&nbsp;&nbsp;&nbsp;&nbsp;mediaTracker.addImage(image,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN></FONT></FONT><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">);<BR>&nbsp;&nbsp;&nbsp;&nbsp;mediaTracker.waitForID(</SPAN><SPAN style="COLOR: #000000">0</SPAN></FONT></FONT><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">);<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;determine&nbsp;thumbnail&nbsp;size&nbsp;from&nbsp;WIDTH&nbsp;and&nbsp;HEIGHT</SPAN></FONT></FONT><SPAN style="COLOR: #008000"><BR></SPAN><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;thumbWidth&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;Integer.parseInt(args[</SPAN><SPAN style="COLOR: #000000">2</SPAN></FONT></FONT><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">]);<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;thumbHeight&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;Integer.parseInt(args[</SPAN><SPAN style="COLOR: #000000">3</SPAN></FONT></FONT><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">]);<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">double</SPAN><SPAN style="COLOR: #000000">&nbsp;thumbRatio&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;(</SPAN><SPAN style="COLOR: #0000ff">double</SPAN><SPAN style="COLOR: #000000">)thumbWidth&nbsp;</SPAN><SPAN style="COLOR: #000000">/</SPAN><SPAN style="COLOR: #000000">&nbsp;(</SPAN><SPAN style="COLOR: #0000ff">double</SPAN></FONT></FONT><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">)thumbHeight;<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;imageWidth&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;image.getWidth(</SPAN><SPAN style="COLOR: #0000ff">null</SPAN></FONT></FONT><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">);<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;imageHeight&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;image.getHeight(</SPAN><SPAN style="COLOR: #0000ff">null</SPAN></FONT></FONT><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">);<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">double</SPAN><SPAN style="COLOR: #000000">&nbsp;imageRatio&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;(</SPAN><SPAN style="COLOR: #0000ff">double</SPAN><SPAN style="COLOR: #000000">)imageWidth&nbsp;</SPAN><SPAN style="COLOR: #000000">/</SPAN><SPAN style="COLOR: #000000">&nbsp;(</SPAN><SPAN style="COLOR: #0000ff">double</SPAN></FONT></FONT><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">)imageHeight;<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">&nbsp;(thumbRatio&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN></FONT></FONT><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">&nbsp;imageRatio)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;thumbHeight&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">)(thumbWidth&nbsp;</SPAN><SPAN style="COLOR: #000000">/</SPAN></FONT></FONT><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">&nbsp;imageRatio);<BR>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</SPAN><SPAN style="COLOR: #0000ff">else</SPAN></FONT></FONT><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;thumbWidth&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">)(thumbHeight&nbsp;</SPAN><SPAN style="COLOR: #000000">*</SPAN></FONT></FONT><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">&nbsp;imageRatio);<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN></FONT></FONT><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #008000">&nbsp;draw&nbsp;original&nbsp;image&nbsp;to&nbsp;thumbnail&nbsp;image&nbsp;object&nbsp;and<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;scale&nbsp;it&nbsp;to&nbsp;the&nbsp;new&nbsp;size&nbsp;on-the-fly</SPAN></FONT></FONT><SPAN style="COLOR: #008000"><BR></SPAN><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;BufferedImage&nbsp;thumbImage&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN></FONT></FONT><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">&nbsp;BufferedImage(thumbWidth,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;thumbHeight,&nbsp;BufferedImage.TYPE_INT_RGB);<BR>&nbsp;&nbsp;&nbsp;&nbsp;Graphics2D&nbsp;graphics2D&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN></FONT></FONT><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">&nbsp;thumbImage.createGraphics();<BR>&nbsp;&nbsp;&nbsp;&nbsp;graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RenderingHints.VALUE_INTERPOLATION_BILINEAR);<BR>&nbsp;&nbsp;&nbsp;&nbsp;graphics2D.drawImage(image,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">,&nbsp;thumbWidth,&nbsp;thumbHeight,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">null</SPAN></FONT></FONT><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">);<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;save&nbsp;thumbnail&nbsp;image&nbsp;to&nbsp;OUTFILE</SPAN></FONT></FONT><SPAN style="COLOR: #008000"><BR></SPAN><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;BufferedOutputStream&nbsp;</SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;BufferedOutputStream(</SPAN><SPAN style="COLOR: #0000ff">new</SPAN></FONT></FONT><SPAN style="COLOR: #000000"><BR><FONT face=Verdana size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FileOutputStream(args[</FONT></SPAN><SPAN style="COLOR: #000000"><FONT face=Verdana size=2>1</FONT></SPAN><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">]));<BR>&nbsp;&nbsp;&nbsp;&nbsp;JPEGImageEncoder&nbsp;encoder&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;JPEGCodec.createJPEGEncoder(</SPAN><SPAN style="COLOR: #0000ff">out</SPAN></FONT></FONT><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">);<BR>&nbsp;&nbsp;&nbsp;&nbsp;JPEGEncodeParam&nbsp;param&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN></FONT></FONT><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">&nbsp;encoder.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getDefaultJPEGEncodeParam(thumbImage);<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;quality&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;Integer.parseInt(args[</SPAN><SPAN style="COLOR: #000000">4</SPAN></FONT></FONT><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">]);<BR>&nbsp;&nbsp;&nbsp;&nbsp;quality&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;Math.max(</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">,&nbsp;Math.min(quality,&nbsp;</SPAN><SPAN style="COLOR: #000000">100</SPAN></FONT></FONT><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">));<BR>&nbsp;&nbsp;&nbsp;&nbsp;param.setQuality((</SPAN><SPAN style="COLOR: #0000ff">float</SPAN><SPAN style="COLOR: #000000">)quality&nbsp;</SPAN><SPAN style="COLOR: #000000">/</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">100.0f</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">false</SPAN></FONT></FONT><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">);<BR>&nbsp;&nbsp;&nbsp;&nbsp;encoder.setJPEGEncodeParam(param);<BR>&nbsp;&nbsp;&nbsp;&nbsp;encoder.encode(thumbImage);<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">out</SPAN></FONT></FONT><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">.close();&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;System.</SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000">.println(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">Done.</SPAN><SPAN style="COLOR: #000000">"</SPAN></FONT></FONT><FONT face=Verdana><FONT size=2><SPAN style="COLOR: #000000">);<BR>&nbsp;&nbsp;&nbsp;&nbsp;System.exit(</SPAN><SPAN style="COLOR: #000000">0</SPAN></FONT></FONT><SPAN style="COLOR: #000000"><FONT face=Verdana size=2>);<BR>&nbsp;&nbsp;}<BR>}<BR></FONT></SPAN></DIV></DIV></PRE>
<DIV class=footer>
<P><FONT face=Verdana size=2>Copyright © 2002, 2003, 2004, 2005 </FONT><A href="http://schmidt.devlib.org/contact.html"><FONT face=Verdana size=2>Marco Schmidt</FONT></A><FONT face=Verdana size=2>. </FONT></P></DIV>
<SCRIPT type=text/javascript>
<!--
var awdoc=document.location.href;
if (awdoc.match(/^http/i)!=null) {
document.write('<scr' + 'ipt language="javascript" src="http://jiu.sourceforge.net/cgi-bin/pslogger.pl?loc='+escape(document.location)+'&ref='+escape(document.referrer));
if(document.all) { document.write('&size='+document.fileSize); }
document.write('"></scr' + 'ipt>'); }
-->
</SCRIPT>

<SCRIPT language=javascript src="http://jiu.sourceforge.net/cgi-bin/pslogger.pl?loc=http%3A//schmidt.devlib.org/java/save-jpeg-thumbnail.html&amp;ref=http%3A//schmidt.devlib.org/java/image-file-code-examples.html"></SCRIPT>

<DIV id=google-toolbar-tooltip style="BORDER-RIGHT: rgb(0,0,0) 1px outset; PADDING-RIGHT: 2px; BORDER-TOP: rgb(0,0,0) 1px outset; DISPLAY: none; PADDING-LEFT: 2px; Z-INDEX: 2147483647; BACKGROUND: rgb(255,255,221) 0% 50%; LEFT: 188px; PADDING-BOTTOM: 2px; FONT: medium serif; TEXT-TRANSFORM: none; BORDER-LEFT: rgb(0,0,0) 1px outset; COLOR: rgb(17,17,17); TEXT-INDENT: 0pt; PADDING-TOP: 2px; BORDER-BOTTOM: rgb(0,0,0) 1px outset; POSITION: absolute; TOP: 85px; TEXT-ALIGN: left; TEXT-DECORATION: none; font-size-adjust: none; font-stretch: normal; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">
<CENTER><SMALL><FONT face=Verdana size=2>Thumbnail: 大拇指的指甲; 极小之物; 极小的; 极短的</FONT></SMALL></CENTER></DIV><img src ="http://www.blogjava.net/Pudgy/aggbug/11457.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Pudgy/" target="_blank">Pudgy's World</a> 2005-08-29 16:12 <a href="http://www.blogjava.net/Pudgy/archive/2005/08/29/11457.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>时标和历法</title><link>http://www.blogjava.net/Pudgy/archive/2005/08/29/11420.html</link><dc:creator>Pudgy's World</dc:creator><author>Pudgy's World</author><pubDate>Mon, 29 Aug 2005 03:42:00 GMT</pubDate><guid>http://www.blogjava.net/Pudgy/archive/2005/08/29/11420.html</guid><wfw:comment>http://www.blogjava.net/Pudgy/comments/11420.html</wfw:comment><comments>http://www.blogjava.net/Pudgy/archive/2005/08/29/11420.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Pudgy/comments/commentRss/11420.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Pudgy/services/trackbacks/11420.html</trackback:ping><description><![CDATA[<!--StartFragment -->&nbsp;转自<A href="http://fmddlmyy.home4u.china.com/text8.html">http://fmddlmyy.home4u.china.com/text8.html</A>
<H2>时标和历法</H2>
<H3>1、时标</H3>时标（Time Scale）就是标度时间的方法。在时间的标度上，存在着两个相互独立的需求：一方面，我们希望时间标度能与地球的自转相吻合，可以称作天文学需求；另一方面，我们要求时间标度的单位是精确的，便于大家获得准确的时间。由于地球自转的不均匀性，从这两个需求出发制定的时标会有细微的差异。<BR>世界时（UT1）是基于地球自转的时标，下文会详细介绍。国际原子时（TAI）是基于单位时间的时标，它以“铯-133原子基态两个超精细能级间跃迁辐射 9,192,631,770周所持续的时间”为一秒，可以称作原子时标。原子时标的准确度为每日数纳秒，而世界时的准确度只有数毫秒。
<P></P>
<H4>1.1 本初子午线</H4>对于基于天文观测的时标，地球上位于不同经度的观测者，在同一瞬间测得的结果是不同的。因此需要统一的地理经度基准。<BR>1884年在华盛顿举行的国际子午线会议决定，采用英国伦敦格林威治（Greenwich）天文台埃里中星仪所在的子午线作为时间和经度计量的标准参考子午线，称为本初子午线，又称格林威治子午线。格林威治天文台于1948年迁到苏塞克斯郡（Sussex）的Herstmonceux Castle，但旧址继续被用作0度经线的位置。<BR>1957年国际上以若干天文测时结果长期稳定性较好的天文台数据为参考，求得平均天文台经度原点。1968年国际上把通过地极原点和平均天文台经度原点的子午线称为本初子午线。可见，本初子午线的定义已经不依赖于格林威治天文台旧址。
<P></P>
<H4>1.2 世界时</H4>世界时的制定基准是太阳的周日视运动。视运动就是我们看到的运动。本来是地球绕着地轴由西向东转动。但如果观测者以为自己不动，就可以认为太阳在由东向西转动，这就是太阳的周日视运动。<BR>地球在自转的同时还围绕太阳公转，因为地球公转轨道是椭圆的，所以太阳的周日视运动是不均匀的。天文学家制定了以太阳周日视运动的平均速度为基础的平太阳时，平太阳时的基本单位是平太阳日。国际天文学联合会于1928年决定，将由格林威治平子夜起算的平太阳时称为世界时，简称UT。<BR>UT0是天文台观测到的原始数据。UT1在UT0的基础上，消除了地轴摆动的影响。还有一个修正了地球自转速度季节性变动的UT2，现在已经不用了。其实UT0、UT1、UT2的差异很小，不超过0.03秒。现在提到的世界时一般指UT1。
<P></P>
<H4>1.3 时区</H4>世界时区的划分,是以本初子午线为标准，从西经7度5分到东经7度5分为零时区；从零时区的边界分别向东和向西，每隔经度15度划一个时区。东、西各划出 12个时区，东十二时区与西十二时区相重合。全球共划分成24个时区。各时区都以中央经线的地方时为本区的区时，相邻两时区的区时相差一小时。<BR>在太平洋中靠近180°经线附近有一条国际规定的国际日期变更线(简称日界线)。此线两侧的日期不同。由东向西过日界线，日期要增加一天（即略去一天不算）；由西向东过日界线，日期要减少一天(即日期重复一次)。
<P></P>
<H4>1.4 协调世界时（UTC）和闰秒</H4>为了调和天文学需求和单位时间需求的差异，一种称为协调世界时（UTC）的折衷时标于1972年面世。UTC的秒长与国际原子时（TAI）相同。但在必要时，UTC会增加1秒或去掉1秒，使UTC和世界时(UT1)的时刻之差保持在±0.9秒以内。这一技术措施被称为闰秒（Leap Second）。<BR>因此，UTC与TAI之间会出现若干整数秒的差别。位于巴黎的国际地球自转事务中央局(IERS)负责决定何时加入闰秒。TAI是从1958年1月1日0 时0分0秒开始计时的。在本文写作时（2005年7月），UTC时间比TAI时间小32秒。最近一次闰秒调整是1999年1月1日。下次闰秒调整是 2006年1月1日。<BR>我们提到的地区标准时就是在UTC上加上时差得到的本地时间。
<P></P>
<H4>1.5 格林威治时间（GMT）</H4>格林威治时间（GMT）是一个比较模糊的概念。在1928年，GMT就是世界时。在UTC被广泛采用后，我们提到的GMT实际上是UTC时间，或者说零时区的标准时。
<P></P>
<H4>1.6 GPS时间</H4>GPS时间可以看作没有闰秒调整的UTC时间，并以1980年1月6日0时0分0秒为起点。目前GPS时间比UTC时间大13秒。<BR>协调世界时（UTC）将在2005年底实施一个正闰秒。届时，所有的时钟将拨慢1秒。GPS时间不做闰秒调整，所以将比UTC时间大14秒。从GPS时间计算本地时间，需要减去目前累计的闰秒，再加上本地的时差。
<P></P>
<H4>1.7 小结</H4>在所有时标中，日和秒的关系都是固定的，每日86400秒。确定了秒的长度，就确定了日的长度，反之亦然。原子时标以秒为基准，秒和日的长度都是固定的。世界时以日为基本单位，每日的长度会有毫秒级的差异。UTC既保证了单位时间的精确，又通过闰秒调整与天文观测的时间保持不大于±0.9秒的误差。我们日常生活中使用的时间都以UTC时间为标准。<BR>时标作为时间的刻度，为时间长河建立了一根以秒或日为单位的坐标轴。虽然，“GPS时间280948秒”可以标志一个唯一的时刻，但用于日常生活未免不太方便。在日常生活中，我们需要更方便的标记时间的方法，这就是下面要谈到的历法。
<P></P>
<H3>2、历法</H3>所谓历法，就是通过合理地安排年、月、日这三个基本量的关系，为时间建立标记的方法。
<P></P>
<H4>2.1 回归年和朔望月</H4>前面说过：地球自转可以看作太阳的周日视运动。同理，地球绕太阳的公转，可以被看作太阳的周年视运动。周年视运动的轨道被称作黄道，黄道面和赤道面的夹角是23°27′。随着太阳在黄道上的位置不同，地球上的季节也由春到夏，以至秋冬。<BR>黄道和赤道的两个交点分别被称作春分点和秋分点，这两点在黄道上的两个中点分别被称作夏至点和冬至点。太阳从春分点出发，绕黄道一周，又回到春分点所花的时间被称为回归年。目前测量的回归年长度是365.242189日。<BR>月亮的盈亏变化，产生了月。月亮绕地球旋转，当转到正对着太阳的位置，我们就会观测到满月，这就是望；当转到背对太阳的位置，我们会完全看不到，这就是朔。月亮从朔到朔，或从望到望所花的时间被称作朔望月。目前测量的朔望月长度是29.530588853000001日。
<P></P>
<H4>2.2 历法的分类</H4>仅以太阳运动为依据的历法被称作阳历或太阳历。例如我们现在使用的公历。阳历以回归年为基本周期，与月亮运动没有任何关系。<BR>仅以月亮运动为依据的历法被称作阴历或太阴历。例如伊斯兰教国家和地区使用的回历。阴历以朔望月为基本周期，与太阳运动没有任何关系。<BR>同时考虑太阳和月亮运动的历法被称作阴阳历，例如我国的农历。在我国，农历习惯上也被称作阴历。阴阳历把回归年和朔望月并列为制历的基本周期。<BR>由于回归年、朔望月的长度都不是日的整数倍，所以各种历法都要通过增加闰日或闰月，来调整自己与基本周期的差异。下面介绍几种常用的历法。
<P></P>
<H4>2.3 儒略历</H4>公元前46年，罗马执政官儒略·凯撒颁布了儒略历。儒略历每年12个月，平年365天，闰年366天。除2月外，单数月份31天，偶数月份30天。2月份平年29天，闰年30天。每隔3年置一闰年。<BR>儒略历是纯太阳历，每年的平均长度是365.25天。每400年，儒略历与回归年大约相差3天，即：<BR>(365.25-365.242189)*400 = 3.1244<BR>凯撒为了纪念改历成功，将他出生的7月从Quintilis改成自己的名字Julius。
<P></P>
<H4>2.4 奥古斯都历</H4>奥古斯都是“神圣”的意思，这是当时人们对罗马统治者屋大维的尊称。<BR>从公元前42年到公元前9年，儒略历被错误地执行为“每3年置一闰年”。儒略·凯撒的侄子屋大维纠正了这个错误，同时将自己出生的8月从Sextilis 改成自己的称号Augustus，将8月改成31天，将9、10、11、12月的大小月对换，并从2月份扣去一天，成为平年28天，闰年29天。<BR>奥古斯都历的月份设置和现在的公历已经完全相同了。
<P></P>
<H4>2.5 格里高利历——公历</H4>公元1582年3月1日，罗马教皇格里高利十三世颁布了格里高利历，将不能被4整除的世纪年算作平年，这就是我们现在使用的公历。<BR>在公历中，每400年有97个闰年，平均每年的长度是：<BR>(365*400+97)/400 = 365.2425 天<BR>每400年，公历与回归年大约相差0.1244天，即：<BR>(365.2425-365.242189)*400 = 0.1244
<P></P>
<H4>2.6 儒略日和简化儒略日</H4>在天文学有一种连续纪日的儒略日（JD），它以儒略历公元前4713年1月1日的GMT正午为第0日的开始。还有一种简化儒略日（MJD）：<BR>MJD=JD-2400000.5<BR>MJD的第0日是从公历1858年11月17日的GMT零时开始的。我写完前一个句号时的MJD是53583.22260。小数部分是以UTC时间在当天逝去的秒数除以86400得到的。0.22260约为UTC时间的5:20，加上中国的时区就是13:20。<BR>需要注意：儒略历公元前4713年1月1日相当于公历公元前4713年11月24日。在香港天文台的网页上，将儒略历说成以“公元前4713年1月1日格林尼治平时正午”起算，是错误的。
<P></P>
<H4>2.7 农历</H4>
<H5>2.7.1 月的划分</H5>农历的月是严格按照朔的时刻确定的，朔所在日是初一。由于朔望月的长度约为29.A日（将小数部分记作A），假设朔发生在(30-29.A)日以内的时刻，两个朔之间就只有29天，该月就是小月；否则两个朔之间有30天，该月就是大月。
<P></P>
<H5>2.7.2 设计</H5>我们已经根据月亮的运动规律将时间长轴划分为一个个月，下面要做的就是确定将哪些月组合成年。设计要求是：该设计应使四季在每年的位置相对稳定。<BR>设计思路是这样的：四季变化以回归年为周期，回归年的长度约为365.242189日。12个朔望月的长度约为354.367066236日，13个朔望月的长度约为383.897655089。如果我们让有的年份有12个朔望月，有的年份有13个朔望月，并按照一定周期循环；在一个周期内，年的平均长度接近回归年的长度，就能实现我们的设计目标。例如：我们在19年中，让7年有13个月，其它年为12个月，则在19年的周期里，每年的平均长度是：<BR>(29.530588853000001*(12*19+7))/19 ≈ 365.246756866 天<BR>这个结果与回归年的长度已经比较接近。包含12个朔望月的年份被称作平年，包含13个朔望月的年份被称作闰年，闰年多加的一个月被称作闰月，这就是《尚书·尧典》中所说的“以闰月定四时成岁”。<BR>那么，闰月加在哪里呢？在介绍置闰的规则前，必须先介绍一下节气。
<P></P>
<H5>2.7.3 二十四节气</H5>以春分点为黄经0度，将黄道分成二十四等分，每等分占黄经15度，太阳通过等分点的时刻就是对应节气的时刻。二十四节气只与太阳的运动有关，所以它们在公历中的日期变化不大。<BR>二十四节气从立春（黄经30度）开始，依次为立春、雨水、惊蛰、春分、清明、谷雨、立夏、小满、芒种、夏至、小暑、大暑、立秋、处暑、白露、秋分、寒露、霜降、立冬、小雪、大雪、冬至、小寒、大寒。<BR>将立春作为第1个节气，依次编号。偶数编号的节气被称为“中气”（major solar terms），奇数编号的节气仍称作“节气”（minor solar terms）。我们在日常生活中将节气和中气统称为节气（solar terms）。中气是置闰的重要依据。
<P></P>
<H5>2.7.4 置闰</H5>在农历中，从前一年正月初一到下一年正月初一被称作年。显然，必须先确定了闰月，才能确定年的范围，我们不可能在置闰规则中用到“年”。实际上，我们用到了另一个概念：岁。从前一个冬至到下一个冬至被称作岁。“岁”的长度就是回归年的长度。<BR>冬至所在的月被定义为11月。如果在两个11月间有12个完整的月，那么这两个11月间的岁就被称作闰岁。因为这两个11月间只有11个中气，所以闰岁的12个月中至少有一个月没有中气。<BR>闰岁的第一个不含中气的月，就是闰月。至此，我们已经描述了编制农历的完整规则。
<P></P>
<H5>2.7.5 闰年和Y2033问题</H5>包含闰月的年被称作闰年。如果闰月出现在11月，就可能出现前一年是闰年，但不是闰岁；后一年是闰岁，但不是闰年。一个典型的例子就是Y2033问题。<BR>从2033年的第1个月算起，第8个月没有中气，第11个月有两个中气，第12个月没有中气，第13个月有两个中气，第14个月没有中气。在2032年的 11月和2033年11月间只有11个完整的月，不是闰岁。在2033年的11月和2034年11月间有12个完整的月，是闰岁。<BR>按照置闰规则，第12个月被作为闰月，即闰11月。8月没有中气，又不是闰月，被称作伪闰月（Fake leap month）。2034年是闰岁，但不是闰年。2034岁的闰月已经在2033年加过了。<BR>国内1990年以前的万年历都将2033年设为闰7月，这个错误被称作Y2033问题。以后出版的万年历都改成了闰11月。但网上的一些万年历程序现在还在使用错误的农历数据。
<P></P>
<H4>2.7 回历</H4>作为太阴历的例子，简单介绍一下回历。回历是伊斯兰教国家和地区采用的历法。它以朔望月为基本周期，每年12个月。平年奇数月30天，偶数月29天，共354天。<BR>每30年为一周，加11个闰日。在30年循环周期中，第2、5、7、10、13、16、18、21、24、26、29年为闰年。闰年在12月底增加一天,共355天。<BR>在回历中，月的平均长度是：<BR>(354*30+11)/30/12 ≈ 29.53 天<BR>这和朔望月长度非常接近，很好地符合了月亮的运动规律。年的平均长度是：<BR>(354*30+11)/30 ≈ 354.366667 天<BR>这和回归年约差11天。因此回历的新年在公历中会逐年提早，循环周期为<BR>365.242189/(365.242189-354.366667) ≈ 33.5838766176 年<BR>回历的起始历元被称作伊斯兰教纪元，定在穆罕默德从麦加迁到麦地那的一天，即儒略历公元622年7月16日，在公历中是公元622年7月19日。例如：伊斯兰教纪元1426年1月1日是公元2005年2月10日。伊斯兰教纪元1427年1月1日是公元2006年1月31日。
<P></P>
<H4>2.8 小结</H4>公历和回历的计算都很简单。但公历的月不能符合月亮的运动规律。回历的年不能符合太阳的运动规律。农历较好地符合了太阳和月亮的运动规律，但计算比较复杂。<BR>在网上可以找到计算各国历法的程序。我曾经将其中一个Java程序库的农历部分改写成C/C++程序，以提高运算速度。在我的个人主页上有关于农历计算程序的进一步讨论(<A href="http://fmddlmyy.home4u.china.com/cal.html">http://fmddlmyy.home4u.china.com/cal.html</A>)。不过这些内容已经超出了本文的范围。<BR>在写这篇文章前，我不知道“时标”，对历法的概念也很模糊。通过查资料、写作，我对相关概念的了解越来越清晰。这篇文章的写作目的是将时标、历法的一些基本概念简单、清晰地描述出来，希望有更多的读者像我一样从中受益。 
<P></P><img src ="http://www.blogjava.net/Pudgy/aggbug/11420.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Pudgy/" target="_blank">Pudgy's World</a> 2005-08-29 11:42 <a href="http://www.blogjava.net/Pudgy/archive/2005/08/29/11420.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>谈谈Unicode编码，简要解释UCS、UTF、BMP、BOM等名词</title><link>http://www.blogjava.net/Pudgy/archive/2005/08/29/11419.html</link><dc:creator>Pudgy's World</dc:creator><author>Pudgy's World</author><pubDate>Mon, 29 Aug 2005 03:39:00 GMT</pubDate><guid>http://www.blogjava.net/Pudgy/archive/2005/08/29/11419.html</guid><wfw:comment>http://www.blogjava.net/Pudgy/comments/11419.html</wfw:comment><comments>http://www.blogjava.net/Pudgy/archive/2005/08/29/11419.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/Pudgy/comments/commentRss/11419.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Pudgy/services/trackbacks/11419.html</trackback:ping><description><![CDATA[<!--StartFragment -->&nbsp;转自<A href="http://fmddlmyy.home4u.china.com/text6.html">http://fmddlmyy.home4u.china.com/text6.html</A>
<H2>谈谈Unicode编码，简要解释UCS、UTF、BMP、BOM等名词</H2>
<P>这是一篇程序员写给程序员的趣味读物。所谓趣味是指可以比较轻松地了解一些原来不清楚的概念，增进知识，类似于打RPG游戏的升级。整理这篇文章的动机是两个问题：</P>
<DL>
<DT>问题一：</DT>
<DD>
<P>使用Windows记事本的“另存为”，可以在GBK、Unicode、Unicode big endian和UTF-8这几种编码方式间相互转换。同样是txt文件，Windows是怎样识别编码方式的呢？</P>
<P>我很早前就发现Unicode、Unicode big endian和UTF-8编码的txt文件的开头会多出几个字节，分别是FF、FE（Unicode）,FE、FF（Unicode big endian）,EF、BB、BF（UTF-8）。但这些标记是基于什么标准呢？</P></DD>
<DT>问题二：</DT>
<DD>最近在网上看到一个ConvertUTF.c，实现了UTF-32、UTF-16和UTF-8这三种编码方式的相互转换。对于Unicode(UCS2)、 GBK、UTF-8这些编码方式，我原来就了解。但这个程序让我有些糊涂，想不起来UTF-16和UCS2有什么关系。</DD></DL>
<P>查了查相关资料，总算将这些问题弄清楚了，顺带也了解了一些Unicode的细节。写成一篇文章，送给有过类似疑问的朋友。本文在写作时尽量做到通俗易懂，但要求读者知道什么是字节，什么是十六进制。</P>
<H3>0、big endian和little endian</H3>
<P>big endian和little endian是CPU处理多字节数的不同方式。例如“汉”字的Unicode编码是6C49。那么写到文件里时，究竟是将6C写在前面，还是将49写在前面？如果将6C写在前面，就是big endian。如果将49写在前面，就是little endian。</P>
<P>“endian”这个词出自《格列佛游记》。小人国的内战就源于吃鸡蛋时是究竟从大头(Big-Endian)敲开还是从小头(Little-Endian)敲开，由此曾发生过六次叛乱，一个皇帝送了命，另一个丢了王位。</P>
<P>我们一般将endian翻译成“字节序”，将big endian和little endian称作“大尾”和“小尾”。</P>
<H3>1、字符编码、内码，顺带介绍汉字编码</H3>
<P>字符必须编码后才能被计算机处理。计算机使用的缺省编码方式就是计算机的内码。早期的计算机使用7位的ASCII编码，为了处理汉字，程序员设计了用于简体中文的GB2312和用于繁体中文的big5。</P>
<P>GB2312(1980年)一共收录了7445个字符，包括6763个汉字和682个其它符号。汉字区的内码范围高字节从B0-F7，低字节从A1-FE，占用的码位是72*94=6768。其中有5个空位是D7FA-D7FE。</P>
<P>GB2312支持的汉字太少。1995年的汉字扩展规范GBK1.0收录了21886个符号，它分为汉字区和图形符号区。汉字区包括21003个字符。</P>
<P>从ASCII、GB2312到GBK，这些编码方法是向下兼容的，即同一个字符在这些方案中总是有相同的编码，后面的标准支持更多的字符。在这些编码中，英文和中文可以统一地处理。区分中文编码的方法是高字节的最高位不为0。按照程序员的称呼，GB2312、GBK都属于双字节字符集 (DBCS)。</P>
<P>2000年的GB18030是取代GBK1.0的正式国家标准。该标准收录了27484个汉字，同时还收录了藏文、蒙文、维吾尔文等主要的少数民族文字。从汉字字汇上说，GB18030在GB13000.1的20902个汉字的基础上增加了CJK扩展A的6582个汉字（Unicode码 0x3400-0x4db5），一共收录了27484个汉字。</P>
<P>CJK就是中日韩的意思。Unicode为了节省码位，将中日韩三国语言中的文字统一编码。GB13000.1就是ISO/IEC 10646-1的中文版，相当于Unicode 1.1。</P>
<P>GB18030的编码采用单字节、双字节和4字节方案。其中单字节、双字节和GBK是完全兼容的。4字节编码的码位就是收录了CJK扩展A的6582个汉字。 例如：UCS的0x3400在GB18030中的编码应该是8139EF30，UCS的0x3401在GB18030中的编码应该是8139EF31。</P>
<P>微软提供了GB18030的升级包，但这个升级包只是提供了一套支持CJK扩展A的6582个汉字的新字体：新宋体-18030，并不改变内码。Windows 的内码仍然是GBK。</P>
<P>这里还有一些细节：</P>
<UL>
<LI>
<P>GB2312的原文还是区位码，从区位码到内码，需要在高字节和低字节上分别加上A0。</P></LI>
<LI>
<P>对于任何字符编码，编码单元的顺序是由编码方案指定的，与endian无关。例如GBK的编码单元是字节，用两个字节表示一个汉字。 这两个字节的顺序是固定的，不受CPU字节序的影响。UTF-16的编码单元是word（双字节），word之间的顺序是编码方案指定的，word内部的字节排列才会受到endian的影响。后面还会介绍UTF-16。</P></LI>
<LI>
<P>GB2312 的两个字节的最高位都是1。但符合这个条件的码位只有128*128=16384个。所以GBK和GB18030的低字节最高位都可能不是1。不过这不影响DBCS字符流的解析：在读取DBCS字符流时，只要遇到高位为1的字节，就可以将下两个字节作为一个双字节编码，而不用管低字节的高位是什么。</P></LI></UL>
<H3>2、Unicode、UCS和UTF</H3>
<P>前面提到从ASCII、GB2312、GBK到GB18030的编码方法是向下兼容的。而Unicode只与ASCII兼容（更准确地说，是与ISO-8859-1兼容），与GB码不兼容。例如“汉”字的Unicode编码是6C49，而GB码是BABA。</P>
<P>Unicode也是一种字符编码方法，不过它是由国际组织设计，可以容纳全世界所有语言文字的编码方案。Unicode的学名是"Universal Multiple-Octet Coded Character Set"，简称为UCS。UCS可以看作是"Unicode Character Set"的缩写。</P>
<P>根据维基百科全书(http://zh.wikipedia.org/wiki/)的记载：历史上存在两个试图独立设计Unicode的组织，即国际标准化组织（ISO）和一个软件制造商的协会（unicode.org）。ISO开发了ISO 10646项目，Unicode协会开发了Unicode项目。</P>
<P>在1991年前后，双方都认识到世界不需要两个不兼容的字符集。于是它们开始合并双方的工作成果，并为创立一个单一编码表而协同工作。从Unicode2.0开始，Unicode项目采用了与ISO 10646-1相同的字库和字码。</P>
<P>目前两个项目仍都存在，并独立地公布各自的标准。Unicode协会现在的最新版本是2005年的Unicode 4.1.0。ISO的最新标准是ISO 10646-3:2003。</P>
<P>UCS只是规定如何编码，并没有规定如何传输、保存这个编码。例如“汉”字的UCS编码是6C49，我可以用4个ascii数字来传输、保存这个编码；也可以用utf-8编码:3个连续的字节E6 B1 89来表示它。关键在于通信双方都要认可。UTF-8、UTF-7、UTF-16都是被广泛接受的方案。UTF-8的一个特别的好处是它与ISO-8859-1完全兼容。UTF是“UCS Transformation Format”的缩写。</P>
<P>IETF的RFC2781和RFC3629以RFC的一贯风格，清晰、明快又不失严谨地描述了UTF-16和UTF-8的编码方法。我总是记不得IETF是Internet Engineering Task Force的缩写。但IETF负责维护的RFC是Internet上一切规范的基础。</P>
<H4>2.1、内码和code page</H4>
<P>目前Windows的内核已经支持Unicode字符集，这样在内核上可以支持全世界所有的语言文字。但是由于现有的大量程序和文档都采用了某种特定语言的编码，例如GBK，Windows不可能不支持现有的编码，而全部改用Unicode。</P>
<P>Windows使用代码页(code page)来适应各个国家和地区。code page可以被理解为前面提到的内码。GBK对应的code page是CP936。</P>
<P>微软也为GB18030定义了code page：CP54936。但是由于GB18030有一部分4字节编码，而Windows的代码页只支持单字节和双字节编码，所以这个code page是无法真正使用的。</P>
<H3>3、UCS-2、UCS-4、BMP</H3>
<P>UCS有两种格式：UCS-2和UCS-4。顾名思义，UCS-2就是用两个字节编码，UCS-4就是用4个字节（实际上只用了31位，最高位必须为0）编码。下面让我们做一些简单的数学游戏：</P>
<P>UCS-2有2^16=65536个码位，UCS-4有2^31=2147483648个码位。</P>
<P>UCS-4根据最高位为0的最高字节分成2^7=128个group。每个group再根据次高字节分为256个plane。每个plane根据第3个字节分为256行 (rows)，每行包含256个cells。当然同一行的cells只是最后一个字节不同，其余都相同。</P>
<P>group 0的plane 0被称作Basic Multilingual Plane, 即BMP。或者说UCS-4中，高两个字节为0的码位被称作BMP。</P>
<P>将UCS-4的BMP去掉前面的两个零字节就得到了UCS-2。在UCS-2的两个字节前加上两个零字节，就得到了UCS-4的BMP。而目前的UCS-4规范中还没有任何字符被分配在BMP之外。</P>
<H3>4、UTF编码</H3>
<P></P>
<P>UTF-8就是以8位为单元对UCS进行编码。从UCS-2到UTF-8的编码方式如下：</P>
<TABLE width="75%" border=1>
<TBODY>
<TR>
<TD>UCS-2编码(16进制)</TD>
<TD>UTF-8 字节流(二进制)</TD></TR>
<TR>
<TD>0000 - 007F</TD>
<TD>0xxxxxxx</TD></TR>
<TR>
<TD>0080 - 07FF</TD>
<TD>110xxxxx 10xxxxxx</TD></TR>
<TR>
<TD>0800 - FFFF</TD>
<TD>1110xxxx 10xxxxxx 10xxxxxx</TD></TR></TBODY></TABLE>
<P>例如“汉”字的Unicode编码是6C49。6C49在0800-FFFF之间，所以肯定要用3字节模板了：<FONT color=#0000ff>1110</FONT>xxxx <FONT color=#0000ff>10</FONT>xxxxxx <FONT color=#0000ff>10</FONT>xxxxxx。将6C49写成二进制是：0110 110001 001001， 用这个比特流依次代替模板中的x，得到：<FONT color=#0000ff>1110</FONT>0110 <FONT color=#0000ff>10</FONT>110001 <FONT color=#0000ff>10</FONT>001001，即E6 B1 89。</P>
<P>读者可以用记事本测试一下我们的编码是否正确。需要注意，UltraEdit在打开utf-8编码的文本文件时会自动转换为UTF-16，可能产生混淆。你可以在设置中关掉这个选项。更好的工具是Hex Workshop。</P>
<P>UTF-16以16位为单元对UCS进行编码。对于小于0x10000的UCS码，UTF-16编码就等于UCS码对应的16位无符号整数。对于不小于0x10000的UCS码，定义了一个算法。不过由于实际使用的UCS2，或者UCS4的BMP必然小于0x10000，所以就目前而言，可以认为 UTF-16和UCS-2基本相同。但UCS-2只是一个编码方案，UTF-16却要用于实际的传输，所以就不得不考虑字节序的问题。</P>
<H3>5、UTF的字节序和BOM</H3>
<P>UTF-8以字节为编码单元，没有字节序的问题。UTF-16以两个字节为编码单元，在解释一个UTF-16文本前，首先要弄清楚每个编码单元的字节序。例如“奎”的Unicode编码是594E，“乙”的Unicode编码是4E59。如果我们收到UTF-16字节流“594E”，那么这是“奎” 还是“乙”？</P>
<P>Unicode规范中推荐的标记字节顺序的方法是BOM。BOM不是“Bill Of Material”的BOM表，而是Byte Order Mark。BOM是一个有点小聪明的想法：</P>
<P>在UCS编码中有一个叫做"ZERO WIDTH NO-BREAK SPACE"的字符，它的编码是FEFF。而FFFE在UCS中是不存在的字符，所以不应该出现在实际传输中。UCS规范建议我们在传输字节流前，先传输字符"ZERO WIDTH NO-BREAK SPACE"。</P>
<P>这样如果接收者收到FEFF，就表明这个字节流是Big-Endian的；如果收到FFFE，就表明这个字节流是Little-Endian的。因此字符"ZERO WIDTH NO-BREAK SPACE"又被称作BOM。</P>
<P>UTF-8不需要BOM来表明字节顺序，但可以用BOM来表明编码方式。字符"ZERO WIDTH NO-BREAK SPACE"的UTF-8编码是EF BB BF（读者可以用我们前面介绍的编码方法验证一下）。所以如果接收者收到以EF BB BF开头的字节流，就知道这是UTF-8编码了。</P>
<P>Windows就是使用BOM来标记文本文件的编码方式的。</P>
<H3>6、进一步的参考资料</H3>
<P>本文主要参考的资料是 "Short overview of ISO-IEC 10646 and Unicode" (http://www.nada.kth.se/i18n/ucs/unicode-iso10646-oview.html)。</P>
<P>我还找了两篇看上去不错的资料，不过因为我开始的疑问都找到了答案，所以就没有看：</P>
<OL>
<LI>"Understanding Unicode A general introduction to the Unicode Standard" (http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&amp;item_id=IWS-Chapter04a)</LI>
<LI>"Character set encoding basics Understanding character set encodings and legacy encodings" (http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&amp;item_id=IWS-Chapter03)</LI></OL>
<P>我写过UTF-8、UCS-2、GBK相互转换的软件包，包括使用Windows API和不使用Windows API的版本。以后有时间的话，我会整理一下放到我的个人主页上(http://fmddlmyy.home4u.china.com)。</P>
<P>我是想清楚所有问题后才开始写这篇文章的，原以为一会儿就能写好。没想到考虑措辞和查证细节花费了很长时间，竟然从下午1:30写到9:00。希望有读者能从中受益。</P>
<H3>附录1 再说说区位码、GB2312、内码和代码页</H3>
<P>有的朋友对文章中这句话还有疑问：<BR>“GB2312的原文还是区位码，从区位码到内码，需要在高字节和低字节上分别加上A0。”</P>
<P>我再详细解释一下：</P>
<P>“GB2312的原文”是指国家1980年的一个标准《中华人民共和国国家标准 信息交换用汉字编码字符集 基本集 GB 2312-80》。这个标准用两个数来编码汉字和中文符号。第一个数称为“区”，第二个数称为“位”。所以也称为区位码。1-9区是中文符号，16-55 区是一级汉字，56-87区是二级汉字。现在Windows也还有区位输入法，例如输入1601得到“啊”。（这个区位输入法可以自动识别16进制的 GB2312和10进制的区位码，也就是说输入B0A1同样会得到“啊”。）</P>
<P>内码是指操作系统内部的字符编码。早期操作系统的内码是与语言相关的。现在的Windows在系统内部支持Unicode，然后用代码页适应各种语言，“内码”的概念就比较模糊了。微软一般将缺省代码页指定的编码说成是内码。</P>
<P>内码这个词汇，并没有什么官方的定义，代码页也只是微软这个公司的叫法。作为程序员，我们只要知道它们是什么东西，没有必要过多地考证这些名词。</P>
<P>所谓代码页(code page)就是针对一种语言文字的字符编码。例如GBK的code page是CP936，BIG5的code page是CP950，GB2312的code page是CP20936。</P>
<P>Windows中有缺省代码页的概念，即缺省用什么编码来解释字符。例如Windows的记事本打开了一个文本文件，里面的内容是字节流：BA、BA、D7、D6。Windows应该去怎么解释它呢？</P>
<P>是按照Unicode编码解释、还是按照GBK解释、还是按照BIG5解释，还是按照ISO8859-1去解释？如果按GBK去解释，就会得到“汉字”两个字。按照其它编码解释，可能找不到对应的字符，也可能找到错误的字符。所谓“错误”是指与文本作者的本意不符，这时就产生了乱码。</P>
<P>答案是Windows按照当前的缺省代码页去解释文本文件里的字节流。缺省代码页可以通过控制面板的区域选项设置。记事本的另存为中有一项ANSI，其实就是按照缺省代码页的编码方法保存。</P>
<P>Windows的内码是Unicode，它在技术上可以同时支持多个代码页。只要文件能说明自己使用什么编码，用户又安装了对应的代码页，Windows就能正确显示，例如在HTML文件中就可以指定charset。</P>
<P>有的HTML文件作者，特别是英文作者，认为世界上所有人都使用英文，在文件中不指定charset。如果他使用了0x80-0xff之间的字符，中文Windows又按照缺省的GBK去解释，就会出现乱码。这时只要在这个html文件中加上指定charset的语句，例如：<BR>&lt;meta http-equiv="Content-Type" content="text/html; charset=ISO8859-1"&gt;<BR>如果原作者使用的代码页和ISO8859-1兼容，就不会出现乱码了。</P>
<P>再说区位码，啊的区位码是1601，写成16进制是0x10,0x01。这和计算机广泛使用的ASCII编码冲突。为了兼容00-7f的ASCII 编码，我们在区位码的高、低字节上分别加上A0。这样“啊”的编码就成为B0A1。我们将加过两个A0的编码也称为GB2312编码，虽然GB2312的原文根本没提到这一点。 </P><img src ="http://www.blogjava.net/Pudgy/aggbug/11419.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Pudgy/" target="_blank">Pudgy's World</a> 2005-08-29 11:39 <a href="http://www.blogjava.net/Pudgy/archive/2005/08/29/11419.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Gmail Invitation Send</title><link>http://www.blogjava.net/Pudgy/archive/2005/08/27/11283.html</link><dc:creator>Pudgy's World</dc:creator><author>Pudgy's World</author><pubDate>Sat, 27 Aug 2005 02:43:00 GMT</pubDate><guid>http://www.blogjava.net/Pudgy/archive/2005/08/27/11283.html</guid><wfw:comment>http://www.blogjava.net/Pudgy/comments/11283.html</wfw:comment><comments>http://www.blogjava.net/Pudgy/archive/2005/08/27/11283.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.blogjava.net/Pudgy/comments/commentRss/11283.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Pudgy/services/trackbacks/11283.html</trackback:ping><description><![CDATA[本人还有N多的Gmail Invitation 放送，要的留言。<br>
<img src ="http://www.blogjava.net/Pudgy/aggbug/11283.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Pudgy/" target="_blank">Pudgy's World</a> 2005-08-27 10:43 <a href="http://www.blogjava.net/Pudgy/archive/2005/08/27/11283.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DotDashBorder 可以实现点划线的CustomBorder</title><link>http://www.blogjava.net/Pudgy/archive/2005/08/27/11278.html</link><dc:creator>Pudgy's World</dc:creator><author>Pudgy's World</author><pubDate>Sat, 27 Aug 2005 02:19:00 GMT</pubDate><guid>http://www.blogjava.net/Pudgy/archive/2005/08/27/11278.html</guid><wfw:comment>http://www.blogjava.net/Pudgy/comments/11278.html</wfw:comment><comments>http://www.blogjava.net/Pudgy/archive/2005/08/27/11278.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Pudgy/comments/commentRss/11278.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Pudgy/services/trackbacks/11278.html</trackback:ping><description><![CDATA[<A name=navbar_top></A><A title=跳过导航链接 href="file:///Z:/doc/DotDashBorder.html#skip-navbar_top"></A>一个Custom Border<BR>可以实现点划线的Border.<BR>代码如下：<BR><BR>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #000000">import&nbsp;java.awt.</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">;<BR>import&nbsp;javax.swing.</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">;<BR>import&nbsp;javax.swing.border.</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">;<BR>&nbsp;<BR></SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">*<BR>&nbsp;*&nbsp;DotDashBorder&nbsp;is&nbsp;a&nbsp;<CODE>java.swing.border.Border</CODE>&nbsp;implementation&nbsp;<BR>&nbsp;*&nbsp;that&nbsp;draws&nbsp;a&nbsp;dotted&nbsp;and/or&nbsp;dashed&nbsp;line&nbsp;border.&nbsp;&nbsp;The&nbsp;dot/dash&nbsp;pattern&nbsp;is&nbsp;<BR>&nbsp;*&nbsp;defined&nbsp;as&nbsp;an&nbsp;array&nbsp;of&nbsp;ints,&nbsp;with&nbsp;every&nbsp;two&nbsp;indices&nbsp;defining&nbsp;the&nbsp;number&nbsp;<BR>&nbsp;*&nbsp;of&nbsp;pixels&nbsp;for&nbsp;each&nbsp;dot/dash&nbsp;and&nbsp;space.&nbsp;&nbsp;E.g.:&nbsp;<BR><BR>&nbsp;*&nbsp;{&nbsp;1,&nbsp;1&nbsp;}&nbsp;==&nbsp;1-pixel-dot,&nbsp;1-pixel-space,&nbsp;1-pixel-dot,&nbsp;1-pixel-space,&nbsp;etc.<BR><BR>&nbsp;*&nbsp;{&nbsp;4,&nbsp;2&nbsp;}&nbsp;==&nbsp;4-pixel-dash,&nbsp;2-pixel-space,&nbsp;4-pixel-dash,&nbsp;2-pixel-space,&nbsp;etc.<BR><BR>&nbsp;</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"><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;DotDashBorder&nbsp;extends&nbsp;AbstractBorder&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">*<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Defines&nbsp;a&nbsp;dotted&nbsp;line&nbsp;pattern:&nbsp;&nbsp;<PRE>.&nbsp;.&nbsp;.&nbsp;.</PRE><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"><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;final&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">[]&nbsp;DOT&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;{&nbsp;</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">&nbsp;};<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">*<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Defines&nbsp;a&nbsp;dashed&nbsp;line&nbsp;pattern:&nbsp;&nbsp;<PRE>-&nbsp;-&nbsp;-&nbsp;-</PRE><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"><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;final&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">[]&nbsp;DASH_SHORT&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;{&nbsp;</SPAN><SPAN style="COLOR: #000000">4</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">4</SPAN><SPAN style="COLOR: #000000">&nbsp;};<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">*<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Defines&nbsp;a&nbsp;long&nbsp;dashed&nbsp;line&nbsp;pattern:&nbsp;&nbsp;<PRE>---&nbsp;&nbsp;&nbsp;---&nbsp;&nbsp;&nbsp;---</PRE><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"><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;final&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">[]&nbsp;DASH_LONG&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;{&nbsp;</SPAN><SPAN style="COLOR: #000000">10</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">10</SPAN><SPAN style="COLOR: #000000">&nbsp;};<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">*<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Defines&nbsp;a&nbsp;long/short&nbsp;dashed&nbsp;line&nbsp;pattern:&nbsp;&nbsp;<PRE>--&nbsp;-&nbsp;--&nbsp;-&nbsp;--&nbsp;-</PRE><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"><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;final&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">[]&nbsp;DASH_LONG_SHORT&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;{&nbsp;</SPAN><SPAN style="COLOR: #000000">6</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">&nbsp;};<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">*<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Defines&nbsp;a&nbsp;long/short/short&nbsp;dashed&nbsp;line&nbsp;pattern:&nbsp;&nbsp;<PRE>--&nbsp;-&nbsp;-&nbsp;--&nbsp;-&nbsp;-&nbsp;--&nbsp;-&nbsp;-</PRE><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"><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;final&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">[]&nbsp;DASH_LONG_SHORT_SHORT&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;{&nbsp;</SPAN><SPAN style="COLOR: #000000">6</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">&nbsp;};<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">*<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;dot/dash&nbsp;pattern.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">private</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">[]&nbsp;pattern&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;DOT;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">*<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;border&nbsp;thickness<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">private</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;thickness&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">*<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;foreground&nbsp;color.&nbsp;&nbsp;If&nbsp;not&nbsp;specified,&nbsp;the&nbsp;component's&nbsp;foreground&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;color&nbsp;is&nbsp;used.&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">private</SPAN><SPAN style="COLOR: #000000">&nbsp;Color&nbsp;colorFG&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">null</SPAN><SPAN style="COLOR: #000000">;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">*<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;background&nbsp;color.&nbsp;&nbsp;If&nbsp;not&nbsp;specified,&nbsp;the&nbsp;component's&nbsp;background&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;color&nbsp;is&nbsp;used.&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">private</SPAN><SPAN style="COLOR: #000000">&nbsp;Color&nbsp;colorBG&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">null</SPAN><SPAN style="COLOR: #000000">;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">*<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Thicken&nbsp;border&nbsp;pattern&nbsp;relative&nbsp;to&nbsp;thickness&nbsp;flag.&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">private</SPAN><SPAN style="COLOR: #000000">&nbsp;boolean&nbsp;thicken&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">false</SPAN><SPAN style="COLOR: #000000">;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">*<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Create&nbsp;a&nbsp;new&nbsp;1-pixel&nbsp;thick&nbsp;DotDashBorder&nbsp;using&nbsp;the&nbsp;component's&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;background&nbsp;color.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;&nbsp;pattern&nbsp;&nbsp;int[]:&nbsp;the&nbsp;dot/dash-space&nbsp;pattern<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;&nbsp;fg&nbsp;&nbsp;Color:&nbsp;the&nbsp;foreground&nbsp;(dot/dash)&nbsp;color<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;DotDashBorder(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">[]&nbsp;pattern,&nbsp;Color&nbsp;fg)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">(pattern,&nbsp;</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">,&nbsp;&nbsp;fg,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">null</SPAN><SPAN style="COLOR: #000000">);<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">*<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Create&nbsp;a&nbsp;new&nbsp;DotDashBorder&nbsp;using&nbsp;the&nbsp;component's&nbsp;foreground&nbsp;and&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;background&nbsp;colors.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;&nbsp;pattern&nbsp;&nbsp;int[]:&nbsp;the&nbsp;dot/dash-space&nbsp;pattern<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;&nbsp;thickness&nbsp;&nbsp;int:&nbsp;the&nbsp;border&nbsp;thickness<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;DotDashBorder(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">[]&nbsp;pattern,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;thickness)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">(pattern,&nbsp;thickness,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">null</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">null</SPAN><SPAN style="COLOR: #000000">);<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">*<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Create&nbsp;a&nbsp;new&nbsp;DotDashBorder&nbsp;using&nbsp;the&nbsp;component's&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;background&nbsp;color.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;&nbsp;pattern&nbsp;&nbsp;int[]:&nbsp;the&nbsp;dot/dash-space&nbsp;pattern<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;&nbsp;thickness&nbsp;&nbsp;int:&nbsp;the&nbsp;border&nbsp;thickness<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;&nbsp;fg&nbsp;&nbsp;Color:&nbsp;the&nbsp;foreground&nbsp;(dot/dash)&nbsp;color<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;DotDashBorder(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">[]&nbsp;pattern,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;thickness,&nbsp;Color&nbsp;fg)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">(pattern,&nbsp;thickness,&nbsp;&nbsp;fg,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">null</SPAN><SPAN style="COLOR: #000000">);<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">*<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Create&nbsp;a&nbsp;new&nbsp;DotDashBorder.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;&nbsp;pattern&nbsp;&nbsp;int[]:&nbsp;the&nbsp;dot/dash-space&nbsp;pattern<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;&nbsp;thickness&nbsp;&nbsp;int:&nbsp;the&nbsp;border&nbsp;thickness<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;&nbsp;fg&nbsp;&nbsp;Color:&nbsp;the&nbsp;foreground&nbsp;(dot/dash)&nbsp;color<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;&nbsp;bg&nbsp;&nbsp;Color:&nbsp;the&nbsp;background&nbsp;(space)&nbsp;color<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;DotDashBorder(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">[]&nbsp;pattern,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;thickness,&nbsp;Color&nbsp;fg,&nbsp;Color&nbsp;bg)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">for</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;i&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;&nbsp;i&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;pattern.length;&nbsp;i</SPAN><SPAN style="COLOR: #000000">++</SPAN><SPAN style="COLOR: #000000">)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">(pattern[i]&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">throw</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;IllegalArgumentException(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">Pattern&nbsp;cannot&nbsp;have&nbsp;values&nbsp;&lt;=&nbsp;0.</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<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;</SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">.pattern&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;pattern;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">(thickness&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">throw</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;IllegalArgumentException(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">Thickness&nbsp;cannot&nbsp;be&nbsp;&lt;=&nbsp;0.</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">.thickness&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;thickness;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">.colorFG&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;fg;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">.colorBG&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;bg;<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">*<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Get&nbsp;the&nbsp;insets&nbsp;for&nbsp;the&nbsp;border.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;&nbsp;Component&nbsp;c:&nbsp;the&nbsp;component&nbsp;the&nbsp;border&nbsp;is&nbsp;for<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;&nbsp;Insets:&nbsp;the&nbsp;insets&nbsp;for&nbsp;the&nbsp;border<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@see&nbsp;&nbsp;#getBorderInsets(Component,&nbsp;Insets)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;Insets&nbsp;getBorderInsets(Component&nbsp;c)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;Insets(thickness,&nbsp;thickness,&nbsp;thickness,&nbsp;thickness);<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">*<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Get&nbsp;the&nbsp;insets&nbsp;for&nbsp;the&nbsp;border.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;&nbsp;Component&nbsp;c:&nbsp;the&nbsp;component&nbsp;the&nbsp;border&nbsp;is&nbsp;for<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;&nbsp;insets&nbsp;&nbsp;Insets:&nbsp;the&nbsp;insets<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;&nbsp;Insets:&nbsp;the&nbsp;insets&nbsp;for&nbsp;the&nbsp;border<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@see&nbsp;&nbsp;#getBorderInsets(Component)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;Insets&nbsp;getBorderInsets(Component&nbsp;c,&nbsp;Insets&nbsp;insets)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;Insets(thickness,&nbsp;thickness,&nbsp;thickness,&nbsp;thickness);<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">*<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Check&nbsp;if&nbsp;the&nbsp;border&nbsp;is&nbsp;opaque.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;&nbsp;boolean:&nbsp;true&nbsp;if&nbsp;the&nbsp;border&nbsp;is&nbsp;opaque<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;boolean&nbsp;isBorderOpaque()&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">true</SPAN><SPAN style="COLOR: #000000">;<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">*<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Check&nbsp;if&nbsp;pattern&nbsp;will&nbsp;be&nbsp;thickened&nbsp;by&nbsp;thickness.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;&nbsp;boolean:&nbsp;true&nbsp;if&nbsp;pattern&nbsp;will&nbsp;be&nbsp;thickened&nbsp;by&nbsp;thickness<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@see&nbsp;&nbsp;#setThickenPattern(boolean)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;boolean&nbsp;isThickenPattern()&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">.thicken;<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">*<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Set&nbsp;if&nbsp;the&nbsp;pattern&nbsp;should&nbsp;be&nbsp;thickened&nbsp;by&nbsp;thickness.&nbsp;&nbsp;If&nbsp;true,&nbsp;a&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;pattern&nbsp;of&nbsp;{&nbsp;1,&nbsp;1&nbsp;}&nbsp;and&nbsp;thickness&nbsp;of&nbsp;5,&nbsp;the&nbsp;pattern&nbsp;would&nbsp;be&nbsp;expanded&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;to&nbsp;{&nbsp;5,&nbsp;5&nbsp;}.&nbsp;&nbsp;This&nbsp;allows&nbsp;setting&nbsp;a&nbsp;pattern&nbsp;based&nbsp;on&nbsp;small&nbsp;pixel&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;measurements&nbsp;that&nbsp;grows&nbsp;proportionally&nbsp;with&nbsp;the&nbsp;thickness.&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;&nbsp;boolean&nbsp;t:&nbsp;true&nbsp;if&nbsp;pattern&nbsp;should&nbsp;be&nbsp;thickened&nbsp;by&nbsp;thickness<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@see&nbsp;&nbsp;#isThickenPattern()<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"><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 style="COLOR: #000000">&nbsp;setThickenPattern(boolean&nbsp;t)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">.thicken&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;t;<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">*<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Paint&nbsp;the&nbsp;border.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;&nbsp;Component&nbsp;c:&nbsp;the&nbsp;component&nbsp;the&nbsp;border&nbsp;is&nbsp;for<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;&nbsp;Graphics&nbsp;g:&nbsp;the&nbsp;graphics&nbsp;object&nbsp;to&nbsp;draw&nbsp;on<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;&nbsp;x&nbsp;&nbsp;int:&nbsp;the&nbsp;border&nbsp;y&nbsp;position<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;&nbsp;y&nbsp;&nbsp;int:&nbsp;the&nbsp;border&nbsp;x&nbsp;position<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;&nbsp;width&nbsp;&nbsp;int:&nbsp;the&nbsp;border&nbsp;width<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;&nbsp;height&nbsp;&nbsp;int:&nbsp;the&nbsp;border&nbsp;height<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"><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 style="COLOR: #000000">&nbsp;paintBorder(Component&nbsp;c,&nbsp;Graphics&nbsp;g,&nbsp;</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 style="COLOR: #000000">&nbsp;height)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Color&nbsp;colorFGX&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;c.getBackground();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">(colorFG&nbsp;</SPAN><SPAN style="COLOR: #000000">!=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">null</SPAN><SPAN style="COLOR: #000000">)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;colorFGX&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;colorFG;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Color&nbsp;colorBGX&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;c.getBackground();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">(colorBG&nbsp;</SPAN><SPAN style="COLOR: #000000">!=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">null</SPAN><SPAN style="COLOR: #000000">)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;colorBGX&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;colorBG;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g.setColor(colorFGX);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g.fillRect(x,&nbsp;x,&nbsp;width,&nbsp;thickness);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;top</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g.fillRect(x,&nbsp;y</SPAN><SPAN style="COLOR: #000000">+</SPAN><SPAN style="COLOR: #000000">height</SPAN><SPAN style="COLOR: #000000">-</SPAN><SPAN style="COLOR: #000000">thickness,&nbsp;width,&nbsp;thickness);&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;bottom</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g.fillRect(x,&nbsp;y,&nbsp;thickness,&nbsp;height);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;left</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g.fillRect(x</SPAN><SPAN style="COLOR: #000000">+</SPAN><SPAN style="COLOR: #000000">width</SPAN><SPAN style="COLOR: #000000">-</SPAN><SPAN style="COLOR: #000000">thickness,&nbsp;y,&nbsp;thickness,&nbsp;height);&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;right</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g.setColor(colorBGX);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;top/bottom</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;cx&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;get&nbsp;real&nbsp;pattern</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">[]&nbsp;realPattern&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">[pattern.length];<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">for</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;i&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;&nbsp;i&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;pattern.length;&nbsp;i</SPAN><SPAN style="COLOR: #000000">++</SPAN><SPAN style="COLOR: #000000">)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">(thicken)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;realPattern[i]&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;pattern[i]</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">thickness;<BR>&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;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;realPattern[i]&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;pattern[i];<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;</SPAN><SPAN style="COLOR: #0000ff">for</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;i&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">,&nbsp;j&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;&nbsp;i&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;width;&nbsp;i</SPAN><SPAN style="COLOR: #000000">++</SPAN><SPAN style="COLOR: #000000">,&nbsp;j</SPAN><SPAN style="COLOR: #000000">+=</SPAN><SPAN style="COLOR: #000000">2</SPAN><SPAN style="COLOR: #000000">)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">(j&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;=</SPAN><SPAN style="COLOR: #000000">&nbsp;realPattern.length)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;j&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;<BR>&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;cx&nbsp;</SPAN><SPAN style="COLOR: #000000">+=</SPAN><SPAN style="COLOR: #000000">&nbsp;realPattern[j];<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g.fillRect(cx,&nbsp;y,&nbsp;realPattern[j</SPAN><SPAN style="COLOR: #000000">+</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">],&nbsp;thickness);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;top</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g.fillRect(cx,&nbsp;y</SPAN><SPAN style="COLOR: #000000">+</SPAN><SPAN style="COLOR: #000000">height</SPAN><SPAN style="COLOR: #000000">-</SPAN><SPAN style="COLOR: #000000">thickness,&nbsp;realPattern[j</SPAN><SPAN style="COLOR: #000000">+</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">],&nbsp;thickness);&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;bottom</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cx&nbsp;</SPAN><SPAN style="COLOR: #000000">+=</SPAN><SPAN style="COLOR: #000000">&nbsp;realPattern[j</SPAN><SPAN style="COLOR: #000000">+</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">];<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;left/right</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;cy&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">for</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;i&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">,&nbsp;j&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;&nbsp;i&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;height;&nbsp;i</SPAN><SPAN style="COLOR: #000000">++</SPAN><SPAN style="COLOR: #000000">,&nbsp;j</SPAN><SPAN style="COLOR: #000000">+=</SPAN><SPAN style="COLOR: #000000">2</SPAN><SPAN style="COLOR: #000000">)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">(j&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;=</SPAN><SPAN style="COLOR: #000000">&nbsp;realPattern.length)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;j&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;<BR>&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;cy&nbsp;</SPAN><SPAN style="COLOR: #000000">+=</SPAN><SPAN style="COLOR: #000000">&nbsp;realPattern[j];<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g.fillRect(x,&nbsp;cy,&nbsp;thickness,&nbsp;realPattern[j</SPAN><SPAN style="COLOR: #000000">+</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">]);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;left</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g.fillRect(x</SPAN><SPAN style="COLOR: #000000">+</SPAN><SPAN style="COLOR: #000000">width</SPAN><SPAN style="COLOR: #000000">-</SPAN><SPAN style="COLOR: #000000">thickness,&nbsp;cy,&nbsp;thickness,&nbsp;realPattern[j</SPAN><SPAN style="COLOR: #000000">+</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">]);&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;right</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cy&nbsp;</SPAN><SPAN style="COLOR: #000000">+=</SPAN><SPAN style="COLOR: #000000">&nbsp;realPattern[j</SPAN><SPAN style="COLOR: #000000">+</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">];<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>}</SPAN></DIV></DIV><img src ="http://www.blogjava.net/Pudgy/aggbug/11278.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Pudgy/" target="_blank">Pudgy's World</a> 2005-08-27 10:19 <a href="http://www.blogjava.net/Pudgy/archive/2005/08/27/11278.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个简单的SplashScreen</title><link>http://www.blogjava.net/Pudgy/archive/2005/08/22/10734.html</link><dc:creator>Pudgy's World</dc:creator><author>Pudgy's World</author><pubDate>Mon, 22 Aug 2005 13:29:00 GMT</pubDate><guid>http://www.blogjava.net/Pudgy/archive/2005/08/22/10734.html</guid><wfw:comment>http://www.blogjava.net/Pudgy/comments/10734.html</wfw:comment><comments>http://www.blogjava.net/Pudgy/archive/2005/08/22/10734.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/Pudgy/comments/commentRss/10734.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Pudgy/services/trackbacks/10734.html</trackback:ping><description><![CDATA[<FONT face=Verdana size=2>最近编写项目，用到一个Splash Screen。<BR>现奉献给大家。<BR><BR>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #000000">import&nbsp;java.awt.Dimension;<BR>import&nbsp;java.awt.Toolkit;<BR>import&nbsp;java.net.URL;<BR><BR>import&nbsp;javax.swing.ImageIcon;<BR>import&nbsp;javax.swing.JFrame;<BR>import&nbsp;javax.swing.JLabel;<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;SplashScreen&nbsp;extends&nbsp;JFrame&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">*Date&nbsp;08.17.2005<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Splash&nbsp;Screen<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Very&nbsp;Simple<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@author&nbsp;Pudgy<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@version&nbsp;0.01<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">private</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">static</SPAN><SPAN style="COLOR: #000000">&nbsp;final&nbsp;</SPAN><SPAN style="COLOR: #0000ff">long</SPAN><SPAN style="COLOR: #000000">&nbsp;serialVersionUID&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">5124L</SPAN><SPAN style="COLOR: #000000">;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;SplashScreen()&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">Starting&nbsp;jDicomSee<IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Toolkit&nbsp;toolkit&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;Toolkit.getDefaultToolkit();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Dimension&nbsp;screenSize&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;toolkit.getScreenSize();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;URL&nbsp;imageURL&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;searchFile(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">splash.png</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">&nbsp;(imageURL&nbsp;</SPAN><SPAN style="COLOR: #000000">!=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">null</SPAN><SPAN style="COLOR: #000000">)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getContentPane().add(</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;JLabel(</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;ImageIcon(imageURL)));<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setUndecorated(</SPAN><SPAN style="COLOR: #0000ff">true</SPAN><SPAN style="COLOR: #000000">);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pack();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setLocation((screenSize.width&nbsp;</SPAN><SPAN style="COLOR: #000000">-</SPAN><SPAN style="COLOR: #000000">&nbsp;getWidth())&nbsp;</SPAN><SPAN style="COLOR: #000000">/</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">2</SPAN><SPAN style="COLOR: #000000">,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(screenSize.height&nbsp;</SPAN><SPAN style="COLOR: #000000">-</SPAN><SPAN style="COLOR: #000000">&nbsp;getHeight())&nbsp;</SPAN><SPAN style="COLOR: #000000">/</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">2</SPAN><SPAN style="COLOR: #000000">);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setVisible(</SPAN><SPAN style="COLOR: #0000ff">true</SPAN><SPAN style="COLOR: #000000">);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">try</SPAN><SPAN style="COLOR: #000000">&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread.sleep(</SPAN><SPAN style="COLOR: #000000">1500</SPAN><SPAN style="COLOR: #000000">);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</SPAN><SPAN style="COLOR: #0000ff">catch</SPAN><SPAN style="COLOR: #000000">&nbsp;(InterruptedException&nbsp;e)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">private</SPAN><SPAN style="COLOR: #000000">&nbsp;URL&nbsp;searchFile(String&nbsp;fileName)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;URL&nbsp;url&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;getClass().getClassLoader().getResource(fileName);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">&nbsp;(url&nbsp;</SPAN><SPAN style="COLOR: #000000">==</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">null</SPAN><SPAN style="COLOR: #000000">)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;url&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;getClass().getClassLoader().getResource(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">images/</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">+</SPAN><SPAN style="COLOR: #000000">&nbsp;fileName);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000">&nbsp;url;<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>}<BR></SPAN></DIV></DIV></FONT><img src ="http://www.blogjava.net/Pudgy/aggbug/10734.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Pudgy/" target="_blank">Pudgy's World</a> 2005-08-22 21:29 <a href="http://www.blogjava.net/Pudgy/archive/2005/08/22/10734.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Fat Jar Eclipse Plug-In Tutorial</title><link>http://www.blogjava.net/Pudgy/archive/2005/08/22/10727.html</link><dc:creator>Pudgy's World</dc:creator><author>Pudgy's World</author><pubDate>Mon, 22 Aug 2005 12:31:00 GMT</pubDate><guid>http://www.blogjava.net/Pudgy/archive/2005/08/22/10727.html</guid><wfw:comment>http://www.blogjava.net/Pudgy/comments/10727.html</wfw:comment><comments>http://www.blogjava.net/Pudgy/archive/2005/08/22/10727.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.blogjava.net/Pudgy/comments/commentRss/10727.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Pudgy/services/trackbacks/10727.html</trackback:ping><description><![CDATA[<p><font face="Verdana"><font size="2">Fat Jar Eclipse Plug-In [FJEP] (<a href="http://fjep.sourceforge.net/">http://fjep.sourceforge.net/</a></font>) <font size="2">是应用One-Jar(<a href="http://one-jar.sourceforge.net/">http://one-jar.sourceforge.net/</a>)技术的一个Eclipse 插件。利用FatJar，可以极大地方便发布Java应用程序与Applet。<br>下面是我写的一个教程，欢迎指教。<br><br>1.介绍<br></font></font><font color="#000000" size="2">一个非常简单的软件打包解决方案，它利用 Java 的定制类装入器，动态地从单一档案文件中装入应用程序所有的类，同时保留支持 JAR 文件的结构。随着 FatJar Eclipse 插件<font size="3"><font size="2"> FJEP 的推出， Eclipse 的用户现在只要在向导中选中一个复选框，就可以创建 One-JAR 应用程序。依赖的库被放进 lib/ 目录，主程序和类被放进 main/main.jar，并自动写好 META-INF/MANIFEST.MF 文件</font>。<br><br>2.</font><font size="2">安装<br>安装很简单，只需把解压出来的文件放到Eclipse 的目录中即可。<br><br>3.使用图解<br>我以打包我的程序文件作为例子。<br><br>(1)在包浏览器面板中，选中Build Fat Jar。<br><img alt="o_FatJar-1.png" src="http://www.blogjava.net/images/blogjava_net/pudgy/2948/o_FatJar-1.png" border="0" height="645" width="373"><br><br>(2)选择主类入口。注意选中Merge individual-sections of all MANIFEST.MF Files.。<br><img alt="o_FatJar-2.png" src="http://www.blogjava.net/images/blogjava_net/pudgy/2948/o_FatJar-2.png" border="0" height="441" width="432"><br><br>(3)选择你要打包的独立JAR文件，这些文件会打包进入最后的Fat-Jar。<br><img alt="o_FatJar-3.png" src="http://www.blogjava.net/images/blogjava_net/pudgy/2948/o_FatJar-3.png" border="0" height="468" width="440"><br><br>(4)成功了。<br><img alt="o_FatJar-4.png" src="http://www.blogjava.net/images/blogjava_net/pudgy/2948/o_FatJar-4.png" border="0" height="139" width="441"><br>4.SWT 程序的打包<br>同样的步骤，只不过最后发布时，连带SWT-XXX.DLL放在同一目录下即可。<br>参见<a href="http://fjep.sourceforge.net/fjepfaq.html">http://fjep.sourceforge.net/fjepfaq.html</a><br><br>5.下载<br><a href="http://fjep.sourceforge.net/fjepfaq.html">http://fjep.sourceforge.net/</a><br>也可下载我已打包好的文件。<br><A href="http://www.blogjava.net/Files/Pudgy/net.sf.fjep.fatjar_0.0.18.rar">http://www.blogjava.net/Files/Pudgy/net.sf.fjep.fatjar_0.0.18.rar</a></font></font></p><img src ="http://www.blogjava.net/Pudgy/aggbug/10727.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Pudgy/" target="_blank">Pudgy's World</a> 2005-08-22 20:31 <a href="http://www.blogjava.net/Pudgy/archive/2005/08/22/10727.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>基于Batik的SVG应用: 关于几何变换</title><link>http://www.blogjava.net/Pudgy/archive/2005/08/20/10572.html</link><dc:creator>Pudgy's World</dc:creator><author>Pudgy's World</author><pubDate>Sat, 20 Aug 2005 00:55:00 GMT</pubDate><guid>http://www.blogjava.net/Pudgy/archive/2005/08/20/10572.html</guid><wfw:comment>http://www.blogjava.net/Pudgy/comments/10572.html</wfw:comment><comments>http://www.blogjava.net/Pudgy/archive/2005/08/20/10572.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Pudgy/comments/commentRss/10572.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Pudgy/services/trackbacks/10572.html</trackback:ping><description><![CDATA[<FONT face=Verdana size=2>
<P>摘自<A href="http://www-128.ibm.com/developerworks/cn/xml/x-BatikSvg/?ca=dwcn-newsletter-xml">http://www-128.ibm.com/developerworks/cn/xml/x-BatikSvg/?ca=dwcn-newsletter-xml</A><A href="http://www-128.ibm.com/developerworks/cn/xml/x-BatikSvg/?ca=dwcn-newsletter-xml#author1"><NAME><BR>陈柯</NAME></A><BR>技术总监, 南京安元科技<BR>2005 年 1 月 </P>
<BLOCKQUOTE>本文是作者在 SVGGIS 系统的开发实践过程中关于 SVG 坐标转换的总结。在描述 SVG 坐标变换原理的同时，使用 Apache Batik 项目实现了相关例子。</BLOCKQUOTE>
<P>SVG 是一种用 xml 语言来描述二维图形对象的语言，SVG 允许三种图形对象：1．矢量图形，2．图片，3．文本对象。这三种图形对象都可以支持分组，使用样式渲染，进行几何变换。</P>
<P>SVG 还能够通过脚本来实现交互操作和动态显示。可以通过定义动画对象或使用script 脚本来实现动画。</P>
<P><A name=N1004D><SPAN class=atitle2>1. SVG 下几种常见的几何变换方式</SPAN></A><BR></P>
<P><A name=N10053><SPAN class=atitle3>1.1 一个 SVG 例子</SPAN></A><BR>我们首先来看一个 SVG 的例子，窗口右上角有四个色块，每个色块是一个50×50的矩形。</P>
<P><A name=N1005E><B>图 1. 一个 SVG 的样本</B></A><BR><IMG height=320 alt="图 1. 一个 SVG 的样本" src="http://www-128.ibm.com/developerworks/cn/xml/x-BatikSvg/images/image002.jpg" width=311 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P><A name=N1006E><B>图 2. 样本文档</B></A><BR>
<TABLE style="WIDTH: 592px; HEIGHT: 191px" cellSpacing=0 cellPadding=5 width=592 bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
&lt;?xml version="1.0"?&gt;
&lt;svg &gt;
    &lt;g&gt; 
	&lt;rect x="0" y="0" width="50" height="50" style="fill:red" /&gt;
	&lt;rect x="50" y="0" width="50" height="50" style="fill:yellow" /&gt;
	&lt;rect x="0" y="50" width="50" height="50" style="fill:green" /&gt;
	&lt;rect x="50" y="50" width="50" height="50" style="fill:black" /&gt;
    &lt;/g&gt;
&lt;/svg&gt;
</CODE></PRE></TD></TR></TBODY></TABLE>
<P><A name=N10078><SPAN class=atitle3>1.2 使用 Adobe SVG Viewer 展示在 SVG 文档中实现的几何变换</SPAN></A><BR>缩放&lt;g transform="scale(2)"&gt;</P>
<P><A name=N10083><B>图 3. 放大一倍</B></A><BR><IMG height=346 alt="图 3. 放大一倍" src="http://www-128.ibm.com/developerworks/cn/xml/x-BatikSvg/images/image004.jpg" width=337 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P>平移&lt;g transform="translate(200 ,200)"&gt;</P>
<P><A name=N10098><B>图 4. 平移200，200个像素</B></A><BR><IMG height=317 alt="图 4. 平移200，200个像素" src="http://www-128.ibm.com/developerworks/cn/xml/x-BatikSvg/images/image006.jpg" width=308 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P>旋转&lt;g transform="rotate(45)"&gt;</P>
<P><A name=N100AD><B>图 5. 顺时针旋转45度</B></A><BR><IMG height=333 alt="图 5. 顺时针旋转45度" src="http://www-128.ibm.com/developerworks/cn/xml/x-BatikSvg/images/image008.jpg" width=325 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P>横切&lt;g transform="skewX(45)"&gt;</P>
<P><A name=N100C2><B>图 6. 以 y 轴为基线在 X 方向横切45度</B></A><BR><IMG height=332 alt="图 6. 以 y 轴为基线在 X 方向横切45度" src="http://www-128.ibm.com/developerworks/cn/xml/x-BatikSvg/images/image010.jpg" width=323 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P><A name=N100D2><SPAN class=atitle2>2. 在 Batik 下实现 SVG 的几何变换</SPAN></A><BR></P>
<P><A name=N100D8><SPAN class=atitle3>2.1 Batik 的基础知识</SPAN></A><BR><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">2.1.1 Batik 的用途</B> </P>
<P>Batik 是基于 java 语言实现的一个 SVG 应用的工具集，用于实现对 SVG 对象的显示、编辑以及将 SVG 图形对象转换成其他图片格式，如 jpg、gif 等。</P>
<P>这个项目的目标就是给开发人员一套用于处理或应用 SVG 对象的基础核心模型。作为Apache 项目成员之一，该项目也为开发人员提供了一个开发的可扩展的平台。同时 batik 也维护了一个可以查看 SVG 文件的浏览器。虽然 batik 还没有完全实现 SVG 的所有标准语法和标记，但通过比较不同版本的区别就会发现，他正在以很高的效率覆盖 SVG 所有的标准。</P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">2.1.2 让我们实现一个简单的 Batik 程序</B> </P>
<P>首先让我们实现一个简单的基于 Batik 的 SVG 浏览器。Batik 封装了org.apache.batik.swing.JSVGCanvas 对象可以用于在 swing 中嵌入 SVG 显示容器，并可以通过 org.apache.batik.swing.JSVGCanvas 提供的方法对 SVG 文档和图像进行操作。这个浏览器可以支持大部分 SVG 的语法和标准包括脚本交互的功能，但暂时还没有引入动画。关于动画和脚本交互的内容我们会在以后的文章中讲述，今天先集中解决几何变换的问题。</P>
<P><A name=N100F5><B>图 7. 运行程序打开我们编写的 SVG 的例子</B></A><BR><IMG height=391 alt="图 7. 运行程序打开我们编写的 SVG 的例子" src="http://www-128.ibm.com/developerworks/cn/xml/x-BatikSvg/images/image012.jpg" width=469 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P>可以通过该页面引导运行该程序： <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">从附件中可以查看该程序的完整代码，也可通过 <A href="http://221.130.8.10:8080/discover/batik/index.htm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">网上下载地址</A> 运行该程序。 </P><A name=N1010E><B>图 8. 将一个 SVGCanvas 添加到界面</B></A><BR>
<TABLE style="WIDTH: 600px; HEIGHT: 95px" cellSpacing=0 cellPadding=5 width=600 bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
private javax.swing.JPanel SVGPanel = new javax.swing.JPanel();
private JSVGCanvas svgCanvas = new org.apache.batik.swing.JSVGCanvas();
SVGPanel.add("Center", svgCanvas);
</CODE></PRE></TD></TR></TBODY></TABLE>
<P><A name=N10118><SPAN class=atitle3>2.2 通过 Batik 的 GVT 模型实现 SVG 的几何变换</SPAN></A><BR><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">2.2.1 为什么要使用 Batik 来实现 SVG 的几何变换</B> </P>
<P>当我们用 Batik 工具集作为 SVG 客户端的解决方案时，如缩放平移这样的操作就在所难免了。但 Batik 并没有直接支持如 Adobe SVG Viewer 那样的鼠标拖动几何变换的操作，这就要求我们对这些功能进行编程处理。</P>
<P>在分析 SVG 的几何变换的细节之前，先让我们了解一下基本的操作编程方式。</P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">2.2.2 Batik 下通过 java.awt.geom.AffineTransform 来实现 SVG 的几何变换</B> </P>
<P>JSVGCanvas 提供方法可以获取 java.awt.geom.AffineTransform 对象。AffineTransform 是用于实现2D 几何图形坐标变换处理的对象，可以通过该对象进行二维几何空间中两个坐标系的相互映射和变换。</P>
<P>平移:</P><A name=N10136><B></B></A><BR>
<TABLE style="WIDTH: 589px; HEIGHT: 112px" cellSpacing=0 cellPadding=5 width=589 bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
//向左和向下平移50个像素
java.awt.geom.AffineTransform  rat = svgCanvas.getRenderingTransform();
rat.translate(50,50);
svgCanvas.setRenderingTransform(rat);
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>缩放:</P><A name=N10142><B></B></A><BR>
<TABLE style="WIDTH: 586px; HEIGHT: 111px" cellSpacing=0 cellPadding=5 width=586 bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
//以屏幕左上角原点为固定点进行缩放操作
java.awt.geom.AffineTransform  rat = svgCanvas.getRenderingTransform();
rat.scale(0.5,0.5);
svgCanvas.setRenderingTransform(rat);
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>旋转:</P><A name=N1014E><B></B></A><BR>
<TABLE style="WIDTH: 585px; HEIGHT: 113px" cellSpacing=0 cellPadding=5 width=585 bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
//以屏幕左上角原点为固定点进行旋转缩放
java.awt.geom.AffineTransform  rat = svgCanvas.getRenderingTransform();
rat.rotate(3.1415926/4);
svgCanvas.setRenderingTransform(rat);
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>复合变换:</P><A name=N1015A><B></B></A><BR>
<TABLE style="WIDTH: 586px; HEIGHT: 144px" cellSpacing=0 cellPadding=5 width=586 bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
//一个综合平移、放大和旋转90度的复合变换
java.awt.geom.AffineTransform  rat = svgCanvas.getRenderingTransform();
rat.translate(50，50);
rat.scale(2，2);
rat.rotate(3.1415926/4);
svgCanvas.setRenderingTransform(rat);
</CODE></PRE></TD></TR></TBODY></TABLE>
<P><A name=N10163><SPAN class=atitle2>3. 当我们需要进行复合几何变换的时候</SPAN></A><BR></P>
<P><A name=N10169><SPAN class=atitle3>3.1 先来让我们通过不同的变换代码组合实现复合几何变换</SPAN></A><BR>先让我们看第一个例子:</P>//放大一倍和平移50个像素的复合变换 <A name=N10172><B></B></A><BR>
<TABLE style="WIDTH: 467px; HEIGHT: 163px" cellSpacing=0 cellPadding=5 width=467 bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
AffineTransform rat = svgCanvas.getRenderingTransform();

        <FONT color=#ff0000>rat.scale(2,2);
rat.translate(50,50);</FONT>
svgCanvas.setRenderingTransform(rat);

      </CODE></PRE></TD></TR></TBODY></TABLE>
<P><A name=N10181><B>图 9. 复合变换一</B></A><BR><IMG height=363 alt="图 9. 复合变换一" src="http://www-128.ibm.com/developerworks/cn/xml/x-BatikSvg/images/image014.jpg" width=440 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P>可以看得出来，这个变换的最终效果是：图形的形状放大一倍，原图形的（0，0）原点坐标平移100个像素。</P>
<P>再来看第二个例子:</P><A name=N10197><B></B></A><BR>
<TABLE style="WIDTH: 465px; HEIGHT: 177px" cellSpacing=0 cellPadding=5 width=465 bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
//放大一倍和平移50个像素的复合变换
AffineTransform rat = svgCanvas.getRenderingTransform();

        <FONT color=#ff0000>rat.translate(50,50);
rat.scale(2,2);</FONT>
svgCanvas.setRenderingTransform(rat);

      </CODE></PRE></TD></TR></TBODY></TABLE>
<P><A name=N101A6><B>图 10. 复合变换二</B></A><BR><IMG height=372 alt="图 10. 复合变换二" src="http://www-128.ibm.com/developerworks/cn/xml/x-BatikSvg/images/image016.jpg" width=452 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P>这个变换的最终效果是：图形的形状放大一倍，原图形的（0，0）原点坐标平移50个像素。</P>
<P><A name=N101B9><SPAN class=atitle3>3.2 关键是顺序</SPAN></A><BR>比较一下这两种平移后的效果会发现,只是因为缩放和平移的顺序不同，变换后的结果就发生了区别。第一个例子实际平移的不是50个像素,而是100个像素。而第二个例子则是平移了50个像素。</P>
<P>有兴趣的读者可以添加其他几何变换方式，并测试不同的变换顺序，会发现复合变换的顺序与复合变换的最终效果是紧密相关的。那么如何分析和计算复合变换的变换结果呢？这里我们需要补充一点数学知识了。</P>
<P><A name=N101C5><SPAN class=atitle3>3.3 对单一的几何变换进行数学模型分析</SPAN></A><BR>对计算机图形学中图形变换相关理论很熟悉的人可以跳过这部分直接看 Batik 的实现方式。这节使用的齐次式图片引用自 <A href="http://www.w3.org/TR/2001/REC-SVG-20010904/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">SVG标准</A>中关于坐标变换的齐次式的例子插图。 </P>
<P>首先我们来了解一下图形变换的齐次式计算方法：</P>
<P><A name=N101D7><B>图 11. 基本几何 变换齐次式</B></A><BR><IMG height=83 alt="图 11. 基本几何 变换齐次式" src="http://www-128.ibm.com/developerworks/cn/xml/x-BatikSvg/images/image017.gif" width=408 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P>这是一个基本图形变换齐次式。等式的最右边是一个坐标点未变换前的坐标矩阵，最左边是该坐标点变换后所在位置的一个三行一列的坐标矩阵，中间那个三行三列的矩阵就是变换矩阵。不同的变换方式将对应不同的变换矩阵，图形平移效果就是通过这样一个变换齐次式来实现的。</P>
<P>平移:如果需要将图形平移（tx，ty）个坐标时，采用如下的变换矩阵带入变换方程。</P>
<P><A name=N101EF><B>图 12. 平移变换矩阵</B></A><BR><IMG height=83 alt="图 12. 平移变换矩阵" src="http://www-128.ibm.com/developerworks/cn/xml/x-BatikSvg/images/image018.gif" width=104 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P>缩放：如果需要在 x 轴方向实现 sx 倍缩放，在 y 轴方向实现 sy 轴缩放时，采用如下的变换矩阵带入变换方程。</P>
<P><A name=N10204><B>图 13. 缩放变换矩阵</B></A><BR><IMG height=83 alt="图 13. 缩放变换矩阵" src="http://www-128.ibm.com/developerworks/cn/xml/x-BatikSvg/images/image019.gif" width=104 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P>旋转:如果需要将图像旋转 a 度时，使用如下的变换矩阵带入变换方程。</P>
<P><A name=N10219><B>图 14. 旋转变换矩阵</B></A><BR><IMG height=83 alt="图 14. 旋转变换矩阵" src="http://www-128.ibm.com/developerworks/cn/xml/x-BatikSvg/images/image020.gif" width=169 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P><A name=N10229><SPAN class=atitle3>3.4 采用复合几何变换的数学模型分析</SPAN></A><BR>3.4.1 数学分析</P>
<P>当两组变换同时作用于同一个图像时，连续使用该等式，得出如下等式。由于做变换的时候是将变换矩阵放在矩阵积的左边，所以对于复合变换的式子，应该从右向左进行读。对于如下的式子：从右至左依次是变换前的坐标，第一次转换的转换矩阵，第二次转换的转换矩阵，转换后的坐标值。</P>
<P><A name=N10237><B>图 15. 进行两次变换的复合矩阵</B></A><BR><IMG height=83 alt="图 15. 进行两次变换的复合矩阵" src="http://www-128.ibm.com/developerworks/cn/xml/x-BatikSvg/images/image021.gif" width=359 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P>进一步推导 n 次几何变换的复合变换等式：</P>
<P><A name=N1024C><B>图 16. n次变换的复合矩阵</B></A><BR><IMG height=179 alt="图 16. n次变换的复合矩阵" src="http://www-128.ibm.com/developerworks/cn/xml/x-BatikSvg/images/image022.gif" width=483 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">3.4.2 来实践一下</B> </P>
<P><A name=N10264><B>图 17. 变换前效果</B></A><BR><IMG height=252 alt="图 17. 变换前效果" src="http://www-128.ibm.com/developerworks/cn/xml/x-BatikSvg/images/image024.jpg" width=428 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P>使用这样一个复合变换方式：</P>
<P>&lt;g transform="translate(50,90) rotate(-45) translate(130,160)"&gt; </P>
<P>根据前面的分析结果带入变换方程，得出如下等式</P>
<P><A name=N1027F><B>图 18. 推导矩阵</B></A><BR><IMG height=296 alt="图 18. 推导矩阵" src="http://www-128.ibm.com/developerworks/cn/xml/x-BatikSvg/images/image025.gif" width=512 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P>根据计算后的变换矩阵，可得变换结果是图形整体平移到（255.03,111.21），同时图形自身沿顺时针方向旋转45度。查看实际变换结果，这里我们可以发现，对于 SVG 的变换来说，虽然我们习惯上从左往右写变换参数的，实际上图形做变换的时候是从右边的变换参数开始依次进行图形变换的。</P>
<P><A name=N10294><B>图 19. 变换后效果</B></A><BR><IMG height=281 alt="图 19. 变换后效果" src="http://www-128.ibm.com/developerworks/cn/xml/x-BatikSvg/images/image027.jpg" width=553 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P><A name=N102A4><SPAN class=atitle3>3.5 分析一下 Batik 是如何实现 SVG 的复合几何变换的</SPAN></A><BR><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">3.5.1 先看第一个例子：</B> </P>
<P>这个变换是先放大后平移的变换，其变换效果最终是，先将图形的形状放大一倍，然后将图形整个平移100个像素。这里我们可以看出，虽然我们是先进行的放大变换，后进行的平移操作，但当我们进行复合变换的时候由于实际运算时上是先进行了平移，后进行了缩放。或者简单的理解为从左向右先写缩放矩阵，再写平移矩阵，这样得出的变换矩阵就可以对变换后的效果进行计算了。</P><A name=N102B3><B></B></A><BR>
<TABLE style="WIDTH: 510px; HEIGHT: 193px" cellSpacing=0 cellPadding=5 width=510 bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
//放大一倍和平移50个像素的复合变换
//&lt;g transform=" scale(2 ) translate(50 50)"&gt;
AffineTransform rat = svgCanvas.getRenderingTransform();

        <FONT color=#ff0000>rat.scale(2,2);
rat.translate(50,50);</FONT>
svgCanvas.setRenderingTransform(rat);

      </CODE></PRE></TD></TR></TBODY></TABLE>
<P>我们可以将这个变换对应的计算矩阵写出来：</P>
<P><A name=N102C5><B>图 20. 复合变换例一的变换矩阵</B></A><BR><IMG height=291 alt="图 20. 复合变换例一的变换矩阵" src="http://www-128.ibm.com/developerworks/cn/xml/x-BatikSvg/images/image029.jpg" width=470 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P>根据上面的分析我们可以看的出，先进行缩放变换在进行平移变换的复合变换时，变换后原图元的坐标会映射到新的位置，其中：</P>
<P>X1=Sx(X+dx) <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Y1=Sy(Y+dy) </P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">3.5.2 再来看第二个例子：</B> </P>
<P>这个变换是先放大后平移的变换，其变换效果最终是，先将图形整个平移50个像素，然后将图形的形状放大一倍。</P><A name=N102E6><B></B></A><BR>
<TABLE style="WIDTH: 493px; HEIGHT: 192px" cellSpacing=0 cellPadding=5 width=493 bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
//放大一倍和平移50个像素的复合变换
//&lt;g transform="translate(50，50) scale(2 )"&gt;
AffineTransform rat = svgCanvas.getRenderingTransform();

        <FONT color=#ff0000>rat.translate(50,50);
rat.scale(2,2);</FONT>
svgCanvas.setRenderingTransform(rat);

      </CODE></PRE></TD></TR></TBODY></TABLE>
<P>我们可以将这个变换对应的 svg 文档实现写出来：</P>
<P>&lt;g transform="translate(50 50) scale(2 )"&gt;</P>
<P><A name=N102FB><B>图 21. 复合变换例二的变换矩阵</B></A><BR><IMG height=259 alt="图 21. 复合变换例二的变换矩阵" src="http://www-128.ibm.com/developerworks/cn/xml/x-BatikSvg/images/image032.jpg" width=416 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P>根据上面的分析我们可以看的出，先进行平移变换再进行缩放变换的复合变换时，变换后原图元的坐标会映射到新的位置，其中：</P>
<P>X1=Sx*X+dx <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Y1=Sy*Y+dy </P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">3.5.3 实用这两个例子的成果</B> </P>
<P>假设我们需要将图形原点的位置移动到（150，300），同时形状放大到原来的3倍，该如何进行变换来实现这样的效果呢？</P>
<P><A name=N1031E><B>图 22. 变换效果</B></A><BR><IMG height=343 alt="图 22. 变换效果" src="http://www-128.ibm.com/developerworks/cn/xml/x-BatikSvg/images/image034.jpg" width=476 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P>使用第一个例子的分析结果，先进行缩放变换，再进行平移变换的方程变换：</P>
<P><A name=N10333><B>图 23. 方程推演</B></A><BR><IMG height=68 alt="图 23. 方程推演" src="http://www-128.ibm.com/developerworks/cn/xml/x-BatikSvg/images/image036.jpg" width=460 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P>根据推导可知需先进行3倍的缩放变换，再平移（50，100）个坐标就可以实现指定的变换效果。实现程序如下</P><A name=N10346><B></B></A><BR>
<TABLE style="WIDTH: 497px; HEIGHT: 177px" cellSpacing=0 cellPadding=5 width=497 bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
//&lt;g transform=" scale(3 ) translate(50，100)"&gt;
AffineTransform rat = svgCanvas.getRenderingTransform();

        <FONT color=#ff0000>rat.scale(3,3);
rat.translate(50,100);</FONT>
svgCanvas.setRenderingTransform(rat);

      </CODE></PRE></TD></TR></TBODY></TABLE>
<P>若先进行平移变换，再进行缩放变换的话，根据第二个例子的推导结果：</P>
<P><A name=N10358><B>图 24. 方程推演</B></A><BR><IMG height=67 alt="图 24. 方程推演" src="http://www-128.ibm.com/developerworks/cn/xml/x-BatikSvg/images/image038.jpg" width=469 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P>可知应先进行（150，300）的平移操作，再实现3倍的缩放操作。实现程序如下：</P><A name=N1036B><B></B></A><BR>
<TABLE style="WIDTH: 495px; HEIGHT: 177px" cellSpacing=0 cellPadding=5 width=495 bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
//&lt;g transform=" translate(150，300) scale(3 )"&gt;
AffineTransform rat = svgCanvas.getRenderingTransform();

        <FONT color=#ff0000>rat.translate(150,300);
rat.scale(3,3);</FONT>
svgCanvas.setRenderingTransform(rat);

      </CODE></PRE></TD></TR></TBODY></TABLE>
<P><A name=N10378><SPAN class=atitle2>4. 一个常用复合变换实例的实现--定点变换</SPAN></A><BR>上边我们分析了 Batik 实现 SVG 图形变换的原理和计算方法。下面我们用分析的结果实现一个常用的变换实例：定点变换。变换的种类包括缩放，旋转（一般不考虑定点平移这个概念）。</P>
<P>所谓定点变换就是在图形变换中指定一个固定的点，在变换结束后，该点的位置不发生变化。定点变换在 GIS 的实际运用中很常见，比如将地图放大到指定倍数而保持地图的某个位置（如：鼠标点击的位置）不发生变化。我们以定点缩放为例描述定点变换的使用方法。</P>
<P>假设我们用(x1,y1)点来做定点变换的基准点进行几何变换，要求实现变换后（x1,y1）的位置不变。</P>
<P>定点变换的基本思想是基于这样一个特性：当图像进行缩放，或旋转变换的时候，坐标原点的位置并不发生变化。定点变换的实现方法就是，先将基准点（x1,y1）平移到原点即做一次[-x1,-y1]变换，进行变换后再将变换后的原点平移到（x1,y1）即再进行一次[x1,y1]变换。</P>
<P><A name=N1038C><B>图 25. 基于（x1,y1）定点变换</B></A><BR><IMG height=262 alt="图 25. 基于（x1,y1）定点变换" src="http://www-128.ibm.com/developerworks/cn/xml/x-BatikSvg/images/image040.jpg" width=540 border=0 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P>实际编程的时候，我们无需对定点变换做如此复杂的运算。例如可以采用如下的方式实现针对（50,50）的定点变换：</P><A name=N1039F><B></B></A><BR>
<TABLE style="WIDTH: 587px; HEIGHT: 253px" cellSpacing=0 cellPadding=5 width=587 bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
//以（50，50）点为基准点进行几何变换
//&lt;g transform="translate(50，50) …………… translate(-50，-50)"&gt;
AffineTransform rat = svgCanvas.getRenderingTransform();

        <FONT color=#ff0000>rat.translate(50，50);
//其他变换方式
………………
………………
………………
rat.translate(-50,-50);
svgCanvas.setRenderingTransform(rat);</FONT>

      </CODE></PRE></TD></TR></TBODY></TABLE>
<P><A name=resources><SPAN class=atitle2>参考资料 </SPAN></A>
<UL>
<LI>有关 SVG 的背景知识，请阅读 developerWorks 上的教程，" <A href="http://www-900.ibm.com/developerworks/cn/cnedu.nsf/xml-onlinecourse-bytitle/409E5759CF4CDA8E48256BBF0035382A?OpenDocument" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">可伸缩向量图形介绍</A>" <BR><BR>
<LI><A href="http://www.w3.org/TR/2001/REC-SVG-20010904/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Scalable Vector Graphics (SVG) 1.0 Specification </A><BR><BR>
<LI>Batik项目介绍 <A href="http://xml.apache.org/batik/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">http://xml.apache.org/batik/</A> <BR></LI></UL>
<P></P></FONT><img src ="http://www.blogjava.net/Pudgy/aggbug/10572.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Pudgy/" target="_blank">Pudgy's World</a> 2005-08-20 08:55 <a href="http://www.blogjava.net/Pudgy/archive/2005/08/20/10572.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>log4j Tutorials</title><link>http://www.blogjava.net/Pudgy/archive/2005/08/18/10449.html</link><dc:creator>Pudgy's World</dc:creator><author>Pudgy's World</author><pubDate>Thu, 18 Aug 2005 08:58:00 GMT</pubDate><guid>http://www.blogjava.net/Pudgy/archive/2005/08/18/10449.html</guid><wfw:comment>http://www.blogjava.net/Pudgy/comments/10449.html</wfw:comment><comments>http://www.blogjava.net/Pudgy/archive/2005/08/18/10449.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/Pudgy/comments/commentRss/10449.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Pudgy/services/trackbacks/10449.html</trackback:ping><description><![CDATA[<font size="2"><span style="font-family: verdana;" id="ArticleContent1_ArticleContent1_lblContent"><p class="toc" xmlns="http://www.w3.org/1999/xhtml"><b>目录</b></p>
<div class="toc" xmlns="http://www.w3.org/1999/xhtml">
<dl><dt>1. <a href="http://www.csdn.net/editor/data.asp?text=21291#LOG4J-Introduction">简介</a> 
</dt><dt>2. <a href="http://www.csdn.net/editor/data.asp?text=21291#LOG4J-Installation">安装</a> 
</dt><dt>3. <a href="http://www.csdn.net/editor/data.asp?text=21291#LOG4J-Basics">log4j基本概念</a> 
</dt><dd>
<dl><dt>3.1. <a href="http://www.csdn.net/editor/data.asp?text=21291#LOG4J-Basics-Logger">Logger</a> 
</dt><dt>3.2. <a href="http://www.csdn.net/editor/data.asp?text=21291#LOG4J-Basics-Appender">Appender</a> 
</dt><dd>
<dl><dt>3.2.1. <a href="http://www.csdn.net/editor/data.asp?text=21291#LOG4J-Basics-Appender-ConsoleAppender">使用ConsoleAppender</a> 
</dt><dt>3.2.2. <a href="http://www.csdn.net/editor/data.asp?text=21291#LOG4J-Basics-Appender-FileAppender">使用FileAppender</a> 
</dt><dt>3.2.3. <a href="http://www.csdn.net/editor/data.asp?text=21291#LOG4J-Basics-Appender-WriterAppender">使用WriterAppender</a></dt></dl>
</dd><dt>3.3. <a href="http://www.csdn.net/editor/data.asp?text=21291#LOG4J-Basics-Layout">Layout</a> 
</dt><dt>3.4. <a href="http://www.csdn.net/editor/data.asp?text=21291#LOG4J-Basics-Basics-Example">基本示例</a> 
</dt><dd>
<dl><dt>3.4.1. <a href="http://www.csdn.net/editor/data.asp?text=21291#LOG4J-Basics-Basics-Example-SimpAndFile">SimpleLayout和FileAppender</a> 
</dt><dt>3.4.2. <a href="http://www.csdn.net/editor/data.asp?text=21291#LOG4J-Basics-Basics-Example-HTMLandFile">HTMLLayout和WriterAppender</a> 
</dt><dt>3.4.3. <a href="http://www.csdn.net/editor/data.asp?text=21291#LOG4J-Basics-Basics-Example-consandpatt">PatternLayout和ConsoleAppender</a></dt></dl></dd></dl>
</dd><dt>4. <a href="http://www.csdn.net/editor/data.asp?text=21291#LOG4J-External-Config-File">使用外部配置文件</a> 
</dt><dt>5. <a href="http://supportweb.cs.bham.ac.uk/documentation/tutorials/docsystem/build/tutorials/log4j/log4j.html#LOG4J-References">参考资料 (以及一些有参考价值的链接)</a></dt></dl></div>
<div class="sect1" xmlns="http://www.w3.org/1999/xhtml">
<div class="titlepage" xmlns="http://www.w3.org/1999/xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
<h2 class="title" style="clear: both;" xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-Introduction" xmlns="http://www.w3.org/1999/xhtml">1.简介</a></h2></div></div>
<p xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-Introduction" xmlns="http://www.w3.org/1999/xhtml">程
序开发环境中的日志记录是由嵌入在程序中以输出一些对开发人员有用信息的语句所组成。例如，跟踪语句（trace），结构转储和常见的
System.out.println或printf调试语句。log4j提供分级方法在程序中嵌入日志记录语句。日志信息具有多种输出格式和多个输出级
别。 </a></p>
<p xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-Introduction" xmlns="http://www.w3.org/1999/xhtml">使
用一个专门的日志记录包，可以减轻对成千上万的System.out.println语句的维护成本，因为日志记录可以通过配置脚本在运行时得以控制。
log4j维护嵌入在程序代码中的日志记录语句。通过规范日志记录的处理过程，一些人认为应该鼓励更多的使用日志记录并且获得更高程度的效率。 </a></p></div>
<div class="sect1" xmlns="http://www.w3.org/1999/xhtml">
<div class="titlepage" xmlns="http://www.w3.org/1999/xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
<h2 class="title" style="clear: both;" xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-Installation" xmlns="http://www.w3.org/1999/xhtml">2.安装</a></h2></div></div>
<p xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-Installation" xmlns="http://www.w3.org/1999/xhtml">为了使用我们即将要安装的日志记录工具，还必须要设置操作环境，只有这样，工具才能知道从哪里找到它所需要的信息，并且操作系统知道从哪里找到这个工具。那么，怎样做呢？实际上，它要求更改操作环境。我有一些这方面的资格文档。 </a><a href="http://supportweb.cs.bham.ac.uk/documentation/tutorials/docsystem/build/tutorials/winenvars/winenvarshome.html" target="_top"><i>Configuring A Windows Working Environment</i></a> 和 <a href="http://supportweb.cs.bham.ac.uk/documentation/tutorials/docsystem/build/tutorials/unixenvars/unixenvarshome.html" target="_top"><i>Configuring A Unix Working Environment</i></a>. </p>
<div class="orderedlist" xmlns="http://www.w3.org/1999/xhtml">
<ol type="1"><li xmlns="http://www.w3.org/1999/xhtml">
<p xmlns="http://www.w3.org/1999/xhtml">从 <a href="http://jakarta.apache.org/log4j/docs/download.html" target="_top">http://jakarta.apache.org/log4j/docs/download.html</a>下载log4j发行版。 </p>
</li><li xmlns="http://www.w3.org/1999/xhtml">
<p xmlns="http://www.w3.org/1999/xhtml">解压存档文件到合适的目录中。</p>
</li><li xmlns="http://www.w3.org/1999/xhtml">
<p xmlns="http://www.w3.org/1999/xhtml">添加文件 dist/lib/log4j-1.2.6.jar 到 CLASSPATH 环境变量中。 </p></li></ol></div></div>
<div class="sect1" xmlns="http://www.w3.org/1999/xhtml">
<div class="titlepage" xmlns="http://www.w3.org/1999/xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
<h2 class="title" style="clear: both;" xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-Basics" xmlns="http://www.w3.org/1999/xhtml">3.log4j的基本概念 </a></h2></div></div>
<p xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-Basics" xmlns="http://www.w3.org/1999/xhtml">使用log4j大概涉及3个主要概念:</a></p>
<div class="orderedlist" xmlns="http://www.w3.org/1999/xhtml">
<ol type="1"><li xmlns="http://www.w3.org/1999/xhtml">
<p xmlns="http://www.w3.org/1999/xhtml"><span class="strong"><a id="LOG4J-Basics" xmlns="http://www.w3.org/1999/xhtml">公共类 Logger</a></span></p>
<p xmlns="http://www.w3.org/1999/xhtml"><span class="strong"><a id="LOG4J-Basics" xmlns="http://www.w3.org/1999/xhtml">Logger</a></span><a id="LOG4J-Basics" xmlns="http://www.w3.org/1999/xhtml"> 负责处理日志记录的大部分操作。 </a></p>
</li><li xmlns="http://www.w3.org/1999/xhtml">
<p xmlns="http://www.w3.org/1999/xhtml"><span class="strong"><a id="LOG4J-Basics" xmlns="http://www.w3.org/1999/xhtml">公共接口 Appender</a></span></p>
<p xmlns="http://www.w3.org/1999/xhtml"><span class="emphasis"><a id="LOG4J-Basics" xmlns="http://www.w3.org/1999/xhtml"><em>Appender</em></a></span><a id="LOG4J-Basics" xmlns="http://www.w3.org/1999/xhtml"> 负责控制日志记录操作的输出。 </a></p>
</li><li xmlns="http://www.w3.org/1999/xhtml">
<p xmlns="http://www.w3.org/1999/xhtml"><span class="strong"><a id="LOG4J-Basics" xmlns="http://www.w3.org/1999/xhtml">公共抽象类Layout</a></span></p>
<p xmlns="http://www.w3.org/1999/xhtml"><span class="strong"><a id="LOG4J-Basics" xmlns="http://www.w3.org/1999/xhtml">Layout</a></span><a id="LOG4J-Basics" xmlns="http://www.w3.org/1999/xhtml"> 负责格式化<span class="strong">Appender</span>的输出。 </a></p></li></ol></div>
<div class="sect2" xmlns="http://www.w3.org/1999/xhtml">
<div class="titlepage" xmlns="http://www.w3.org/1999/xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
<h3 class="title" xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-Basics-Logger" xmlns="http://www.w3.org/1999/xhtml">3.1.Logger</a></h3></div></div>
<p xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-Basics-Logger" xmlns="http://www.w3.org/1999/xhtml">日志记录器(Logger)是日志处理的核心组件。log4j具有5种正常级别(Level)。 日志记录器(Logger)的可用级别<span class="strong">Level</span> (不包括自定义级别 <span class="strong">Level</span>)， 以下内容就是摘自log4j API (</a><a href="http://jakarta.apache.org/log4j/docs/api/index.html" target="_top">http://jakarta.apache.org/log4j/docs/api/index.html</a>): </p>
<div class="itemizedlist" xmlns="http://www.w3.org/1999/xhtml">
<ul type="disc"><li xmlns="http://www.w3.org/1999/xhtml">
<p xmlns="http://www.w3.org/1999/xhtml"><span class="strong">static Level DEBUG</span> </p>
<p xmlns="http://www.w3.org/1999/xhtml">DEBUG Level指出细粒度信息事件对调试应用程序是非常有帮助的。</p>
</li><li xmlns="http://www.w3.org/1999/xhtml">
<p xmlns="http://www.w3.org/1999/xhtml"><span class="strong">static Level INFO</span> </p>
<p xmlns="http://www.w3.org/1999/xhtml">INFO level表明 消息在粗粒度级别上突出强调应用程序的运行过程。 </p>
</li><li xmlns="http://www.w3.org/1999/xhtml">
<p xmlns="http://www.w3.org/1999/xhtml"><span class="strong">static Level WARN</span></p>
<p xmlns="http://www.w3.org/1999/xhtml">WARN level表明会出现潜在错误的情形。</p>
</li><li xmlns="http://www.w3.org/1999/xhtml">
<p xmlns="http://www.w3.org/1999/xhtml"><span class="strong">static Level ERROR</span></p>
<p xmlns="http://www.w3.org/1999/xhtml">ERROR level指出虽然发生错误事件，但仍然不影响系统的继续运行。</p>
</li><li xmlns="http://www.w3.org/1999/xhtml">
<p xmlns="http://www.w3.org/1999/xhtml"><span class="strong">static Level FATAL</span></p>
<p xmlns="http://www.w3.org/1999/xhtml">FATAL level指出每个严重的错误事件将会导致应用程序的退出。</p></li></ul></div>
<p xmlns="http://www.w3.org/1999/xhtml">另外，还有两个可用的特别的日志记录级别: (以下描述来自log4j API <a href="http://jakarta.apache.org/log4j/docs/api/index.html" target="_top">http://jakarta.apache.org/log4j/docs/api/index.html</a>): </p>
<div class="itemizedlist" xmlns="http://www.w3.org/1999/xhtml">
<ul type="disc"><li xmlns="http://www.w3.org/1999/xhtml">
<p xmlns="http://www.w3.org/1999/xhtml"><span class="strong">static Level ALL</span></p>
<p xmlns="http://www.w3.org/1999/xhtml">ALL Level是最低等级的，用于打开所有日志记录。 </p>
</li><li xmlns="http://www.w3.org/1999/xhtml">
<p xmlns="http://www.w3.org/1999/xhtml"><span class="strong">static Level OFF</span></p>
<p xmlns="http://www.w3.org/1999/xhtml">OFF Level是最高等级的，用于关闭所有日志记录。 </p></li></ul></div>
<p xmlns="http://www.w3.org/1999/xhtml">日志记录器（Logger）的行为是分等级的。如下表所示：</p>
<div class="figure" xmlns="http://www.w3.org/1999/xhtml"><a id="id215962" xmlns="http://www.w3.org/1999/xhtml">
</a><p class="title" xmlns="http://www.w3.org/1999/xhtml"><a id="id215962" xmlns="http://www.w3.org/1999/xhtml"><b>图.日志输出等级</b></a></p>
<div class="mediaobject" xmlns="http://www.w3.org/1999/xhtml"><a id="id215962" xmlns="http://www.w3.org/1999/xhtml"><img alt="Logger Output Hierarchy" src="g:%5Cmydoc%5Cresearch%5CLog4J.files%5Cloggerlevels.png" border="0" hspace="0"></a></div></div>
<p xmlns="http://www.w3.org/1999/xhtml"><a id="id215962" xmlns="http://www.w3.org/1999/xhtml">日志记录器（Logger）将只输出那些级别高于或等于它的级别的信息。如果没有设置日志记录器（Logger）的级别，那么它将会继承最近的祖先的级别。因此，如果在包<span class="strong">com.foo.bar</span>中创建一个日志记录器（Logger）并且没有设置级别，那它将会继承在包<span class="strong">com.foo</span>中创建的日志记录器（Logger）的级别。如果在<span class="strong">com.foo</span>中没有创建日志记录器（Logger）的话,那么在<span class="strong">com.foo.bar</span>中创建的日志记录器（Logger）将继承<span class="strong">root</span> 日志记录器（Logger）的级别，root日志记录器（Logger）经常被实例化而可用，它的级别为<span class="strong">DEBUG</span>。 </a></p>
<p xmlns="http://www.w3.org/1999/xhtml"><a id="id215962" xmlns="http://www.w3.org/1999/xhtml">有很多方法可以创建一个日志记录器（Logger），下面方法可以取回root日志记录器:</a></p>
<table bgcolor="#e0e0e0" border="0" width="90%">
<tbody>
<tr>
<td><pre class="programlisting">Logger logger = Logger.getRootLogger();</pre></td></tr></tbody></table>
<p xmlns="http://www.w3.org/1999/xhtml"><a id="id215962" xmlns="http://www.w3.org/1999/xhtml">还可以这样创建一个新的日志记录器:</a></p>
<table bgcolor="#e0e0e0" border="0" width="90%">
<tbody>
<tr>
<td><pre class="programlisting">Logger logger = Logger.getLogger("MyLogger");</pre></td></tr></tbody></table>
<p xmlns="http://www.w3.org/1999/xhtml"><a id="id215962" xmlns="http://www.w3.org/1999/xhtml">比较常用的用法，就是根据类名实例化一个静态的全局日志记录器:</a></p>
<table bgcolor="#e0e0e0" border="0" width="90%">
<tbody>
<tr>
<td><pre class="programlisting">static Logger logger = Logger.getLogger(test.class);</pre></td></tr></tbody></table>
<p xmlns="http://www.w3.org/1999/xhtml"><a id="id215962" xmlns="http://www.w3.org/1999/xhtml">所有这些创建的叫"logger"的日志记录器都可以用下面方法设置级别:</a></p>
<table bgcolor="#e0e0e0" border="0" width="90%">
<tbody>
<tr>
<td><pre class="programlisting">logger.setLevel((Level)Level.WARN);</pre></td></tr></tbody></table>
<p xmlns="http://www.w3.org/1999/xhtml"><a id="id215962" xmlns="http://www.w3.org/1999/xhtml">可以使用7个级别中的任何一个; Level.DEBUG, Level.INFO, Level.WARN, Level.ERROR, Level.FATAL, Level.ALL and Level.OFF. </a></p></div>
<div class="sect2" xmlns="http://www.w3.org/1999/xhtml">
<div class="titlepage" xmlns="http://www.w3.org/1999/xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
<h3 class="title" xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-Basics-Appender" xmlns="http://www.w3.org/1999/xhtml">3.2.Appender</a></h3></div></div>
<p xmlns="http://www.w3.org/1999/xhtml"><span class="strong"><a id="LOG4J-Basics-Appender" xmlns="http://www.w3.org/1999/xhtml">Appender</a></span><a id="LOG4J-Basics-Appender" xmlns="http://www.w3.org/1999/xhtml"> 控制日志怎样输出。下面列出一些可用的Appender(log4j API中所描述的 </a><a href="http://jakarta.apache.org/log4j/docs/api/index.html" target="_top">http://jakarta.apache.org/log4j/docs/api/index.html</a>): </p>
<div class="orderedlist" xmlns="http://www.w3.org/1999/xhtml">
<ol type="1"><li xmlns="http://www.w3.org/1999/xhtml">
<p xmlns="http://www.w3.org/1999/xhtml"><span class="strong">ConsoleAppender:</span>使用用户指定的布局(layout) 输出日志事件到System.out或者 System.err。默认的目标是System.out。 </p>
</li><li xmlns="http://www.w3.org/1999/xhtml">
<p xmlns="http://www.w3.org/1999/xhtml"><span class="strong">DailyRollingFileAppender</span> 扩展FileAppender，因此多个日志文件可以以一个用户选定的频率进行循环日志记录。 </p>
</li><li xmlns="http://www.w3.org/1999/xhtml">
<p xmlns="http://www.w3.org/1999/xhtml"><span class="strong">FileAppender</span> 把日志事件写入一个文件 </p>
</li><li xmlns="http://www.w3.org/1999/xhtml">
<p xmlns="http://www.w3.org/1999/xhtml"><span class="strong">RollingFileAppender</span> 扩展FileAppender备份容量达到一定大小的日志文件。</p>
</li><li xmlns="http://www.w3.org/1999/xhtml">
<p xmlns="http://www.w3.org/1999/xhtml"><span class="strong">WriterAppender</span>根据用户的选择把日志事件写入到Writer或者OutputStream。 </p>
</li><li xmlns="http://www.w3.org/1999/xhtml">
<p xmlns="http://www.w3.org/1999/xhtml"><span class="strong">SMTPAppender</span> 当特定的日志事件发生时，一般是指发生错误或者重大错误时，发送一封邮件。 </p>
</li><li xmlns="http://www.w3.org/1999/xhtml">
<p xmlns="http://www.w3.org/1999/xhtml"><span class="strong">SocketAppender</span> 给远程日志服务器（通常是网络套接字节点）发送日志事件（LoggingEvent）对象。</p>
</li><li xmlns="http://www.w3.org/1999/xhtml">
<p xmlns="http://www.w3.org/1999/xhtml"><span class="strong">SocketHubAppender</span> 给远程日志服务器群组（通常是网络套接字节点）发送日志事件（LoggingEvent）对象。</p>
</li><li xmlns="http://www.w3.org/1999/xhtml">
<p xmlns="http://www.w3.org/1999/xhtml"><span class="strong">SyslogAppender</span>给远程异步日志记录的后台精灵程序(daemon)发送消息。 </p>
</li><li xmlns="http://www.w3.org/1999/xhtml">
<p xmlns="http://www.w3.org/1999/xhtml"><span class="strong">TelnetAppender</span> 一个专用于向只读网络套接字发送消息的log4j appender。 </p></li></ol></div>
<p xmlns="http://www.w3.org/1999/xhtml">还可以实现 <span class="emphasis"><em>Appender</em></span> 接口，创建以自己的方式进行日志输出的Appender。 </p>
<div class="sect3" xmlns="http://www.w3.org/1999/xhtml">
<div class="titlepage" xmlns="http://www.w3.org/1999/xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
<h4 class="title" xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-Basics-Appender-ConsoleAppender" xmlns="http://www.w3.org/1999/xhtml">3.2.1.使用ConsoleAppender</a></h4></div></div>
<p xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-Basics-Appender-ConsoleAppender" xmlns="http://www.w3.org/1999/xhtml">ConsoleAppender可以用这种方式创建：</a></p>
<table bgcolor="#e0e0e0" border="0" width="90%">
<tbody>
<tr>
<td><pre class="programlisting">ConsoleAppender appender = new ConsoleAppender(new PatternLayout());</pre></td></tr></tbody></table>
<p xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-Basics-Appender-ConsoleAppender" xmlns="http://www.w3.org/1999/xhtml">创建了一个控制台appender，具有一个默认的PatternLayout。它使用了默认的<span class="strong">System.out</span> 输出。 </a></p></div>
<div class="sect3" xmlns="http://www.w3.org/1999/xhtml">
<div class="titlepage" xmlns="http://www.w3.org/1999/xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
<h4 class="title" xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-Basics-Appender-FileAppender" xmlns="http://www.w3.org/1999/xhtml">3.2.2.使用FileAppender</a></h4></div></div>
<p xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-Basics-Appender-FileAppender" xmlns="http://www.w3.org/1999/xhtml">FileAppender可以用这种方式创建:</a></p>
<table bgcolor="#e0e0e0" border="0" width="90%">
<tbody>
<tr>
<td><pre class="programlisting">          FileAppender appender = null;<br>          try {<br>             appender = new FileAppender(new PatternLayout(),"filename");<br>          } catch(Exception e) {}<br>        </pre></td></tr></tbody></table>
<p xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-Basics-Appender-FileAppender" xmlns="http://www.w3.org/1999/xhtml">上面用到的构造函数:</a></p>
<table bgcolor="#e0e0e0" border="0" width="90%">
<tbody>
<tr>
<td><pre class="programlisting">FileAppender(Layout layout, String filename) <br>          实例化一个FileAppender并且打开变量"filename"指定的文件。<br>        </pre></td></tr></tbody></table>
<p xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-Basics-Appender-FileAppender" xmlns="http://www.w3.org/1999/xhtml">另一个有用的构造函数是：</a></p>
<table bgcolor="#e0e0e0" border="0" width="90%">
<tbody>
<tr>
<td><pre class="programlisting">FileAppender(Layout layout, String filename, boolean append) <br>          实例化一个FileAppender并且打开变量"filename"指定的文件。<br>        </pre></td></tr></tbody></table>
<p xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-Basics-Appender-FileAppender" xmlns="http://www.w3.org/1999/xhtml">这个构造函数还可以选择是否对指定的文件进行追加的方式输出。如果没有指定值，那么默认的方式就是追加。 </a></p></div>
<div class="sect3" xmlns="http://www.w3.org/1999/xhtml">
<div class="titlepage" xmlns="http://www.w3.org/1999/xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
<h4 class="title" xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-Basics-Appender-WriterAppender" xmlns="http://www.w3.org/1999/xhtml">3.2.3.使用WriterAppender</a></h4></div></div>
<p xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-Basics-Appender-WriterAppender" xmlns="http://www.w3.org/1999/xhtml">WriterAppender可以用这种方式创建:</a></p>
<table bgcolor="#e0e0e0" border="0" width="90%">
<tbody>
<tr>
<td><pre class="programlisting">          WriterAppender appender = null;<br>          try {<br>            appender = new WriterAppender(new PatternLayout(),new FileOutputStream("filename"));<br>          } catch(Exception e) {}<br>        </pre></td></tr></tbody></table>
<p xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-Basics-Appender-WriterAppender" xmlns="http://www.w3.org/1999/xhtml">这个WriterAppender使用的构造函数带有PatternLayout和OutputStream参数，在这种情况下， FileOutputStream用于向一个文件输出。当然，它还具有其他可用的构造函数。 </a></p></div></div>
<div class="sect2" xmlns="http://www.w3.org/1999/xhtml">
<div class="titlepage" xmlns="http://www.w3.org/1999/xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
<h3 class="title" xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-Basics-Layout" xmlns="http://www.w3.org/1999/xhtml">3.3.Layout</a></h3></div></div>
<p xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-Basics-Layout" xmlns="http://www.w3.org/1999/xhtml">Appender必须使用一个与之相关联的 <span class="strong">Layout</span>，这样它才能知道怎样格式化它的输出。当前，log4j具有三种类型的Layout: </a></p>
<div class="orderedlist" xmlns="http://www.w3.org/1999/xhtml">
<ol type="1"><li xmlns="http://www.w3.org/1999/xhtml">
<p xmlns="http://www.w3.org/1999/xhtml"><span class="strong"><a id="LOG4J-Basics-Layout" xmlns="http://www.w3.org/1999/xhtml">HTMLLayout</a></span><a id="LOG4J-Basics-Layout" xmlns="http://www.w3.org/1999/xhtml"> 格式化日志输出为HTML表格。 </a></p>
</li><li xmlns="http://www.w3.org/1999/xhtml">
<p xmlns="http://www.w3.org/1999/xhtml"><span class="strong"><a id="LOG4J-Basics-Layout" xmlns="http://www.w3.org/1999/xhtml">PatternLayout</a></span><a id="LOG4J-Basics-Layout" xmlns="http://www.w3.org/1999/xhtml"> 根据指定的 <span class="emphasis"><em>转换模式</em></span>格式化日志输出，或者如果没有指定任何转换模式，就使用默认的转换模式。 </a></p>
</li><li xmlns="http://www.w3.org/1999/xhtml">
<p xmlns="http://www.w3.org/1999/xhtml"><span class="strong"><a id="LOG4J-Basics-Layout" xmlns="http://www.w3.org/1999/xhtml">SimpleLayout</a></span><a id="LOG4J-Basics-Layout" xmlns="http://www.w3.org/1999/xhtml"> 以一种非常简单的方式格式化日志输出，它打印级别 <span class="strong">Level</span>，然后跟着一个破折号“-“ ，最后才是日志消息。 </a></p></li></ol></div></div>
<div class="sect2" xmlns="http://www.w3.org/1999/xhtml">
<div class="titlepage" xmlns="http://www.w3.org/1999/xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
<h3 class="title" xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-Basics-Basics-Example" xmlns="http://www.w3.org/1999/xhtml">3.4.基本示例</a></h3></div></div>
<div class="sect3" xmlns="http://www.w3.org/1999/xhtml">
<div class="titlepage" xmlns="http://www.w3.org/1999/xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
<h4 class="title" xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-Basics-Basics-Example-SimpAndFile" xmlns="http://www.w3.org/1999/xhtml">3.4.1.SimpleLayout和 FileAppender</a></h4></div></div>
<p xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-Basics-Basics-Example-SimpAndFile" xmlns="http://www.w3.org/1999/xhtml">这里是一个非常简单的例子，程序实现了SimpleLayout和FileAppender:</a></p>
<table bgcolor="#e0e0e0" border="0" width="90%">
<tbody>
<tr>
<td><pre class="programlisting">import org.apache.log4j.Level;<br>import org.apache.log4j.Logger;<br>import org.apache.log4j.SimpleLayout;<br>import org.apache.log4j.FileAppender;<br>public class simpandfile {<br>   static Logger logger = Logger.getLogger(simpandfile.class);<br>   public static void main(String args[]) {<br>      SimpleLayout layout = new SimpleLayout();<br>      FileAppender appender = null;<br>      try {<br>         appender = new FileAppender(layout,"output1.txt",false);<br>      } catch(Exception e) {}<br>      logger.addAppender(appender);<br>      logger.setLevel((Level) Level.DEBUG);<br>      logger.debug("Here is some DEBUG");<br>      logger.info("Here is some INFO");<br>      logger.warn("Here is some WARN");<br>      logger.error("Here is some ERROR");<br>      logger.fatal("Here is some FATAL");<br>   }<br>}<br>        </pre></td></tr></tbody></table>
<p xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-Basics-Basics-Example-SimpAndFile" xmlns="http://www.w3.org/1999/xhtml">你可以下载: </a><a href="http://supportweb.cs.bham.ac.uk/documentation/tutorials/docsystem/build/tutorials/log4j/files/simpandfile.java" target="_top">simpandfile.java</a>。 还可以查看它的输出： <a href="http://supportweb.cs.bham.ac.uk/documentation/tutorials/docsystem/build/tutorials/log4j/files/output1.txt" target="_top">output1.txt</a>. </p></div>
<div class="sect3" xmlns="http://www.w3.org/1999/xhtml">
<div class="titlepage" xmlns="http://www.w3.org/1999/xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
<h4 class="title" xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-Basics-Basics-Example-HTMLandFile" xmlns="http://www.w3.org/1999/xhtml">3.4.2.HTMLLayout和 WriterAppender</a></h4></div></div>
<p xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-Basics-Basics-Example-HTMLandFile" xmlns="http://www.w3.org/1999/xhtml">这里是一个非常简单的例子，程序实现了 HTMLLayout和WriterAppender:</a></p>
<table bgcolor="#e0e0e0" border="0" width="90%">
<tbody>
<tr>
<td><pre class="programlisting">import java.io.*;<br>import org.apache.log4j.Level;<br>import org.apache.log4j.Logger;<br>import org.apache.log4j.HTMLLayout;<br>import org.apache.log4j.WriterAppender;<br>public class htmlandwrite {<br>   static Logger logger = Logger.getLogger(htmlandwrite.class);<br>   public static void main(String args[]) {<br>      HTMLLayout layout = new HTMLLayout();<br>      WriterAppender appender = null;<br>      try {<br>         FileOutputStream output = new FileOutputStream("output2.html");<br>         appender = new WriterAppender(layout,output);<br>      } catch(Exception e) {}<br>      logger.addAppender(appender);<br>      logger.setLevel((Level) Level.DEBUG);<br>      logger.debug("Here is some DEBUG");<br>      logger.info("Here is some INFO");<br>      logger.warn("Here is some WARN");<br>      logger.error("Here is some ERROR");<br>      logger.fatal("Here is some FATAL");<br>   }<br>}<br>        </pre></td></tr></tbody></table>
<p xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-Basics-Basics-Example-HTMLandFile" xmlns="http://www.w3.org/1999/xhtml">你可以下载: </a><a href="http://supportweb.cs.bham.ac.uk/documentation/tutorials/docsystem/build/tutorials/log4j/files/htmlandwrite.java" target="_top">simpandfile.java</a>. 还可以查看它的输出：<a href="http://supportweb.cs.bham.ac.uk/documentation/tutorials/docsystem/build/tutorials/log4j/files/output2.html" target="_top">output1.txt</a>. </p></div>
<div class="sect3" xmlns="http://www.w3.org/1999/xhtml">
<div class="titlepage" xmlns="http://www.w3.org/1999/xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
<h4 class="title" xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-Basics-Basics-Example-consandpatt" xmlns="http://www.w3.org/1999/xhtml">3.4.3.PatternLayout和 ConsoleAppender</a></h4></div></div>
<p xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-Basics-Basics-Example-consandpatt" xmlns="http://www.w3.org/1999/xhtml">这里是一个非常简单的例子，程序实现了PatternLayout和ConsoleAppender:</a></p>
<table bgcolor="#e0e0e0" border="0" width="90%">
<tbody>
<tr>
<td><pre class="programlisting">import org.apache.log4j.Level;<br>import org.apache.log4j.Logger;<br>import org.apache.log4j.PatternLayout;<br>import org.apache.log4j.ConsoleAppender;<br>public class consandpatt {<br>   static Logger logger = Logger.getLogger(consandpatt.class);<br>   public static void main(String args[]) {<br>      // Note, %n is newline<br>      String pattern =  "Milliseconds since program start: %r %n";<br>             pattern += "Classname of caller: %C %n";<br>             pattern += "Date in ISO8601 format: %d{ISO8601} %n";<br>             pattern += "Location of log event: %l %n";<br>             pattern += "Message: %m %n %n"; <br>      <br>      PatternLayout layout = new PatternLayout(pattern);<br>      ConsoleAppender appender = new ConsoleAppender(layout);<br>      logger.addAppender(appender);<br>      logger.setLevel((Level) Level.DEBUG);<br>      logger.debug("Here is some DEBUG");<br>      logger.info("Here is some INFO");<br>      logger.warn("Here is some WARN");<br>      logger.error("Here is some ERROR");<br>      logger.fatal("Here is some FATAL");<br>   }<br>}<br>        </pre></td></tr></tbody></table>
<p xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-Basics-Basics-Example-consandpatt" xmlns="http://www.w3.org/1999/xhtml">你可以下载:</a><a href="http://supportweb.cs.bham.ac.uk/documentation/tutorials/docsystem/build/tutorials/log4j/files/consandpatt.java" target="_top">simpandfile.java</a>. 还可以查看它的输出： <a href="http://supportweb.cs.bham.ac.uk/documentation/tutorials/docsystem/build/tutorials/log4j/files/output2.txt" target="_top">output2.txt</a>. </p></div></div></div>
<div class="sect1" xmlns="http://www.w3.org/1999/xhtml">
<div class="titlepage" xmlns="http://www.w3.org/1999/xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
<h2 class="title" style="clear: both;" xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-External-Config-File" xmlns="http://www.w3.org/1999/xhtml">4.使用外部配置文件</a></h2></div></div>
<p xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-External-Config-File" xmlns="http://www.w3.org/1999/xhtml">Log4j经常与外部日志文件联合使用，这样很多可选项不必硬编码在软件中。使用外部配置文件的优点就是修改可选项不需要重新编译程序。唯一的缺点就是，由于用到<span class="emphasis"><em>io</em></span> 指令，速度稍微有些减慢。 </a></p>
<p xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-External-Config-File" xmlns="http://www.w3.org/1999/xhtml">有两个方法可以用来指定外部配置文件：文本文件或者XML文件。既然现在所有事情都写成XML文件，那么该教程就重点讲解XML文件方法，但是也包含相关文本文件的例子。首先，看看下面的XML配置文件示例：</a></p>
<table bgcolor="#e0e0e0" border="0" width="90%">
<tbody>
<tr>
<td><pre class="programlisting">&lt;?xml version="1.0" encoding="UTF-8" ?&gt;<br>&lt;!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"&gt;<br>&lt;log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"&gt;<br>        <br>  &lt;appender name="ConsoleAppender" class="org.apache.log4j.ConsoleAppender"&gt;<br>    &lt;layout class="org.apache.log4j.SimpleLayout"/&gt;<br>  &lt;/appender&gt;<br>  &lt;root&gt;<br>    &lt;priority value ="debug" /&gt;<br>    &lt;appender-ref ref="ConsoleAppender"/&gt;<br>  &lt;/root&gt;<br>&lt;/log4j:configuration&gt; <br>    </pre></td></tr></tbody></table>
<p xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-External-Config-File" xmlns="http://www.w3.org/1999/xhtml">文件以标准的XML声明作为开始，后面跟着指出DTD（文档类型定义）的DOCTYPE声明，它定义了XML文件的结构，例如，什么元素可以嵌入在其他元素中等等。上面文件在log4j发行版的src/java/org/apache/log4j/xml目录中。 接着看看封装所有元素的 <span class="strong">log4j:configuration</span> 元素，它在DOCTYPE声明中被指定为根元素。嵌入在根元素中有两个结构： </a></p>
<table bgcolor="#e0e0e0" border="0" width="90%">
<tbody>
<tr>
<td><pre class="programlisting">  &lt;appender name="ConsoleAppender" class="org.apache.log4j.ConsoleAppender"&gt;<br>    &lt;layout class="org.apache.log4j.SimpleLayout"/&gt;<br>  &lt;/appender&gt;      <br>    </pre></td></tr></tbody></table>
<p xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-External-Config-File" xmlns="http://www.w3.org/1999/xhtml">这里创建一个名叫"ConsoleAppender"的 <span class="emphasis"><em>Appender</em></span>，注意，你可以选择任何名字，该示例之所以选择"ConsoleAppender"，完全是为了示例的设计。接着这个appender类以全名形式给出，经常用规范（fully qualified）类名。 <span class="emphasis"><em>Appender</em></span>必须具有一个指定的 <span class="emphasis"><em>name</em></span>和<span class="emphasis"><em>class</em></span>。嵌入在 <span class="emphasis"><em>Appender</em></span>之内的是 <span class="emphasis"><em>layout</em></span>元素，这里它被指定为SimpleLayout。 <span class="emphasis"><em>Layout</em></span> 必须具有一个 <span class="emphasis"><em>class</em></span>属性。 </a></p>
<table bgcolor="#e0e0e0" border="0" width="90%">
<tbody>
<tr>
<td><pre class="programlisting">  &lt;root&gt;<br>    &lt;priority value ="debug" /&gt;<br>    &lt;appender-ref ref="ConsoleAppender"/&gt;<br>  &lt;/root&gt;      <br>    </pre></td></tr></tbody></table>
<p xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-External-Config-File" xmlns="http://www.w3.org/1999/xhtml">root元素必须存在且不能被子类化。示例中的优先级被设置为"debug"，设置appender饱含一个<span class="emphasis"><em>appender-ref</em></span>元素。还有更多的属性或元素可以指定。查看log4j发行版中的src/java/org/apache/log4j/xml/log4j.dtd以了解关于XML配置文件结构的更多信息。可以用下面这种方法把配置信息文件读入到Java程序中: </a></p>
<table bgcolor="#e0e0e0" border="0" width="90%">
<tbody>
<tr>
<td><pre class="programlisting">DOMConfigurator.configure("configurationfile.xml");<br>    </pre></td></tr></tbody></table>
<p xmlns="http://www.w3.org/1999/xhtml"><span class="emphasis"><a id="LOG4J-External-Config-File" xmlns="http://www.w3.org/1999/xhtml"><em>DOMConfigurator</em></a></span><a id="LOG4J-External-Config-File" xmlns="http://www.w3.org/1999/xhtml"> 用一棵DOM树来初始化log4j环境。这里是示例中的XML配置文件：</a><a href="http://supportweb.cs.bham.ac.uk/documentation/tutorials/docsystem/build/tutorials/log4j/files/plainlog4jconfig.xml" target="_top">plainlog4jconfig.xml</a>。这里是执行该配置文件的程序: <a href="http://supportweb.cs.bham.ac.uk/documentation/tutorials/docsystem/build/tutorials/log4j/files/externalxmltest.java" target="_top">files/externalxmltest.java</a>: </p>
<table bgcolor="#e0e0e0" border="0" width="90%">
<tbody>
<tr>
<td><pre class="programlisting">import org.apache.log4j.Logger;<br>import org.apache.log4j.xml.DOMConfigurator;<br>public class externalxmltest {<br>   static Logger logger = Logger.getLogger(filetest.class);<br>   public static void main(String args[]) {<br>      DOMConfigurator.configure("xmllog4jconfig.xml");<br>      logger.debug("Here is some DEBUG");<br>      logger.info("Here is some INFO");<br>      logger.warn("Here is some WARN");<br>      logger.error("Here is some ERROR");<br>      logger.fatal("Here is some FATAL");<br>   }<br>}<br>    </pre></td></tr></tbody></table>
<p xmlns="http://www.w3.org/1999/xhtml">这里是一个实现带有<span class="emphasis"><em>PatternLayout</em></span>的<span class="emphasis"><em>FileAppender</em></span>的日志记录器Logger的XML配置文件: </p>
<table bgcolor="#e0e0e0" border="0" width="90%">
<tbody>
<tr>
<td><pre class="programlisting">&lt;?xml version="1.0" encoding="UTF-8" ?&gt;<br>&lt;!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"&gt;<br>&lt;log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"&gt;<br>        <br>  &lt;appender name="appender" class="org.apache.log4j.FileAppender"&gt;<br>    &lt;param name="File" value="Indentify-Log.txt"/&gt;<br>    &lt;param name="Append" value="false"/&gt;<br>    &lt;layout class="org.apache.log4j.PatternLayout"&gt;<br>      &lt;param name="ConversionPattern" value="%d [%t] %p - %m%n"/&gt;<br>    &lt;/layout&gt;<br>  &lt;/appender&gt;<br>  &lt;root&gt;<br>    &lt;priority value ="debug"/&gt;<br>    &lt;appender-ref ref="appender"/&gt;<br>  &lt;/root&gt;<br>&lt;/log4j:configuration&gt;<br>    </pre></td></tr></tbody></table>
<p xmlns="http://www.w3.org/1999/xhtml">你可以从这里下载示例: <a href="http://supportweb.cs.bham.ac.uk/documentation/tutorials/docsystem/build/tutorials/log4j/files/xmllog4jconfig2.xml" target="_top">xmllog4jconfig2.xml</a>。 想要得到更多的使用XML文件配置log4j环境的例子，请查看log4j发行版的目录src/java/org/apache/log4j/xml/examples/ 。 </p>
<p xmlns="http://www.w3.org/1999/xhtml">这就是上面讨论的文本文件形式的配置文件:</p>
<table bgcolor="#e0e0e0" border="0" width="90%">
<tbody>
<tr>
<td><pre class="programlisting"># initialise root logger with level DEBUG and call it BLAH<br>log4j.rootLogger=DEBUG, BLAH<br># add a ConsoleAppender to the logger BLAH<br>log4j.appender.BLAH=org.apache.log4j.ConsoleAppender<br># set set that layout to be SimpleLayout<br>log4j.appender.BLAH.layout=org.apache.log4j.SimpleLayout<br>    </pre></td></tr></tbody></table>
<p xmlns="http://www.w3.org/1999/xhtml">从这里可以下载: <a href="http://supportweb.cs.bham.ac.uk/documentation/tutorials/docsystem/build/tutorials/log4j/files/plainlog4jconfig.txt" target="_top">plainlog4jconfig.txt</a>。这就是执行该配置文件的程序: </p>
<table bgcolor="#e0e0e0" border="0" width="90%">
<tbody>
<tr>
<td><pre class="programlisting">import org.apache.log4j.Logger;<br>import org.apache.log4j.PropertyConfigurator;<br>public class externalplaintest {<br>   static Logger logger = Logger.getLogger(externalplaintest.class);<br>   public static void main(String args[]) {<br>      PropertyConfigurator.configure("plainlog4jconfig.xml");<br>      logger.debug("Here is some DEBUG");<br>      logger.info("Here is some INFO");<br>      logger.warn("Here is some WARN");<br>      logger.error("Here is some ERROR");<br>      logger.fatal("Here is some FATAL");<br>   }<br>}<br>    </pre></td></tr></tbody></table>
<p xmlns="http://www.w3.org/1999/xhtml">你可以下载使用该配置文件的示例： <a href="http://supportweb.cs.bham.ac.uk/documentation/tutorials/docsystem/build/tutorials/log4j/files/externalplaintest.java">externalplaintest.java</a>。想要获得更多的使用文本文件配置log4j环境的例子，请查看log4j发行版中的目录examples。 </p>
<p xmlns="http://www.w3.org/1999/xhtml">使用外部配置文件的例子就简单的讨论到这里，现在应该可以肯定你已经有能力独立学习更多的log4j发行版和测试版中提供的例子。</p></div>
<div class="sect1" xmlns="http://www.w3.org/1999/xhtml">
<div class="titlepage" xmlns="http://www.w3.org/1999/xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
<h2 class="title" style="clear: both;" xmlns="http://www.w3.org/1999/xhtml"><a id="LOG4J-References" xmlns="http://www.w3.org/1999/xhtml">5.参考资料 (以及一些有参考价值的链接)</a></h2></div></div>
<div class="itemizedlist" xmlns="http://www.w3.org/1999/xhtml">
<ul type="disc"><li xmlns="http://www.w3.org/1999/xhtml">
<p xmlns="http://www.w3.org/1999/xhtml"><a href="http://jakarta.apache.org/log4j/docs/manual.html" target="_top">http://jakarta.apache.org/log4j/docs/manual.html</a></p>
<p xmlns="http://www.w3.org/1999/xhtml">log4j的简明介绍 - Ceki G- 2002年3月</p>
</li><li xmlns="http://www.w3.org/1999/xhtml">
<p xmlns="http://www.w3.org/1999/xhtml"><a href="http://www.vipan.com/htdocs/log4jhelp.html" target="_top">http://www.vipan.com/htdocs/log4jhelp.html</a></p>
<p xmlns="http://www.w3.org/1999/xhtml">不要用System.out.println！用Log4j - Vipan Singla </p>
</li><li xmlns="http://www.w3.org/1999/xhtml">
<p xmlns="http://www.w3.org/1999/xhtml"><a href="http://www.opensymphony.com/guidelines/logging.jsp" target="_top">http://www.opensymphony.com/guidelines/logging.jsp</a></p>
<p xmlns="http://www.w3.org/1999/xhtml">LOG4J / OpenSymphony日志记录入门</p>
</li><li xmlns="http://www.w3.org/1999/xhtml">
<p xmlns="http://www.w3.org/1999/xhtml"><a href="http://builder.com.com/article.jhtml?id=u00820020124kev01.htm" target="_top">http://builder.com.com/article.jhtml?id=u00820020124kev01.htm</a></p>
<p xmlns="http://www.w3.org/1999/xhtml">给你的Java应用程序添加日志记录 - Kevin Brown</p></li></ul></div></div></span></font><img src ="http://www.blogjava.net/Pudgy/aggbug/10449.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Pudgy/" target="_blank">Pudgy's World</a> 2005-08-18 16:58 <a href="http://www.blogjava.net/Pudgy/archive/2005/08/18/10449.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>程序员心声 </title><link>http://www.blogjava.net/Pudgy/archive/2005/08/16/10219.html</link><dc:creator>Pudgy's World</dc:creator><author>Pudgy's World</author><pubDate>Tue, 16 Aug 2005 04:58:00 GMT</pubDate><guid>http://www.blogjava.net/Pudgy/archive/2005/08/16/10219.html</guid><wfw:comment>http://www.blogjava.net/Pudgy/comments/10219.html</wfw:comment><comments>http://www.blogjava.net/Pudgy/archive/2005/08/16/10219.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/Pudgy/comments/commentRss/10219.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Pudgy/services/trackbacks/10219.html</trackback:ping><description><![CDATA[<P>&nbsp;&nbsp;&nbsp; 这些日子我一直在写一个实时操作系统内核，已有小成了，等写完我会全部公开，希望能够为国内IT的发展尽自己一份微薄的力量。最近看到很多学生朋友和我当年一样没有方向 ，所以把我的经历写出来与大家共勉，希望能给刚如行的朋友们一点点帮助。 一转眼我在IT行业学习工作已经七年多了，这期间我做过网页，写过MIS、数据库，应用程序，做过通信软件、硬件驱动、协议栈，到现在做操作系统内核和IC相关开发，这中间走了很多弯路，也吃了不少苦。<BR>&nbsp;&nbsp;&nbsp; 我上的是一个三流的高校，就连同一个城市的人多数都不知道。因为学校不好也就没有指望能靠学校名气找一个好工作。所有的希望都寄托在自己的努力上了，大一开学前的假期我就开始了学习，记得我买的第一本书是《计算机基础DOS3.0》，大家别吓着了，其实当时已经普及了DOS6.22了，只是我在书店里看到了DOS4.0，5.0，6.0的书，以为像英语那样是第四、五、六册，记得当时到处找DOS1.0，现在 想想也幸好我没有找到：）开学前我学完了PASCAL，那时既没有计算机也没有人可以请教，我连程序是什么的概念都没有， 只好死记硬背代码，然后拿纸写，我一直到大三才有了一台486，在这之前用纸写了多少程序我也记不清楚了，只知道最长的一个我拿A4大小的草稿纸写了30多页，我的C语言、C++ 、VC都是在这样的条件下入门的。所以说条件是可以克服的，希望我的经历多少给条件艰苦的同学们一点信心。第一次上机是在我姐夫的机房，我的心情激动的无与伦比，但是一上机我立刻傻了眼，他们用的是英文版的Win3.1，我的那点DOS知识都见了鬼，上机提心吊胆的一阵瞎摸，一不小心把Word弄成了全屏，怎么都还不了原，当时真是心急如焚，我以为机器被我弄坏了。第一个C语言程序，就是那个经典的HelloWorld，我调了几个星期，上机机会非常少，也没有书告诉我开发环境（TC2.0）需要设置，而且开始我都不知道有编译器，我甚至自作聪明把写好的程序扩展名从.c改成.exe，结果可想而知。大一学完了C、X86的汇编、数据结构、C++。由于精力都花在自学上了，大一下四门课挂了彩，三类学校就是这点好，挂上一二十门也照样毕业。不过扯远点说，我那么刻苦都及不了格，可见我们国家的计算机教育有多死板。 <BR>　　大二准备学VC和BC，当时难以取舍，后来选了VC，不为别的，只为书店里两本书，VC 那本便宜6块钱。我的努力在班上无人能及，学的日夜不分，大三有了计算机后更是如此， 很多次父亲半夜教训我说我不要命了，我一直觉得自己基础差，记忆又不行，条件也不好 ，所以觉得只有多花点时间才能赶上别人。居然后来有许多朋友说我有学计算机的天赋， 让我哭笑不得。我用的是486，16M内存，1G硬盘，当时同学们的配置都是P166MMX，我安装 一个Windows NT4.0需要一个通宵，编译一个BC5.0向导生成的程序需要近两个小时，我的显示器是个二手的，辐射非常大，开机屏幕冒火花，看起来很酷的：），有一次程序写的太久，觉得怎么白色的编辑器背景变成了紫色，以为显示器坏了，后来才发现眼睛不行了，不过说来也奇怪，到今天我的视力还能保持1.5，真是个奇迹。但是就是那台破机器陪伴了我两年，让我学会了VC、Delphi、SQLServer等。后来那台机器给我阿姨打字用，据她说一天她正打的开心，一股青烟夹着火苗从显示器钻出来，之后它才寿终正寝。 <BR>　　大三假期找了个机会在一个计算机研究所实习，与其说实习不如说是做义工，工作了两个月一分钱没有拿。但是这两个月对我的发展帮助很大，让我早一步了解了社会，刚去的时候我当然是一窍不通，在那里我熟悉了网络，学会了Delphi和Oracle。由于工作很认真， 得到了比较好的评价，在一位长者的引荐下，我开始和他们一起做项目，这使我在大三大四就有了自己的收入，大四又找了两家MIS公司兼职，虽然钱不多，但是在学生期间有1000多的收入我已经非常满足了，我终于用自己赚的钱把计算机换了。大四下开始找工作，这时我的工作经验已经比较多（当然现在想想非常幼稚），开始听父母的想去那个研究所， 实习过那个部门也希望我能去，但是不知道为什么最后不了了之，这种单位就是比较官僚 ，我一气之下就到了我兼职的一个公司做MIS的TeamLeader。在大三到毕业一年的时间，做过了各种MIS，从煤气、烟厂、公安、铁路、饮食到高校，什么有钱做什么，工作也很辛苦 ，经常加班和熬通宵，从跟客户谈需求到设计、编码、测试、交付都要上。那时觉得很有成就感，觉得自己还不错，现在想想真是很肤浅。<BR>　　刚走上工作岗位的学生很容易被误导，各种开发工具让人眼花缭乱，同时也觉得很受公司器重，但这样工作永远是一个低层次的开发者。不要跟我说什么系统分析有多么多么重要，多么多么难。你以为自己跟用户谈需求做设计就是系统分析和设计了吗，国内又有几个公司能够做的很到位很规范？我是ISO9000内审员，也在Rational公司受过多次培训，拿了4个证书，还有一个公司让我去做CMM。这些我听过很多，但是很多事情到国内就变了性质，一个公司不是通过了ISO9000或者CMM就能规范了，我现在在一家有几十年历史的外企工作，里面的管理不是一般国内企业能及的。作为一个毕业不久以前没有步入过社会的学生，几乎不可能在很短的时间掌握系统分析和设计，面向对象、UML只是一个工具，关键是人本身的思想，不是说你熟悉了C++、Rose就能够做出好的设计，相反如果你具备了很高的素质，你可以用C写出比别人用C++更加模块化的程序。 <BR>　　话说远一些，国内软件开发行业有一个怪圈，很多人觉得VC &gt; Delphi &gt; VB，真是很搞笑。这几个软件我都做过开发，说白了他们都是工具，应该根据应用的需要选择采用哪个，而不是觉得哪个上层次。如果你因为用某个开发工具很有面子而选择的话，只能说明你很浅薄。如果说层次，那么这些工具都不上层次，因为它们用来用去都是一些系统的API，微软的朋友不会因为你记住他们多少个API或者多少个类就会觉得你很了不起，你永远只是他们的客户，他们看重的是你口袋里的银子。我也做过系统内核，我也封装过很多API，同样我也不会看重那些使用这些API做二次开发的客户，除非他能够作出自己独到的设计。 <BR>　　至于有人认为C++ &gt; C那更是让人笑掉大牙，不妨你去打听一下，现在有几个操作系统内核是用C++写的，又有几个实时系统用的是C++，当然我也不是说C++不好，但是目前的内核和实时系统中C++还无法与C匹敌，至于说C++适合做应用系统的开发那是另外一回事。所以我的观点是不在于你用什么工具和语言，而在于你干什么工作。你的设计体现了你的技术层次。<BR>　　这样干了一年我觉得非常苦闷，做的大多数都是熟练工种的活，个人技术上没有太多 的提高也看不到方向。所以决定离开这个城市去上海，寻求更好的发展，并且打算放弃我以前的MIS转到通信行业。 <BR>　　写到这里不能不提到我女朋友，我们是在来上海前半年认识的，她大四在我公司实习，公司派她给我写文档，我们的感情发展的很快。她告诉我很多事情，她家原本是改革开放的第一批暴发户，她母亲爱打牌，输掉了几百万，还欠了很多债，她有男朋友，但是她对他没有感情，只因为他给了她母亲两万多块钱，后来还强迫她写了四万块的借条，她男朋友背叛过她并且不止一次打她，现在逼她结婚不然就要她还钱。这人居然还是一个高校的老师！她母亲把父亲给她的学费花了，因为拖欠学费她没有办法拿到毕业证。她母亲现在有病需要钱，我拿出了自己的一点积蓄并且跟朋友们接了一些，替她交了学费并给她母亲看 病（后来才知道看病的钱又不知所终，就连她母亲是不是有病我都不知道，但她也是没有办法）。这个时候我家知道了一些事情，坚决反对我和她在一起，她原来的男朋友也极力破坏。无奈之下我们决定早一定离开这个伤心的城市，并且瞒着我们家。由于时间仓促，我只准备了4000块钱，她仅有的几百块钱也被她母亲要去了，我买了三张票，一张是中午的，两张是晚上的，中午我的家人把我送上船，他们一离开我就下了船，我和她乘坐晚上的船离开了这个我和她生活了很多年的城市，带走的只是一身债务。没有来过上海的我们两个性倔强，都不愿意去麻烦同学和朋友。来到上海是傍晚6点半，我们 都不知道该去哪里，我们找了一个20块钱的旅馆，这个房间连窗户都没有，7月份的天气酷热难耐，房间里非常闷热。第二天我们开始租房子，因为身上的钱不多，我们基本都是步行，花了一个星期时间，不知道在浦东转了多少圈后找到了一个400块的房子，但是我们都不了解上海是付三压一，还要付半个月的中介费，买了一些锅碗瓢盆后，我们身上只有800块钱了，工作都还没有着落，这800块钱要支持到我们拿到第一个月工资，为了省钱我们自己做饭，每天买菜只花两块钱，她非常喜欢吃（也可能她在大学经常挨饿的愿意），看到她现在这样省吃俭用我真的很不忍心。她以前的男朋友也没有放过她，经常打电话来骚扰，并且来上海看她，还说了不少恐吓她的话，她过于善良，说他以前毕竟帮助过她，叫我不要与他一般见识。以后的每天在家就是苦等面试通知，原本我想迅速找一家MIS公司解决眼前的困难，但是她坚持让我不要放弃自己的理想，终于功夫不负有心人，我找到了一家通信公司，4000块的工资虽然赶不上MIS公司给我开出的价位，但也够在上海生存。她也找到了工作，第一天上班她哭了，这是她来上海第一次流泪，我心里很难受也很感动。<BR>　　由于是全新的行业，我把自己降到了零点，我学的VC、Delphi、数据库派不上用场， 摆在我面前的是嵌入式、协议、信令一些我从未接触过的知识。我知道我没有退路，于是拼命的学习，我把自己当做一个应届毕业生一样，一分努力一分收获，半年过去我终于熟悉了工作，并且得到了公司的表彰，薪水也加了一级。后面的日子里我们省吃俭用，把欠朋友的1万多块钱还了，日子终于上了正轨。这时女朋友告诉我她想考研究生，我也很支持，于是她辞职在家备考。<BR>　　另外，在这里我要感谢我的ProjectManager，他原来是一个大通信公司的产品经理， 对人非常和善，我从他那里学到了很多知识，而且他也给了我许许多多无私的帮助。在工作上他给我充分的空间和信任。记得公司安排我维护一个接入服务器软件，由于代码量不算太小（5万行），资料和文档都不齐全，我维护起来非常吃力 ，所以想重新把它做一遍， 公司领导不太支持，可能觉得工作量太大，但是他极力支持我，私下里他让我放手去做， 我的维护工作他挤时间做。在他的支持下，我花了半年时间完成了接入服务器的软件，并且实现了一个相对完整的TCP/IP协议栈。在这里我学会了嵌入式系统设计、驱动开发、TCP/IP和很多通信的知识，我花了一年时间终于使自己从MIS开发转到了通信行业，并且站稳了脚跟。我的开发大量是对硬件的直接操作，不再受微软的操作系统，VC、Delhpi这些开发工具的约束，我终于看到了另外一片天空。 <BR>&nbsp;　我做事情喜欢追根问底，随着开发的深入，软件开发与硬件联系越来越紧密，硬件知识的匮乏又对我的发展产生了障碍，而且芯片技术基本上掌握在国外公司的手里，这对做系统级设计是一个非常大的制约，一个新产品出来，第一道利润（也往往是最丰厚的利润）常常都被IC公司如Intel、Motorola赚去了，国内的厂商只能喝点汤。所以我决心解决自己的硬件技术障碍，并打算离开通信行业，进入IC设计相关领域。 <BR>　　当然我明白如果我对硬件了解的非常少，没有哪家IC公司会仁慈到招我这样一个一窍不通的人来培训。所以我必须努力打好基础，学一些相关知识为以后做准备。就像我开始从MIS转到通信一样，我看过大量通信方面的书，并且给一个ISP做过RADIUS计费分拣台，在这样的背景下这家通信公司才给了我这个机会。我在的通信公司是做系统设计的，有不少PCB Layout硬件人员，平常我就注意向他们学习，由于我做的是软件，在公司看硬件资料不好意思，所以开始只好在家看，刚来上海工作我连续一年都在加班，后来不加了，因为我要挤出时间学习，通常我12点左右睡 ，第二天5点半起，我上班比较早，地铁上如果人不多我也用来看书。学习当然不会是一帆风顺的，有些实在不懂的问题就积累起来问硬件人员，他们的帮助使我学习进度快了很多，因为在没有人点拨的情况下自学，我的一半时间是花在解决疑难问题上，但这种问题经常是别人的一句话就可以让我豁然开朗，我非常庆幸我有这样的学习环境。在后面的一年里，我学会了看硬件原理图，学会了简单的硬件设计（模拟电路方面还有不小的差距），事情就是这样的，当你安安份份做软件，别人永远认为你是软件开发人员，在你开始学习硬件时别人未必会认同，有位中兴通讯的朋友还对我说过，一个人不可能把所有东西都学完。我也明白这一点，但我希望自 己做的更好。但当你熟悉硬件后大家又会觉得你好像原本就是软硬件都懂的，同事们也都习以为常了。这个时候我可以把硬件资料堂堂正正的拿到公司看，没有人再大惊小怪了。 让我比较自豪的是我通过自己的努力做了一个IAD（软交换的终端设备）系统方案，包含软硬件的选型、设计等内容，这个方案得到了公司和同事们的认同，让我感到非常欣慰。 <BR>　　技术是相辅相成的，当我的硬件有了一定的进步后，我的软件设计也有了很大的提高 ，我可以从更深层次理解问题，我做的接入服务器CPU是Motorola PowerPC860，熟悉的朋友都知道860 QMC与软件的批量数据传输通常采用BD表的方式，硬件人员做驱动的时候习惯采用固定BD表，每接收或发送数据都将数据从BD表拷贝到用户Buffer，或从用户Buffer拷贝到BD表，由于理解的比较深入，我自己重新实现了 这个过程，采用动态BD表的方式，驱动从一个网口接收数据，提交给我的软件进行三层交换，直至从另外的接口发送出去，没有进行一次拷贝。这样的设计大大提高了性能，使系统的指标接近理论值。软硬件的结合使我的设计水平上了一个台阶。我现在写的这个操作系统，编译后我把程序反编译成汇编，找出其中不优化的代码，然后在C程序中进行调整。举个例子，很多CPU没有专门的乘法指令，这个大家应该都知道，在这种CPU上进行一个乘法操作常常会花费大量的指令周期， 有的朋友会说这个我知道，我会尽量避免采用×号，但是事情往往不是那么简单，你知道C语言中数组的下标操作是怎么实现的吗？仔细看看反汇编的代码你就会明白，同样是通过下标的定位操作，C编译器会有时候会产生位移指令，但有时候会用乘法实现，两者效率往往是天壤之别，所以明白这些问题你才能将系统性能提升到极致。这些问题就不多说了，有兴趣的话以后可以共同探讨。<BR>　　话说远一点，我由衷的希望在软件上做的比较深入的朋友们有机会学学硬件以及其它相关知识，尤其是做底层开发和嵌入式设计的。这对软件技术的提高有非常大的帮助，否则很多事情你只知道该这样但不会明白为什么该这样。我这个观点在我现在的IC公司Project Manager那里也得到了验证。他告诉我们公司现在的802.11芯片产品的软件经理原本是做该芯片硬件设计的，某某某原本是做软件的，现在在做IC，类似的例子还有很多，只是在国内这样的风气不是非常流行。<BR>　　我有一些心得体会与大家分享，只有当我干好本职工作后，我才会学习与工作关系不大的技术，这样公司的上司才不至于反感，在入门阶段的问题我通常不去问那些资深人士 ，而是问一些资历比较浅的朋友，比如刚毕业不久的学生，因为他们往往会跟你详细的讲解，而资深人士通常觉得你的问题太简单，所以回答的也很简单，我又不好意思多问。等技术上了一定的层次后我才会问他们，他们也能给你比较深入的回答。另外，有些朋友说我机会比较好，他们也希望能从事新的工作可惜没有机会，我听了只有苦笑，我的机会了解的人都应该知道，我没有出生在什么IT世家：）也没有谁一路提拔我，所有的路都是自己走出来的，我母亲去世比较早，我的后母（我叫她阿姨）看着我努力过来的，一次她看我大年30还在写程序，她说像我这样努力木头都能学出来。 <BR>　　我的最终目的是IC而不是PCB，所以我下一步的准备开始学习IC设计的知识。公司的同事没有懂IC设计的，后面的路又要靠自己了，我买了不少相关的书，在网上也查了很多的资料，我花了大量的时间去学习VHDL，并且用软件进行了一些简单的设计和仿真（没有设计ASIC，只是针对FPGA），随着学习的深入，我渐渐明白了IC设计的基本流程，同时也明白了这条路的艰辛。这个时候我已经做好了跳槽的准备，我向一家业界又一定知名度的IC设计公司投了简历，并通过了漫长的面试（4个多小时）。其他的一切我都比较满意，唯独薪资差强人意，我也明白原因，因为我是这个行业的新人，我没有经验，我再一次将自己清零了。公司老板问我6000多一个月能不能接受，我知道他也是照章办事。想想我通信行业的朋友们，基本上都是年薪10万以上，月薪过万的也比比皆是，朋友们也帮我介绍了不少待遇不错的公司，我该怎么选择，当时我很犹豫，我热爱我的事业，我向往我的追求， 但我也是一个普通的人，我也需要养家糊口，我也想早一点买房买车。生活给我出了一道难题。 <BR>&nbsp; 　爱因斯坦在63岁时说过“一个人没有在30岁以前达成科学上的最大成就，那他永远都不会有。”这句话给了我很大的压力和震动，我马上就26岁了，离30只有四年时间，我必须抓紧这几年宝贵的时间，努力达到我技术上的最高峰。为了这个理想，为了能离自己的梦更近一些，我选择了这家IC公司，我明白自己的薪资和公司刚进来的硕士研究生相差无几， 但为了今后的发展只能忍受，一切又得重新开始。换行业是一个非常痛苦的过程，尤其从一个春风得意的位置换到一个陌生的岗位，感觉象从温暖的被子里钻出来跳进冰水中，让人难以接受。在原来那家通信公司，我是唯一两年时间涨了五次工资的员工，公司和同事都给了我极大的认可，工作上也常常被委以重任。但现在这一切都成了过去，在新的公司我只是一个新人,没有人知道也没有人在意我过去的成绩。我决定重新开始，我把自己看作新毕业的学生，我要用自己的努力得到公司的认可。进入新的行业是非常痛苦的，我告诉自己必须忍受这一切，虽然外面有很多诱惑，但是既然作出了选择我就不允许自己轻易放弃 。 <BR>　　我现在已经在这家新公司上了一个多月的班，开始非常艰难，现在慢慢适应了。第一 个月结束时，Team Leader找我谈话，说我是新进员工中最优秀的一个，我心里很欣慰，这也算对我努力的一个肯定吧。在这里还要感谢我的女朋友，她给了我很大的支持和鼓舞， 每次在我动摇的时候她都在鼓励我，让我坚持自己的理想，刚来上海是她让我不要勉强去做MIS，这次也是她让我顶住了月薪过万的诱惑，没有她我可能不会有今天的成绩。 现在的公司有自己的操作系统，自己的CPU、DSP和其它芯片，在这里我能学到世界上最先进的技术，我们的设计开发不再完全依赖别人的硬件和系统，这让我很开心。我打算等工作步入正轨后，全力学习新的知识，实现我的理想。 </P>
<P>&nbsp;&nbsp;&nbsp; 在后面的两年里我给自己定下了几个目标： </P>
<P>一.努力做好本职工作，在工作上得到公司和同事们的认同； </P>
<P>二.努力学习IC硬件设计知识，多向同事请教，并利用一切机会多实践； </P>
<P>三.实现我的实时操作系统的主要部分，完成TCP/IP协议栈模块，并免费发布源代码； </P>
<P>四.和我女朋友结婚并买一套小房子，这是最重要的，因为我明白事业是可以重来的，但是珍贵的感情很难失而复得。 </P>
<P>这里提一下我现在开发的操作系统，它是一个实时嵌入式系统，目前支持以下特性： </P>
<P>&nbsp;a.支持时间片轮转调度和基于优先级调度，最多64个优先级； </P>
<P>&nbsp;b.抢占式实时内核； </P>
<P>&nbsp;c.为了便于移植，主体用标准C实现； </P>
<P>&nbsp;d.汇编代码非常少，不到100行； </P>
<P>&nbsp;e.支持任务管理，各任务有独立的堆栈； </P>
<P>&nbsp;f.进程同步和通信目前完成了Semaphore，Message Queue正在调试； </P>
<P>&nbsp;g.实现了定时系统调用； </P>
<P>&nbsp;h.可以在windows上仿真调试 </P>
<P>&nbsp;&nbsp;&nbsp; 我还打算下一步实现优先级反转保护，Event Flag，Data Pipe，内存管理（以前实现过）、驱动接口等。 在这之后我还会努力完善它，比如加入文件系统，协议栈、调试接口等。希望朋友们提出自己的意见和建议，在此不胜感激！ </P>
<P>&nbsp;后记： </P>
<P>　　就像有的朋友说的，我的经历或许会给一些朋友产生误导，在这里我必须说明一下。 我来上海以前学习过于拼命，常常晚上只睡3个多小时，我身高1米71，那时只有108斤（我现在130多），家人也说我这样拼命活不过60岁，但是当时的我太固执，我对他们说只要能实现理想活50岁我就够了。那时的拼命使我的身体受到了影响，有一次早上突然腰肌剧痛难忍，痛的我倒在床上站不起来。虽然我现在已经比较注意，但有时候还会隐隐作痛。后来在女朋友说服了我，来上海以后我不再如此。我经常引用父亲的一句话“身体是革命的本钱”。<BR>　　而且我也发现拼命不是办法，我可以熬一两个通宵，最多的一次我连续工作了三天三夜， 但是我半个月都没有恢复过来，这样是不是得不偿失？学习工作应该是一个长期的过程， 像马拉松而不是百米冲刺。我现在非常注意调整学习和工作的强度，我要保证每天尽量有相对充沛的精力，一些年轻的朋友觉得自己也应该拼命努力，这让我多少有些担心，如果我的故事能让你在学习工作上多一点兴趣，我会感到很开心，但如果误导了某些朋友，让你做一些不值得的付出，我会感到很内疚。<BR>&nbsp; 　技术没有贵贱之分，我以前换行业是因为自己的兴趣所致，而不是对哪个行业有什么偏见。我希望我的经历不要给朋友一个错误的导向，觉得我始终向更高的技术发展。其实各行各业做到顶尖都是很困难的。话又说回来虽然技术没有贵贱，但是门槛是有高低的， 无论如何，做IC的门槛要比做网页的高，这一点无可否认。国家各种人才都是需要的，但是作为个人奋发向上的想法还是应该有的，努力在自己喜欢的行业上做的更好，而不应该停留在比较肤浅的层次上。<BR>　　我是一个自己觉得比较有自知之明的人，或许我最大的优点就是知道自己有很多缺点 ：）。我的故事中很多的曲折和错误都是由我的缺点造成的，希望大家用审慎的眼光看待我的经历，不要被我的“花言巧语”所迷惑。我学习有些随心所欲，这给我带来了无尽的麻烦，也大大阻碍的我的发展。记得我小时候成绩比较出色，但是后来学习严重偏科，导致我中学成绩一再滑坡，也没有考上什么好的学校，小时候的一个朋友，当时的成绩和我相仿，但是没有我这个缺点，她上了清华，后来在去了美国深造，在一个著名导师手下研究理论科学，这未尝不是一条更好的出路。另外我的学习方法也是在不断改善中的，过去的学习过于讲究数量和时间，那样学习既苦而已效率不高，现在我非常注意学习的效率和技巧，这样才是学习的捷径（当然不是指投机取巧），比如说学一相对陌生的技术，如果有条件，不妨问一问有经验的人，不需要问很多，往往他不经意的几句话会给你非常大的帮助，甚至超过你看一个星期的书。带着这样的思想再去学习你会节省很多时间，这样何乐不为呢？这些年中我学了不少的东西，由于开始非常盲目，所以学的东西杂乱无章，现在回想起来让我啼笑皆非，我把大量的时间浪费在一些没有必要深入了解的知识上，毕竟一个人的精力是有限度的。很多朋友很我一样都背过五笔字形，的确它是个不错的输入法，但是对一个研发人员它绝对不值得你去背，你的时间应该花在有价值的地方。我这样的事情还做过很多，我背过CCED、WPS的命令和快捷键，在dBase基本退出历史舞台后我还花了很多时间去学习它的使用。所以我的学习在前期缺乏规划，没有明确的短期目的、中期目标，只有一个虚无飘渺的长期的理想。这就像做设计一样，好的设计是从需求抽象到代码有很多过程，而不能得到了需求就立刻开始开始编码。 <BR>&nbsp;　　当然这么些年的学习和工作多多少少有些收获，下面我说说我的一些学习的心得，这 些方法未必正确，我也在不断探索和改进中。我的学习和工作有相对明确的目标，我不会一时心动而去学习某一技术，在下决定之前我会考虑很多，包括长期的发展，个人路线的规划，需要付出的代价、可能遇到的困难及解决的办法等等，在决定后还会制定更加明确的计划，包括短期、中期和长期的，身边可以利用到的资源（包括好的书籍、资料、软硬件环境，也包括有经验的朋友或者师长），以及每一个阶段是怎么过渡到高一阶段的计划，往往在一个学习阶段一旦上路后会走的相对顺利，但是跨阶段通常比较麻烦，比如从学习基础知识转到实践。另外我买书也有自己的方法，现在世面上高质量的书远不如低质量书多，对于一个陌生的技术，往往在第一次买书会选择错误，即使买到一本好书但是它的方向也未必适合你，所以我通常会先在网上查找一些该技术的介绍，有了一点点概念后再去买一本比较薄、相对便宜并且内容相对泛泛而谈的书，这是国内作者最善于写的书：） ，再把它浏览一遍后我就会基本明白这门技术的要点，后面买书和制定计划就会明确的多。否则一开始就想找本好书往往比较困难，而且买回来后努力学习，有时候学了一半才发现是本低质量的书或者是相对过时技术，让人非常懊恼。另外让有经验的人帮你介绍，通常也是一个不错的选择。<BR>　　有些朋友想学通信、嵌入式开发，但总觉得自己没有软硬件环境，我就按我的了解给 大家介绍一下怎么建立这样的环境，当然我了解的只是我学习和工作的方向。通信我做的是数据网方面的工作，包括TCP/IP、二三层交换、对接入网、H.323和软交换也有一点认识。这些软硬件环境都是可以在PC上构建的。你甚至可以在一个没有网卡的PC上建立一个包含多个路由器、接入服务器、VoIP网关、网守、主机等的仿真网络环境，而且与实际的网络相当接近，当然这需要你有清晰的网络概念和一定的网络知识，我一直在努力开发一套软件将这个过程简化，目前试验已经做完，我可能会将它融入我的操作系统外围扩展软件中。这样的方法我无法用简单的语句讲的很清楚，我可以说一下大概的思想，就是在PC上实现仿真网卡，（知道Windows怎么在没有网卡的机器实现虚拟网卡技术的朋友都应该会明白），然后每一个仿真网卡对应一个虚拟设备，如路由器或者主机。你也可以借助第三方工具完成部分工作，如VmWare等。我现在就是利用一个仿真网卡做自己的开发的。<BR>　　至于嵌入式开发环境更加容易实现，PC就是一个非常大的硬件平台，现有的嵌入式操 作系统通常都支持X86，你可以在上面做开发，通过软盘Boot或者使用虚拟机装载，我用VxWorks做了试验，在一台PC上跑Windows和VxWorks两个系统。另外Windows上的兼容DOS的16位仿真X86环境也为很多操作系统提供了绝佳的试验环境，我的操作系统在Windows上就是这样实现的。Linux在嵌入式中应用也比较广泛，它在网上有大量的资料，而且也相对比较容易实践。同时很多完善的嵌入式开发环境支持软件仿真，如Tornado、WinCE等。 </P><img src ="http://www.blogjava.net/Pudgy/aggbug/10219.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Pudgy/" target="_blank">Pudgy's World</a> 2005-08-16 12:58 <a href="http://www.blogjava.net/Pudgy/archive/2005/08/16/10219.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ImageIO 's IIOReadProgressListener</title><link>http://www.blogjava.net/Pudgy/archive/2005/08/16/10215.html</link><dc:creator>Pudgy's World</dc:creator><author>Pudgy's World</author><pubDate>Tue, 16 Aug 2005 04:19:00 GMT</pubDate><guid>http://www.blogjava.net/Pudgy/archive/2005/08/16/10215.html</guid><wfw:comment>http://www.blogjava.net/Pudgy/comments/10215.html</wfw:comment><comments>http://www.blogjava.net/Pudgy/archive/2005/08/16/10215.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Pudgy/comments/commentRss/10215.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Pudgy/services/trackbacks/10215.html</trackback:ping><description><![CDATA[<FONT face=Verdana size=2>Recently, I am working on graphic project. This project I faced is a big challenge to me. Here is a sloution to show the progress bar when loading the image from the net.<BR>PS:<BR>If you install the JAI, it will break the progress interrupt. <BR>See this in Sun's Bug Database </FONT><A href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4842452"><FONT face=Verdana size=2>http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4842452</FONT></A><BR><BR><BR>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #008080">&nbsp;&nbsp;1</SPAN>&nbsp;<SPAN style="COLOR: #000000">import&nbsp;java.awt.BorderLayout;<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;&nbsp;2</SPAN>&nbsp;<SPAN style="COLOR: #000000">import&nbsp;java.awt.</SPAN><SPAN style="COLOR: #0000ff">event</SPAN><SPAN style="COLOR: #000000">.ActionEvent;<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;&nbsp;3</SPAN>&nbsp;<SPAN style="COLOR: #000000">import&nbsp;java.awt.</SPAN><SPAN style="COLOR: #0000ff">event</SPAN><SPAN style="COLOR: #000000">.ActionListener;<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;&nbsp;4</SPAN>&nbsp;<SPAN style="COLOR: #000000">import&nbsp;java.awt.image.BufferedImage;<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;&nbsp;5</SPAN>&nbsp;<SPAN style="COLOR: #000000">import&nbsp;java.io.IOException;<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;&nbsp;6</SPAN>&nbsp;<SPAN style="COLOR: #000000">import&nbsp;java.net.MalformedURLException;<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;&nbsp;7</SPAN>&nbsp;<SPAN style="COLOR: #000000">import&nbsp;java.net.URL;<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;&nbsp;8</SPAN>&nbsp;<SPAN style="COLOR: #000000">import&nbsp;java.util.Iterator;<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;&nbsp;9</SPAN>&nbsp;<SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">&nbsp;10</SPAN>&nbsp;<SPAN style="COLOR: #000000">import&nbsp;javax.imageio.ImageIO;<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;11</SPAN>&nbsp;<SPAN style="COLOR: #000000">import&nbsp;javax.imageio.ImageReader;<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;12</SPAN>&nbsp;<SPAN style="COLOR: #000000">import&nbsp;javax.imageio.</SPAN><SPAN style="COLOR: #0000ff">event</SPAN><SPAN style="COLOR: #000000">.IIOReadProgressListener;<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;13</SPAN>&nbsp;<SPAN style="COLOR: #000000">import&nbsp;javax.imageio.stream.ImageInputStream;<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;14</SPAN>&nbsp;<SPAN style="COLOR: #000000">import&nbsp;javax.swing.</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">;<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;15</SPAN>&nbsp;<SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">&nbsp;16</SPAN>&nbsp;<SPAN style="COLOR: #000000"></SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;IIOProgressTest<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;17</SPAN>&nbsp;<SPAN style="COLOR: #000000">{<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;18</SPAN>&nbsp;<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)<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;19</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;{<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;20</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">try</SPAN><SPAN style="COLOR: #000000">&nbsp;{<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;21</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;22</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</SPAN><SPAN style="COLOR: #0000ff">catch</SPAN><SPAN style="COLOR: #000000">&nbsp;(Exception&nbsp;e)&nbsp;{<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;23</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;24</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;25</SPAN>&nbsp;<SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">&nbsp;26</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;final&nbsp;JLabel&nbsp;imageLabel&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;JLabel();<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;27</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JScrollPane&nbsp;scrollPane&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;JScrollPane(imageLabel);<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;28</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;final&nbsp;JButton&nbsp;startBtn&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">Load&nbsp;Image</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;29</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;final&nbsp;JProgressBar&nbsp;progressBar&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;JProgressBar();<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;30</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;progressBar.setVisible(</SPAN><SPAN style="COLOR: #0000ff">false</SPAN><SPAN style="COLOR: #000000">);<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;31</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JPanel&nbsp;p&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(</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;BorderLayout(</SPAN><SPAN style="COLOR: #000000">5</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">5</SPAN><SPAN style="COLOR: #000000">));<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;32</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p.add(startBtn,&nbsp;BorderLayout.WEST);<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;33</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p.add(progressBar,&nbsp;BorderLayout.CENTER);<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;34</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;35</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;final&nbsp;IIOReadProgressListener&nbsp;progressListener&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;IIOReadProgressListener()&nbsp;{<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;36</SPAN>&nbsp;<SPAN style="COLOR: #000000">&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;imageStarted(ImageReader&nbsp;source,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;imageIndex)<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;37</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;38</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SwingUtilities.invokeLater(</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;Runnable()<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;39</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;40</SPAN>&nbsp;<SPAN style="COLOR: #000000">&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">public</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;run()<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;41</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;42</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;startBtn.setEnabled(</SPAN><SPAN style="COLOR: #0000ff">false</SPAN><SPAN style="COLOR: #000000">);<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;43</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;progressBar.setValue(</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">);<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;44</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;progressBar.setVisible(</SPAN><SPAN style="COLOR: #0000ff">true</SPAN><SPAN style="COLOR: #000000">);<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;45</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;invalidate();<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;46</SPAN>&nbsp;<SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">&nbsp;47</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;48</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;49</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;50</SPAN>&nbsp;<SPAN style="COLOR: #000000">&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;imageProgress(ImageReader&nbsp;source,&nbsp;final&nbsp;</SPAN><SPAN style="COLOR: #0000ff">float</SPAN><SPAN style="COLOR: #000000">&nbsp;percentageDone)<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;51</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;52</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SwingUtilities.invokeLater(</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;Runnable()<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;53</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;54</SPAN>&nbsp;<SPAN style="COLOR: #000000">&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">public</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;run()<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;55</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;56</SPAN>&nbsp;<SPAN style="COLOR: #000000">&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.</SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000">.println(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">percentageDone</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">+</SPAN><SPAN style="COLOR: #000000">&nbsp;percentageDone);<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;57</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;progressBar.setValue((</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">)&nbsp;(percentageDone));<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;58</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;59</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;60</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;61</SPAN>&nbsp;<SPAN style="COLOR: #000000">&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;imageComplete(ImageReader&nbsp;source)&nbsp;<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;62</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;63</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SwingUtilities.invokeLater(</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;Runnable()<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;64</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;65</SPAN>&nbsp;<SPAN style="COLOR: #000000">&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">public</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;run()<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;66</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;67</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;startBtn.setEnabled(</SPAN><SPAN style="COLOR: #0000ff">true</SPAN><SPAN style="COLOR: #000000">);<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;68</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;progressBar.setValue(</SPAN><SPAN style="COLOR: #000000">100</SPAN><SPAN style="COLOR: #000000">);<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;69</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;progressBar.setVisible(</SPAN><SPAN style="COLOR: #0000ff">false</SPAN><SPAN style="COLOR: #000000">);<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;70</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;71</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;72</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;73</SPAN>&nbsp;<SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">&nbsp;74</SPAN>&nbsp;<SPAN style="COLOR: #000000">&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;sequenceStarted(ImageReader&nbsp;source,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;minIndex)&nbsp;{}<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;75</SPAN>&nbsp;<SPAN style="COLOR: #000000">&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;sequenceComplete(ImageReader&nbsp;source)&nbsp;{}<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;76</SPAN>&nbsp;<SPAN style="COLOR: #000000">&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;thumbnailStarted(ImageReader&nbsp;source,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;imageIndex,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;thumbnailIndex)&nbsp;{}<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;77</SPAN>&nbsp;<SPAN style="COLOR: #000000">&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;thumbnailProgress(ImageReader&nbsp;source,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">float</SPAN><SPAN style="COLOR: #000000">&nbsp;percentageDone)&nbsp;{}<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;78</SPAN>&nbsp;<SPAN style="COLOR: #000000">&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;thumbnailComplete(ImageReader&nbsp;source)&nbsp;{}<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;79</SPAN>&nbsp;<SPAN style="COLOR: #000000">&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;readAborted(ImageReader&nbsp;source)&nbsp;{}<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;80</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;81</SPAN>&nbsp;<SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">&nbsp;82</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;startBtn.addActionListener(</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;ActionListener()<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;83</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;84</SPAN>&nbsp;<SPAN style="COLOR: #000000">&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)<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;85</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;86</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;final&nbsp;String&nbsp;urlStr&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;JOptionPane.showInputDialog(<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;87</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SwingUtilities.getWindowAncestor(startBtn),&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">Input&nbsp;image&nbsp;URL</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;88</SPAN>&nbsp;<SPAN style="COLOR: #000000">&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;(urlStr&nbsp;</SPAN><SPAN style="COLOR: #000000">==</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">null</SPAN><SPAN style="COLOR: #000000">)&nbsp;{<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;89</SPAN>&nbsp;<SPAN style="COLOR: #000000">&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">return</SPAN><SPAN style="COLOR: #000000">;<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;90</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;91</SPAN>&nbsp;<SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">&nbsp;92</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;Thread()&nbsp;{<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;93</SPAN>&nbsp;<SPAN style="COLOR: #000000">&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">public</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;run()<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;94</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;95</SPAN>&nbsp;<SPAN style="COLOR: #000000">&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">try</SPAN><SPAN style="COLOR: #000000">&nbsp;{<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;96</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;URL&nbsp;url&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;URL(urlStr);<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;97</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ImageInputStream&nbsp;iis&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;ImageIO.createImageInputStream(url.openStream());<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;98</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Iterator&nbsp;iter&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;ImageIO.getImageReaders(iis);<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;99</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&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">if</SPAN><SPAN style="COLOR: #000000">&nbsp;(iter.hasNext())&nbsp;{<BR></SPAN><SPAN style="COLOR: #008080">100</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ImageReader&nbsp;reader&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;(ImageReader)&nbsp;iter.next();<BR></SPAN><SPAN style="COLOR: #008080">101</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reader.setInput(iis);<BR></SPAN><SPAN style="COLOR: #008080">102</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reader.addIIOReadProgressListener(progressListener);<BR></SPAN><SPAN style="COLOR: #008080">103</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BufferedImage&nbsp;image&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;reader.read(reader.getMinIndex());<BR></SPAN><SPAN style="COLOR: #008080">104</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;final&nbsp;ImageIcon&nbsp;icon&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;ImageIcon(image);<BR></SPAN><SPAN style="COLOR: #008080">105</SPAN>&nbsp;<SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">106</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SwingUtilities.invokeLater(</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;Runnable()<BR></SPAN><SPAN style="COLOR: #008080">107</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR></SPAN><SPAN style="COLOR: #008080">108</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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">public</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;run()<BR></SPAN><SPAN style="COLOR: #008080">109</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR></SPAN><SPAN style="COLOR: #008080">110</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;imageLabel.setIcon(icon);<BR></SPAN><SPAN style="COLOR: #008080">111</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;imageLabel.revalidate();<BR></SPAN><SPAN style="COLOR: #008080">112</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR></SPAN><SPAN style="COLOR: #008080">113</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});<BR></SPAN><SPAN style="COLOR: #008080">114</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR></SPAN><SPAN style="COLOR: #008080">115</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&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">catch</SPAN><SPAN style="COLOR: #000000">&nbsp;(MalformedURLException&nbsp;e)&nbsp;{<BR></SPAN><SPAN style="COLOR: #008080">116</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<BR></SPAN><SPAN style="COLOR: #008080">117</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&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">catch</SPAN><SPAN style="COLOR: #000000">&nbsp;(IOException&nbsp;e)&nbsp;{<BR></SPAN><SPAN style="COLOR: #008080">118</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<BR></SPAN><SPAN style="COLOR: #008080">119</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR></SPAN><SPAN style="COLOR: #008080">120</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR></SPAN><SPAN style="COLOR: #008080">121</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}.start();<BR></SPAN><SPAN style="COLOR: #008080">122</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR></SPAN><SPAN style="COLOR: #008080">123</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});<BR></SPAN><SPAN style="COLOR: #008080">124</SPAN>&nbsp;<SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">125</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JFrame&nbsp;f&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(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">IIOProgressTest</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<BR></SPAN><SPAN style="COLOR: #008080">126</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f.getContentPane().setLayout(</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;BorderLayout(</SPAN><SPAN style="COLOR: #000000">5</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">5</SPAN><SPAN style="COLOR: #000000">));<BR></SPAN><SPAN style="COLOR: #008080">127</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f.getContentPane().add(scrollPane,&nbsp;BorderLayout.CENTER);<BR></SPAN><SPAN style="COLOR: #008080">128</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f.getContentPane().add(p,&nbsp;BorderLayout.SOUTH);<BR></SPAN><SPAN style="COLOR: #008080">129</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f.setSize(</SPAN><SPAN style="COLOR: #000000">800</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">600</SPAN><SPAN style="COLOR: #000000">);<BR></SPAN><SPAN style="COLOR: #008080">130</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f.setLocationRelativeTo(</SPAN><SPAN style="COLOR: #0000ff">null</SPAN><SPAN style="COLOR: #000000">);<BR></SPAN><SPAN style="COLOR: #008080">131</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);<BR></SPAN><SPAN style="COLOR: #008080">132</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f.setVisible(</SPAN><SPAN style="COLOR: #0000ff">true</SPAN><SPAN style="COLOR: #000000">);<BR></SPAN><SPAN style="COLOR: #008080">133</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<BR></SPAN><SPAN style="COLOR: #008080">134</SPAN>&nbsp;<SPAN style="COLOR: #000000">}<BR></SPAN><SPAN style="COLOR: #008080">135</SPAN>&nbsp;<SPAN style="COLOR: #000000"></SPAN></DIV></DIV><BR><img src ="http://www.blogjava.net/Pudgy/aggbug/10215.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Pudgy/" target="_blank">Pudgy's World</a> 2005-08-16 12:19 <a href="http://www.blogjava.net/Pudgy/archive/2005/08/16/10215.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java Learning Path </title><link>http://www.blogjava.net/Pudgy/archive/2005/08/15/10177.html</link><dc:creator>Pudgy's World</dc:creator><author>Pudgy's World</author><pubDate>Mon, 15 Aug 2005 14:31:00 GMT</pubDate><guid>http://www.blogjava.net/Pudgy/archive/2005/08/15/10177.html</guid><wfw:comment>http://www.blogjava.net/Pudgy/comments/10177.html</wfw:comment><comments>http://www.blogjava.net/Pudgy/archive/2005/08/15/10177.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Pudgy/comments/commentRss/10177.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Pudgy/services/trackbacks/10177.html</trackback:ping><description><![CDATA[<P dir=ltr style="MARGIN-RIGHT: 0px"><BR>Java&nbsp;Learning&nbsp;Path&nbsp;（一）、工具篇&nbsp;<BR>一、&nbsp;JDK&nbsp;(Java&nbsp;Development&nbsp;Kit)&nbsp;<BR><BR>JDK是整个Java的核心，包括了Java运行环境（Java&nbsp;Runtime&nbsp;Envirnment），一堆Java工具和Java基础的类库(rt.jar)。不论什么Java应用服务器实质都是内置了某个版本的JDK。因此掌握JDK是学好Java的第一步。最主流的JDK是Sun公司发布的JDK，除了Sun之外，还有很多公司和组织都开发了自己的JDK，例如IBM公司开发的JDK，BEA公司的Jrocket，还有GNU组织开发的JDK等等。其中IBM的JDK包含的JVM（Java&nbsp;Virtual&nbsp;Machine）运行效率要比Sun&nbsp;JDK包含的JVM高出许多。而专门运行在x86平台的Jrocket在服务端运行效率也要比Sun&nbsp;JDK好很多。但不管怎么说，我们还是需要先把Sun&nbsp;JDK掌握好。&nbsp;<BR><BR>1、&nbsp;JDK的下载和安装&nbsp;<BR>JDK又叫做J2SE（Java2&nbsp;SDK&nbsp;Standard&nbsp;Edition），可以从Sun的Java网站上下载到，http://java.sun.com/j2se/downloads.html&nbsp;，JDK当前最新的版本是J2SDK1.4.2，建议下载该版本的JDK，下载页面在这里：http://java.sun.com/j2se/1.4.2/download.html。&nbsp;<BR><BR>下载好的JDK是一个可执行安装程序，默认安装完毕后会在C:\Program&nbsp;Files\Java\目录下安装一套JRE（供浏览器来使用），在C:\j2sdk1.4.2下安装一套JDK（也包括一套JRE）。然后我们需要在环境变量PATH的最前面增加java的路径C:\j2sdk1.4.2\bin。这样JDK就安装好了。&nbsp;<BR><BR>2、&nbsp;JDK的命令工具&nbsp;<BR>JDK的最重要命令行工具：&nbsp;<BR>java：&nbsp;启动JVM执行class&nbsp;<BR>javac：&nbsp;Java编译器&nbsp;<BR>jar：&nbsp;Java打包工具&nbsp;<BR>javadoc：&nbsp;Java文档生成器&nbsp;<BR>这些命令行必须要非常非常熟悉，对于每个参数都要很精通才行。对于这些命令的学习，JDK&nbsp;Documentation上有详细的文档。&nbsp;<BR><BR><BR>二、&nbsp;JDK&nbsp;Documentation&nbsp;<BR><BR>Documentation在JDK的下载页面也有下载连接，建议同时下载Documentation。Documentation是最最重要的编程手册，涵盖了整个Java所有方面的内容的描述。可以这样说，学习Java编程，大部分时间都是花在看这个Documentation上面的。我是随身携带的，写Java代码的时候，随时查看，须臾不离手。&nbsp;<BR><BR><BR>三、&nbsp;应用服务器(App&nbsp;Server)&nbsp;<BR><BR>App&nbsp;Server是运行Java企业组件的平台，构成了应用软件的主要运行环境。当前主流的App&nbsp;Server是BEA公司的Weblogic&nbsp;Server和IBM公司的Websphere以及免费的Jboss，选择其中一个进行学习就可以了，个人推荐Weblogic，因为它的体系结构更加干净，开发和部署更加方便，是Java企业软件开发人员首选的开发平台。下面简要介绍几种常用的App&nbsp;Server：&nbsp;<BR><BR>1、&nbsp;Tomcat&nbsp;<BR>Tomcat严格意义上并不是一个真正的App&nbsp;Server，它只是一个可以支持运行Serlvet/JSP的Web容器，不过Tomcat也扩展了一些App&nbsp;Server的功能，如JNDI，数据库连接池，用户事务处理等等。Tomcat被非常广泛的应用在中小规模的Java&nbsp;Web应用中，因此本文做一点下载、安装和配置Tomcat的介绍：&nbsp;<BR><BR>Tomcat是Apache组织下Jakarta项目下的一个子项目，它的主网站是：http://jakarta.apache.org/tomcat/&nbsp;，Tomcat最新版本是Tomcat4.1.27，软件下载的连接是：http://www.apache.org/dist/jakarta/tomcat-4/binaries/&nbsp;。&nbsp;<BR><BR>下载Tomcat既可以直接下载zip包，也可以下载exe安装包（个人建议zip更干净些），不管哪种情况，下载完毕安装好以后（zip直接解压缩就可以了）。需要设置两个环境变量：&nbsp;<BR><BR>JAVA_HOME=C:\j2sdk1.4.2&nbsp;<BR>CATALINA_HOME=D:\tomcat4&nbsp;(你的Tomcat安装目录)&nbsp;<BR><BR>这样就安装好了，启动Tomcat运行CATALINA_HOME\bin\startup.bat，关闭Tomcat运行shutdown.bat脚本。Tomcat启动以后，默认使用8080端口，因此可以用浏览器访问http://localhost:8080来测试Tomcat是否正常启动。&nbsp;<BR><BR>Tomcat提供了两个Web界面的管理工具，URL分别是：&nbsp;<BR>http://localhost:8080/admin/index.jsp&nbsp;<BR>http://localhost:8080/manager/html&nbsp;<BR>在启用这两个管理工具之前，先需要手工配置一下管理员用户和口令。用一个文本工具打开CATALINA_HOME\conf\tomcat-users.xml这个文件，加入如下几行：&nbsp;<BR><BR>&lt;role&nbsp;rolename="manager"/&gt;&nbsp;<BR>&lt;role&nbsp;rolename="admin"/&gt;&nbsp;<BR>&lt;user&nbsp;username="robbin"&nbsp;password="12345678"&nbsp;roles="admin,manager,tomcat"/&gt;&nbsp;<BR><BR>这样用户“robbin”就具备了超级管理员权限。重新启动Tomcat以后，你就可以使用该用户来登陆如上的两个管理工具，通过Web方式进行Tomcat的配置和管理了。&nbsp;<BR><BR>2、&nbsp;BEA&nbsp;Weblogic&nbsp;<BR>Weblogic可以到BEA的网站上免费注册之后下载到最新的Weblogic8.1企业版，License可以免费使用1年时间，其实这已经完全足够了。Weblogic的下载连接：http://commerce.bea.com/index.jsp，Weblogic的在线文档：http://edocs.bea.com/&nbsp;。&nbsp;<BR><BR>3、&nbsp;IBM&nbsp;Webshpere&nbsp;<BR>Websphere同样可以下载到免费的试用版本，到IBM的developerWorks网站可以看到Websphere试用产品的下载和相关的Websphere的资料，developerWorks中文网站的连接是：http://www-900.ibm.com/developerWorks/cn/wsdd/&nbsp;，Websphere的下载连接：http://www7b.software.ibm.com/wsdd/downloads/WASsupport.html&nbsp;。&nbsp;<BR><BR>4、&nbsp;Jboss&nbsp;<BR>Jboss是免费开源的App&nbsp;Server，可以免费的从Jboss网站下载：http://www.jboss.org/index.html，然而Jboss的文档是不免费，需要花钱购买，所以为我们学习Jboss设置了一定的障碍。在Jdon上有几篇不错的Jboss配置文档，可以用来参考：http://www.jdon.com/idea.html&nbsp;<BR><BR><BR>四、&nbsp;Java应用的运行环境&nbsp;<BR><BR>Java的应用可以简单分为以下几个方面：&nbsp;<BR><BR>1、&nbsp;Java的桌面应用&nbsp;<BR>桌面应用一般仅仅需要JRE的支持就足够了。&nbsp;<BR><BR>2、&nbsp;Java&nbsp;Web应用&nbsp;<BR>Java的Web应用至少需要安装JDK和一个web容器（例如Tomcat），以及一个多用户数据库，Web应用至少分为三层：&nbsp;<BR>Browser层：浏览器显示用户页面&nbsp;<BR>Web层：运行Servlet/JSP&nbsp;<BR>DB层：后端数据库，向Java程序提供数据访问服务&nbsp;<BR><BR>3、&nbsp;Java企业级应用&nbsp;<BR>企业级应用比较复杂，可以扩展到n层，最简单情况会分为4层：&nbsp;<BR>Browser层：浏览器显示用户页面&nbsp;<BR>Client层：Java客户端图形程序（或者嵌入式设备的程序）直接和Web层或者EJB层交互&nbsp;<BR>Web层：运行Servlet/JSP&nbsp;<BR>EJB层：运行EJB，完成业务逻辑运算&nbsp;<BR>DB层：后端数据库，向Java程序提供数据访问服务&nbsp;<BR><BR>4、&nbsp;Java嵌入式应用&nbsp;<BR>Java嵌入式应用是一个方兴未艾的领域，从事嵌入式开发，需要从Sun下载J2ME开发包，J2ME包含了嵌入式设备专用虚拟机KVM，和普通的JDK中包含的JVM有所不同。另外还需要到特定的嵌入式厂商那里下载模拟器。&nbsp;<BR><BR><BR>Java&nbsp;Learning&nbsp;Path（二）、书籍篇&nbsp;<BR><BR>学习一门新的知识，不可能指望只看一本，或者两本书就能够完全掌握。需要有一个循序渐进的阅读过程。我推荐Oreilly出版的Java系列书籍。&nbsp;<BR><BR>在这里我只想补充一点看法，很多人学习Java是从《Thinking&nbsp;in&nbsp;Java》这本书入手的，但是我认为这本书是不适合初学者的。我认为正确的使用这本书的方法应该是作为辅助的读物。《Thinking&nbsp;in&nbsp;Java》并不是在完整的介绍Java的整个体系，而是一种跳跃式的写作方法，是一种类似tips的方法来对Java很多知识点进行了深入的分析和解释。&nbsp;<BR><BR>对于初学者来说，最好是找一本Java入门的书籍，但是比较完整的循序的介绍Java的语法，面向对象的特性，核心类库等等，在看这本书的同时，可以同步来看《Thinking&nbsp;in&nbsp;Java》，来加深对Java的理解和原理的运用，同时又可以完整的了解Java的整个体系。&nbsp;<BR><BR>对于Java的入门书籍，蔡学镛推荐的是Oreilly的《Exploring&nbsp;Java,&nbsp;2nd&nbsp;Edition》&nbsp;或者《Java&nbsp;in&nbsp;a&nbsp;Nutshell,2nd&nbsp;Edition（针对C++背景）》，我并没有看过这两本书。其实我觉得电子工业出版社的《Java&nbsp;2编程详解》或者《Java&nbsp;2从入门到精通》就很不错。&nbsp;<BR><BR>在所有的Java书籍当中，其实最最有用的，并不是O'reilly的&nbsp;Java&nbsp;Serials，真正最最有用处是JDK的Documentation！几乎你想获得的所有的知识在Documentation里面全部都有，其中最主要的部分当然是Java基础类库的API文档，是按照package来组织的，对于每一个class都有详细的解释，它的继承关系，是否实现了某个接口，通常用在哪些场合，还可以查到它所有的public的属性和方法，每个属性的解释，意义，每个方法的用途，调用的参数，参数的意义，返回值的类型，以及方法可能抛出的异常等等。可以这样来说，所有关于Java编程方面的书籍其实都不过是在用比较通俗易懂的语言，和良好的组织方式来介绍Documentation里面的某个package里面包含的一些类的用法而已。所以万变不离其宗，如果你有足够的能力来直接通过Documentation来学习Java的类库，那么基本上就不需要看其他的书籍了。除此之外，Documentation也是编程必备的手册，我的桌面上有三个Documentation的快捷方式，分别是J2SDK1.4.1的Documentation，Servlet2.3的Documentation和J2SDKEE1.3.1的Documentation。有了这个三个Documentation，什么其他的书籍都不需要了。&nbsp;<BR><BR>对于Java&nbsp;Web&nbsp;编程来说，最核心的是要熟悉和掌握HTTP协议，这个就和Java无关了，在熟悉HTTP协议之后，就需要熟悉Java的实现HTTP协议的类库，也就是Servlet&nbsp;API，所以最重要的东西就是Servlet&nbsp;API。当然对于初学者而言，直接通过Servlet&nbsp;API来学习Web编程有很大的难度，我推荐O'reilly的《Java&nbsp;Server&nbsp;Pages&nbsp;》这本书来学习Web&nbsp;编程。&nbsp;<BR><BR>EJB的书籍当中，《Enterprise&nbsp;JavaBeans,&nbsp;2nd&nbsp;Edition》是一本很不错的书，&nbsp;EJB的学习门槛是比较高，入门很难，但是这本书完全降低了学习的难度，特别重要的一点是，EJB的学习需要结合一种App&nbsp;Server的具体实现，所以在学习EJB的同时，必须同步的学习某种App&nbsp;Server，而这本书相关的出了三本书，分别是Weblogic6.1，Websphere4.0和JBoss3.0上面部署书中例子的实做。真是既有理论，又有实践。在学习EJB的同时，可以边看边做，EJB的学习会变得很轻松。&nbsp;<BR><BR>但是这本书也有一个问题，就是版本比较旧，主要讲EJB1.1规范和部分EJB2.0的规范。而Ed&nbsp;Roman写的《Mastering&nbsp;EJB&nbsp;2.0》这本书完全是根据EJB2.0规范写的，深入浅出，覆盖了EJB编程的各个方面，并且还有很多编程经验tips，也是学习EJB非常推荐的书籍之一。&nbsp;<BR><BR>如果是结合Weblogic来学习J2EE的话，《J2EE应用与BEA&nbsp;Weblogic&nbsp;Server》绝对是首选读物，虽然是讲述的Weblogic6.0，仍然值得购买，这本书是BEA官方推荐的教材，作者也是BEA公司的工程师。现在中文版已经随处可见了。这本书结合Weblogic介绍了J2EE各个方面的技术在Weblogic平台上的开发和部署，实践指导意义非常强。&nbsp;<BR><BR>在掌握了Java平台基础知识和J2EE方面的知识以后，更进一步的是学习如何运用OO的方法进行软件的设计，那么就一定要学习“设计模式”。Sun公司出版了一本《J2EE核心模式》，是每个开发Java企业平台软件的架构师必备的书籍。这本书全面的介绍了J2EE体系架构的各种设计模式，是设计师的必读书籍。&nbsp;<BR><BR>Java&nbsp;Learning&nbsp;Path（三）过程篇&nbsp;<BR><BR>每个人的学习方法是不同的，一个人的方法不见得适合另一个人，我只能是谈自己的学习方法。因为我学习Java是完全自学的，从来没有问过别人，所以学习的过程基本上完全是自己摸索出来的。我也不知道这种方法是否是比较好的方法，只能给大家提供一点参考了。&nbsp;<BR><BR>学习Java的第一步是安装好JDK，写一个Hello&nbsp;World，?&nbsp;其实JDK的学习没有那么简单，关于JDK有两个问题是很容易一直困扰Java程序员的地方：一个是CLASSPATH的问题，其实从原理上来说，是要搞清楚JRE的ClassLoader是如何加载Class的；另一个问题是package和import问题，如何来寻找类的路径问题。把这两个问题摸索清楚了，就扫除了学习Java和使用JDK的最大障碍。推荐看一下王森的《Java深度历险》，对这两个问题进行了深入的探讨。&nbsp;<BR><BR>第二步是学习Java的语法。Java的语法是类C++的，基本上主流的编程语言不是类C，就是类C++的，没有什么新东西，所以语法的学习，大概就是半天的时间足够了。唯一需要注意的是有几个不容易搞清楚的关键字的用法，public，protected，private，static，什么时候用，为什么要用，怎么用，这可能需要有人来指点一下，我当初是完全自己琢磨出来的，花了很久的时间。不过后来我看到《Thinking&nbsp;in&nbsp;Java》这本书上面是讲了这些概念的。&nbsp;<BR><BR>第三步是学习Java的面向对象的编程语言的特性的地方。比如继承，构造器，抽象类，接口，方法的多态，重载，覆盖，Java的异常处理机制。对于一个没有面向对象语言背景的人来说，我觉得这个过程需要花很长很长时间，因为学习Java之前没有C++的经验，只有C的经验，我是大概花了一个月左右吧，才彻底把这些概念都搞清楚，把书上面的例子反复的揣摩，修改，尝试，把那几章内容反复的看过来，看过去，看了不下5遍，才彻底领悟了。不过我想如果有C++经验的话，应该一两天时间足够了。那么在这个过程中，可以多看看《Thinking&nbsp;in&nbsp;Java》这本书，对面向对象的讲解非常透彻。可惜的是我学习的时候，并没有看到这本书，所以自己花了大量的时间，通过自己的尝试和揣摩来学会的。&nbsp;<BR><BR>第四步就是开始熟悉Java的类库。Java的基础类库其实就是JDK安装目录下面jre\lib\rt.jar这个包。学习基础类库就是学习rt.jar。基础类库里面的类非常非常多。据说有3000多个，我没有统计过。但是真正对于我们来说最核心的只有4个，分别是&nbsp;<BR>java.lang.*;&nbsp;<BR>java.io.*;&nbsp;<BR>java.util.*;&nbsp;<BR>java.sql.*;&nbsp;<BR><BR>这四个包的学习，每个包的学习都可以写成一本厚厚的教材，而O'reilly也确实是这样做的。我觉得如果时间比较紧，是不可能通过读四本书来学习。我觉得比较好的学习方法是这样的：&nbsp;<BR>首先要通读整个package的框架，了解整个package的class，interface，exception的构成，最好是能够找到介绍整个包框架的文章。这些专门介绍包的书籍的前几章应该就是这些总体的框架内容介绍。&nbsp;<BR><BR>对包整体框架的把握并不是要熟悉每个类的用法，记住它有哪些属性，方法。想记也记不住的。而是要知道包有哪些方面的类构成的，这些类的用途是什么，最核心的几个类分别是完成什么功能的。我在给人培训的时候一般是一次课讲一个包，所以不可能详细的介绍每个类的用法，但是我反复强调，我给你们讲这些包的不是要告诉你们类的方法是怎么调用的，也不要求你们记住类的方法调用，而是要你们了解，Java给我们提供了哪些类，每个类是用在什么场合，当我遇到问题的时候，我知道哪个类，或者哪几个类的组合可以解决我的问题，That'all！，当我们具体写程序的时候，只要你知道该用哪个类来完成你的工作就足够了。编码的时候，具体的方法调用，是边写代码，边查Documentation，所有的东西都在Documentation里面，不要求你一定记住，实际你也记不住3000多个类的总共将近10万个方法调用。所以对每个包的总体框架的把握就变得极为重要。&nbsp;<BR><BR>第五步，通过上面的学习，如果学的比较扎实的话，就打好了Java的基础了，剩下要做的工作是扫清Documentation里面除了上面4个包之外的其他一些比较有用处的类。相信进展到这一步，Java的自学能力已经被培养出来了，可以到了直接学习Documentation的水平了。除了要做GUI编程之外，JDK里面其他会有用处的包是这些：&nbsp;<BR>java.text.*;&nbsp;<BR>java.net.*;&nbsp;<BR>javax.naming.*;&nbsp;<BR>这些包里面真正用的比较多的类其实很少，只有几个，所以不需要花很多时间。&nbsp;<BR><BR>第六步，Java&nbsp;Web&nbsp;编程&nbsp;<BR>Web编程的核心是HTTP协议，HTTP协议和Java无关，如果不熟悉HTTP协议的话，虽然也可以学好Servlet/JSP编程，但是达不到举一反三，一通百通的境界。所以HTTP协议的学习是必备的。如果熟悉了HTTP协议的话，又有了Java编程的良好的基础，学习Servlet/JSP简直易如反掌，我学习Servlet/JSP就用了不到一周的时间，然后就开始用JSP来做项目了。&nbsp;<BR><BR>在Servlet/JSP的学习中，重头仍然是Servlet&nbsp;Documentation。Servlet&nbsp;API最常用的类很少，花比较少的时间就可以掌握了。把这些类都看一遍，多写几个例子试试。Servlet/JSP编程本质就是在反复调用这些类来通过HTTP协议在Web&nbsp;Server和Brower之间交谈。另外对JSP，还需要熟悉几个常用JSP的标记，具体的写法记不住的话，临时查就是了。&nbsp;<BR><BR>此外Java&nbsp;Web编程学习的重点要放在Web&nbsp;Application的设计模式上，如何进行业务逻辑的分析，并且进行合理的设计，按照MVC设计模式的要求，运用Servlet和JSP分别完成不同的逻辑层，掌握如何在Servlet和JSP之间进行流程的控制和数据的共享，以及Web&nbsp;Application应该如何配置和部署。&nbsp;<BR><BR>第七步，J2EE编程&nbsp;<BR>以上的学习过程如果是比较顺利的话，进行到这一步，难度又陡然提高。因为上面的知识内容都是只涉及一个方面，而像EJB，JMS，JTA等核心的J2EE规范往往是几种Java技术的综合运用的结晶，所以掌握起来难度比较大。&nbsp;<BR><BR>首先一定要学习好JNDI，JNDI是App&nbsp;Server定位服务器资源（EJB组件，Datasouce，JMS）查找方法，如果对JNDI不熟悉的话，EJB，JMS这些东西几乎学不下去。JNDI其实就是javax.naming.*这个包，运用起来很简单。难点在于服务器资源文件的配置。对于服务器资源文件的配置，就需要看看专门的文档规范了，比如web.xml的写法，ejb-jar.xml的写法等等。针对每种不同的App&nbsp;Server，还有自己的服务资源配置文件，也是需要熟悉的。&nbsp;<BR><BR>然后可以学习JTA，主要是要理解JTA对于事务的控制的方法，以及该在什么场合使用JTA。这里可以简单的举个例子，我们知道一般情况可以对于一个数据库连接进行事务控制(conn.setAutoCommit(false),....,conn.commit())，做为一个原子操作，但是假设我的业务需求是要把对两个不同数据库的操作做为一个原子操作，你能做的到吗？这时候只能用JTA了。假设操作过程是先往A数据库插一条记录，然后删除B数据库另一个记录，我们自己写代码是控制不了把整个操作做为一个原子操作的。用JTA的话，由App&nbsp;Server来完成控制。&nbsp;<BR><BR>在学习EJB之前要学习对象序列化和RMI，RMI是EJB的基础。接着学习JMS和EJB，对于EJB来说，最关键是要理解EJB是如何通过RMI来实现对远端对象的调用的，以及在什么情况下要用到EJB。&nbsp;<BR><BR>在学习完EJB，JMS这些东西之后，你可能会意识到要急不可待学习两个领域的知识，一个是UML，另一个是Design&nbsp;Pattern。Java企业软件的设计非常重视框架(Framework)的设计，一个好的软件框架是软件开发成功的必要条件。在这个时候，应该开始把学习的重点放在设计模式和框架的学习上，通过学习和实际的编程经验来掌握EJB的设计模式和J2EE的核心模式。&nbsp;<BR><BR>J2EE规范里面，除了EJB，JMS，JTA，Servlet/JSP，JDBC之外还有很多很多的企业技术，这里不一一进行介绍了。&nbsp;<BR><BR>另外还有一个最新领域Web&nbsp;Services。Web&nbsp;Services也完全没有任何新东西，它像是一种黏合剂，可以把不同的服务统一起来提供一个统一的调用接口，作为使用者来说，我只要获得服务提供者给我的WSDL（对服务的描述），就够了，我完全不知道服务器提供者提供的服务究竟是EJB组件，还是.Net组件，还是什么CORBA组件，还是其他的什么实现，我也不需要知道。Web&nbsp;Services最伟大的地方就在于通过统一的服务提供方式和调用方式，实现了整个Internet服务的共享，是一个非常令人激动的技术领域。Web&nbsp;Services好像目前还没有什么很好的书籍，但是可以通过在网络上面查资料的方式来学习。&nbsp;<BR><BR>Java&nbsp;Learning&nbsp;Path（四）&nbsp;方法篇&nbsp;<BR><BR>Java作为一门编程语言，最好的学习方法就是写代码。当你学习一个类以后，你就可以自己写个简单的例子程序来运行一下，看看有什么结果，然后再多调用几个类的方法，看看运行结果，这样非常直观的把类给学会了，而且记忆非常深刻。然后不应该满足把代码调通，你应该想想看如果我不这样写，换个方式，再试试行不行。记得哪个高人说过学习编程就是个破坏的过程，把书上的例子，自己学习Documentation编写的例子在运行通过以后，不断的尝试着用不同的方法实现，不断的尝试破坏代码的结构，看看它会有什么结果。通过这样的方式，你会很彻底的很精通的掌握Java。&nbsp;<BR><BR>举个例子，我们都编过Hello&nbsp;World&nbsp;<BR><BR></P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><IMG id=Codehighlighter1_24_108_Open_Image onclick="this.style.display='none'; Codehighlighter1_24_108_Open_Text.style.display='none'; Codehighlighter1_24_108_Closed_Image.style.display='inline'; Codehighlighter1_24_108_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_24_108_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_24_108_Closed_Text.style.display='none'; Codehighlighter1_24_108_Open_Image.style.display='inline'; Codehighlighter1_24_108_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align=top><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;HelloWorld&nbsp;</SPAN><SPAN id=Codehighlighter1_24_108_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"></SPAN><SPAN id=Codehighlighter1_24_108_Open_Text><SPAN style="COLOR: #000000">{&nbsp;<BR><IMG id=Codehighlighter1_66_105_Open_Image onclick="this.style.display='none'; Codehighlighter1_66_105_Open_Text.style.display='none'; Codehighlighter1_66_105_Closed_Image.style.display='inline'; Codehighlighter1_66_105_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_66_105_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_66_105_Closed_Text.style.display='none'; Codehighlighter1_66_105_Open_Image.style.display='inline'; Codehighlighter1_66_105_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top></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_66_105_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"></SPAN><SPAN id=Codehighlighter1_66_105_Open_Text><SPAN style="COLOR: #000000">{&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>System.</SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000">.println(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">Hello&nbsp;World</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>}</SPAN></SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</SPAN></SPAN></DIV></DIV>
<P dir=ltr style="MARGIN-RIGHT: 0px">&nbsp;<BR><BR>很多初学者不是很理解为什么main方法一定要这样来定义public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)，能不能不这样写？包括我刚学习Java的时候也有这样的疑问。想知道答案吗？很简单，你把main改个名字运行一下，看看报什么错误，然后根据出错信息进行分析；把main的public取掉，在试试看，报什么错误；static去掉还能不能运行；不知道main方法是否一定要传一个String[]数组的，把String[]改掉，改成int[]，或者String试试看；不知道是否必须写args参数名称的，也可以把args改成别的名字，看看运行结果如何。&nbsp;<BR><BR>我当初学习Java的时候就是这样做的，把Hello&nbsp;World程序反复改了七八次，不断运行，分析运行结果，最后就彻底明白为什么了main方法是这样定义的了。&nbsp;<BR><BR>此外，我对于staic，public，private，Exception，try{&nbsp;}catch&nbsp;{}finally{}等等等等一开始都不是很懂，都是把参考书上面的例子运行成功，然后就开始破坏它，不断的根据自己心里面的疑问来重新改写程序，看看能不能运行，运行出来是个什么样子，是否可以得到预期的结果。这样虽然比较费时间，不过一个例子程序这样反复破坏几次之后。我就对这个相关的知识彻底学通了。有时候甚至故意写一些错误的代码来运行，看看能否得到预期的运行错误。这样对于编程的掌握是及其深刻的。&nbsp;<BR><BR>其中特别值得一提的是JDK有一个非常棒的调试功能，-verbose&nbsp;<BR>java&nbsp;-verbose&nbsp;<BR>javac&nbsp;-verbose&nbsp;以及其它很多JDK工具都有这个选项&nbsp;<BR>-verbose&nbsp;可以显示在命令执行的过程中，JVM都依次加载哪里Class，通过这些宝贵的调试信息，可以帮助我们分析出JVM在执行的过程中都干了些什么。&nbsp;<BR><BR>另外，自己在学习过程中，写的很多的这种破坏例程，应该有意识的分门别类的保存下来，在工作中积累的典型例程也应该定期整理，日积月累，自己就有了一个代码库了。遇到类似的问题，到代码库里面&nbsp;Copy&nbsp;&amp;&nbsp;Paste&nbsp;，Search&nbsp;&amp;&nbsp;Replace，就好了，极大提高了开发速度。最理想的情况是把一些通用的例程自己再抽象一层，形成一个通用的类库，封装好。那么可复用性就更强了。&nbsp;<BR><BR>所以我觉得其实不是特别需要例程的，自己写的破坏例程就是最好的例子，如果你实在对自己写的代码不放心的话，我强烈推荐你看看JDK基础类库的Java源代码。在JDK安装目录下面会有一个src.zip，解开来就可以完整的看到整个JDK基础类库，也就是rt.jar的Java源代码，你可以参考一下Sun是怎么写Java程序的，规范是什么样子的。我自己在学习Java的类库的时候，当有些地方理解的不是很清楚的时候，或者想更加清晰的理解运作的细节的时候，往往会打开相应的类的源代码，通过看源代码，所有的问题都会一扫而空。&nbsp;<BR><BR>Java&nbsp;Learning&nbsp;Path（五）资源篇&nbsp;<BR><BR>1、&nbsp;http://java.sun.com/&nbsp;(英文)&nbsp;<BR>Sun的Java网站，是一个应该经常去看的地方。不用多说。&nbsp;<BR><BR>2、&nbsp;http://www-900.ibm.com/developerWorks/cn/&nbsp;<BR>IBM的developerWorks网站，英语好的直接去英文主站点看。这里不但是一个极好的面向对象的分析设计网站，也是Web&nbsp;Services，Java，Linux极好的网站。强烈推荐！！！&nbsp;<BR><BR>3、&nbsp;http://www.java-cn.com/&nbsp;(中文)&nbsp;<BR>JAVA中文站，目前国内资料最全、会员最多的JAVA技术网站，人气极高。有《JAVA电子书库》、《JAVA视频库》(国内唯一)、《JAVA技术文摘库》、《JAVA源代码库》、《JAVA工具库》、《招聘求职广场》等主要栏目，还有一些专家栏目。目前会员有5万多，VIP会员近1000人。无论是菜鸟还是老鸟，都能在此网站中找到自己所需要的东东！！　最强烈推荐！！！！！！&nbsp;<BR><BR>4、&nbsp;http://www.javaworld.com/&nbsp;(英文)&nbsp;<BR>关于Java很多新技术的讨论和新闻。想多了解Java的方方面面的应用，这里比较好。&nbsp;<BR><BR>5、&nbsp;http://dev2dev.bea.com.cn/index.jsp&nbsp;<BR>BEA的开发者园地，BEA作为最重要的App&nbsp;Server厂商，有很多独到的技术，在Weblogic上做开发的朋友不容错过。&nbsp;<BR><BR>6、&nbsp;http://www.huihoo.com/&nbsp;<BR>灰狐动力网站，一个专业的中间件网站，虽然不是专业的Java网站，但是在J2EE企业应用技术方面有深厚的造诣。&nbsp;<BR><BR>7、&nbsp;http://www.theserverside.com/home/&nbsp;(英文)&nbsp;<BR>TheServerSide是一个著名的专门面向Java&nbsp;Server端应用的网站。&nbsp;<BR><BR>8、&nbsp;http://www.javaresearch.org/&nbsp;<BR>Java研究组织，有很多优秀的Java方面的文章和教程，特别是在JDO方面的文章比较丰富。&nbsp;<BR><BR>9、&nbsp;http://www.cnjsp.org/&nbsp;<BR>JSP技术网站，有相当多的Java方面的文章和资源。&nbsp;<BR><BR>10、&nbsp;http://www.jdon.com/&nbsp;<BR>Jdon论坛，是一个个人性质的中文J2EE专业技术论坛，在众多的Java的中文论坛中，Jdon一个是技术含量非常高，帖子质量非常好的论坛。&nbsp;<BR><BR>11、&nbsp;http://sourceforge.net/&nbsp;<BR>SourgeForge是一个开放源代码软件的大本营，其中也有非常非常丰富的Java的开放源代码的著名的软件。</P><img src ="http://www.blogjava.net/Pudgy/aggbug/10177.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Pudgy/" target="_blank">Pudgy's World</a> 2005-08-15 22:31 <a href="http://www.blogjava.net/Pudgy/archive/2005/08/15/10177.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>