Do you drink java?



                像寫情書一樣coding

           

          2005年9月24日

          發發牢騷

          IE7訪問我的部落格頁面布局異常!

          Firefox2.0添加新隨筆JS腳本異常!!

          |/__


          換了風格

          posted @ 2006-11-23 16:49 leon 閱讀(410) | 評論 (0)編輯 收藏

          [Swing]在 JFileChooser 中進行文件驗證的小技巧

          我們在做GUI編程的時候經常需要用到JFileChooser組件構造一個文件選取對話框來為用戶提供打開文件、保存文件等操作。

          通常的做法是調用JFileChooser.showXXX()方法顯示文件選取對話框并且選擇一個文件后,點擊Approve 按鈕(默認情況下標有 "Open" 或 "Save")當對話框關閉后使用JFileChooser.getSelectedFile()方法得到選取的文件(或使用JFileChooser.getSelectedFiles()取得選取的文件數組),然后再對被選取的文件有效性進行驗證(例如,文件的文件名是否合法、選取的路徑下是否已有同名文件存在等等),如果驗證不通過,需要再次打開文件選擇對話框進行選取。

          顯然,驗證沒有通過的情況下,文件選取對話框被反復的打開和關閉,影響用戶體驗。

          我現在介紹一個方法,在點擊了文件選取對話框上的Approve 按鈕后,文件選取對話框關閉前對選取的文件進行驗證,如果驗證沒有通過,那么對話框不關閉,直接進行下一次選擇。

          查看JFileChooser的API,可以發現這樣一個方法 public void approveSelection() ,這個方法會在用戶單擊 Approve 按鈕時由 UI 調用此方法。導致使用等于 APPROVE_SELECTION 的命令字符串激發一個操作事件。

          那么,我們現在可以選擇繼承JFileChooser再覆寫這個方法,將對選中文件的有效性驗證寫入這個方法中,只有當驗證通過時才調用超類的approveSelection() 完成文件選取,否則直接返回,繼續選擇新的文件。

          下面是我寫的一個demo以供參考:

          import java.io.File;
          import javax.swing.JOptionPane;

          /**
          ?* 在 JFileChooser 中進行文件驗證的小技巧
          ?* @author Chen Wei
          ?* @email chenwei.mobi@gmail.com
          ?*/
          public class JFileChooserDemo extends javax.swing.JFileChooser{
          ???
          ??? public void approveSelection(){
          ??????? File file = getSelectedFile();
          ???????
          ??????? // 驗證文件名是否合法
          ??????? if (!validateFileName(file.getName())) {
          ??????????? JOptionPane.showMessageDialog(getParent(), "文件名不能包含下列任何字符之一:\n \\ / : * ? \" < > |");
          ??????????? return;
          ??????? }else{
          ??????????? super.approveSelection();
          ??????? }
          ??? }
          ???
          ??? /**
          ???? * 驗證輸入字符串參數是否為有效文件名。
          ???? * @param name 待驗證的文件名字符串。
          ???? * @return 通過驗證,文件名無效返回 false,有效返回 true。
          ???? */
          ??? public static boolean validateFileName(String name) {
          ??????? if (name.indexOf('\\') != -1 || name.indexOf('/') != -1 ||
          ??????????? name.indexOf(':') != -1 || name.indexOf('*') != -1 ||
          ??????????? name.indexOf('?') != -1 || name.indexOf('"') != -1 ||
          ??????????? name.indexOf('<') != -1 || name.indexOf('>') != -1 ||
          ??????????? name.indexOf('|') != -1) {

          ??????????? return false;
          ??????? } else {
          ??????????? return true;
          ??????? }
          ??? }
          ???
          ??? public static void main(String[] args){
          ??????? JFileChooserDemo chooser = new JFileChooserDemo();
          ??????? chooser.showOpenDialog(null);
          ??? }
          }


          程序運行截圖:
          JFileChooserDemo.jpg

          posted @ 2006-11-23 14:15 leon 閱讀(5405) | 評論 (7)編輯 收藏

          [news]chenwei.mobi

          本博搬家到CSDN,網址 http://blog.csdn.net/chenweionline ,可以通過 www.chenwei.mobi 訪問!

          posted @ 2006-10-30 17:16 leon 閱讀(545) | 評論 (0)編輯 收藏

          [tips]使用Java將中文字符轉換成Unicode編碼

          這兩天操作XML使用到了Jdom,在創建XML文件并輸出到硬盤的時候遇到一個中文編碼的問題:Jdom默認輸出的XML編碼是UTF-8,但是文檔中如果出現中文字符那么該中文字符就會變成亂碼,造成XML文件無法被正確解析。

          UTF-8應該是可以用來表示中文的吧?我不知道這是不是Jdom的一個BUG(Jdom 1.0,beta了10次的產物哦!)。我google了一下,大家解決這個問題的辦法無非是把Jdom的輸出字符集改為GBK或者GB2312,但是這樣就會有一些副作用,如果在沒有特定字符集(GBK或者GB2312)的操作系統上不是依然不能正確解析嗎?一個比較好的解決辦法是先把中文轉換成Unicode編碼在直接輸出,程序解析XML后的時候再把Unicode編碼轉回中文就沒有問題了。

          于是我查看了JDK的文檔,截至Java 5好像都沒有做類似轉換的類可以直接使用,但是我發現一個類 java.util.Properties,它的源代碼里有兩個私有(private)方法 loadConvert (char[] in, int off, int len, char[] convtBuf) 和 saveConvert(String theString, boolean escapeSpace) 其實就是做特殊字符和Unicode編碼字符間轉換的,我把它們提取出來,單獨包裝到一個類里就可以使用了。

          下面是我包裝的類 CharacterSetToolkit

          /*
          ?* CharacterSetToolkit.java
          ?*
          ?* Created on 2006年10月27日, 下午2:06
          ?*
          ?* To change this template, choose Tools | Template Manager
          ?* and open the template in the editor.
          ?*/

          package mobi.chenwei.lang;

          /**
          ?* 進行字符操作的工具類
          ?* @author Chen Wei
          ?* @email chenwei.mobi@gmail.com
          ?*/
          public class CharacterSetToolkit {
          ???
          ??? /** Creates a new instance of CharacterSetToolkit */
          ??? public CharacterSetToolkit() {
          ??? }
          ???
          ??? private static final char[] hexDigit = {
          ??????? '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
          ??? };
          ???
          ??? private static char toHex(int nibble) {
          ??????? return hexDigit[(nibble & 0xF)];
          ??? }
          ???
          ??? /**
          ???? * 將字符串編碼成 Unicode 。
          ???? * @param theString 待轉換成Unicode編碼的字符串。
          ???? * @param escapeSpace 是否忽略空格。
          ???? * @return 返回轉換后Unicode編碼的字符串。
          ???? */
          ??? public static String toUnicode(String theString, boolean escapeSpace) {
          ??????? int len = theString.length();
          ??????? int bufLen = len * 2;
          ??????? if (bufLen < 0) {
          ??????????? bufLen = Integer.MAX_VALUE;
          ??????? }
          ??????? StringBuffer outBuffer = new StringBuffer(bufLen);

          ??????? for(int x=0; x<len; x++) {
          ??????????? char aChar = theString.charAt(x);
          ??????????? // Handle common case first, selecting largest block that
          ??????????? // avoids the specials below
          ??????????? if ((aChar > 61) && (aChar < 127)) {
          ??????????????? if (aChar == '\\') {
          ??????????????????? outBuffer.append('\\'); outBuffer.append('\\');
          ??????????????????? continue;
          ??????????????? }
          ??????????????? outBuffer.append(aChar);
          ??????????????? continue;
          ??????????? }
          ??????????? switch(aChar) {
          ??????????????? case ' ':
          ??????????????????? if (x == 0 || escapeSpace)
          ??????????????????????? outBuffer.append('\\');
          ??????????????????? outBuffer.append(' ');
          ??????????????????? break;
          ??????????????? case '\t':outBuffer.append('\\'); outBuffer.append('t');
          ????????????????????????? break;
          ??????????????? case '\n':outBuffer.append('\\'); outBuffer.append('n');
          ????????????????????????? break;
          ??????????????? case '\r':outBuffer.append('\\'); outBuffer.append('r');
          ????????????????????????? break;
          ??????????????? case '\f':outBuffer.append('\\'); outBuffer.append('f');
          ????????????????????????? break;
          ??????????????? case '=': // Fall through
          ??????????????? case ':': // Fall through
          ??????????????? case '#': // Fall through
          ??????????????? case '!':
          ??????????????????? outBuffer.append('\\'); outBuffer.append(aChar);
          ??????????????????? break;
          ??????????????? default:
          ??????????????????? if ((aChar < 0x0020) || (aChar > 0x007e)) {
          ??????????????????????? outBuffer.append('\\');
          ??????????????????????? outBuffer.append('u');
          ??????????????????????? outBuffer.append(toHex((aChar >> 12) & 0xF));
          ??????????????????????? outBuffer.append(toHex((aChar >>? 8) & 0xF));
          ??????????????????????? outBuffer.append(toHex((aChar >>? 4) & 0xF));
          ??????????????????????? outBuffer.append(toHex( aChar??????? & 0xF));
          ??????????????????? } else {
          ??????????????????????? outBuffer.append(aChar);
          ??????????????????? }
          ??????????? }
          ??????? }
          ??????? return outBuffer.toString();
          ??? }
          ???
          ??? /**
          ???? * 從 Unicode 碼轉換成編碼前的特殊字符串。
          ???? * @param in Unicode編碼的字符數組。
          ???? * @param off 轉換的起始偏移量。
          ???? * @param len 轉換的字符長度。
          ???? * @param convtBuf 轉換的緩存字符數組。
          ???? * @return 完成轉換,返回編碼前的特殊字符串。
          ???? */
          ??? public String fromUnicode(char[] in, int off, int len, char[] convtBuf) {
          ??????? if (convtBuf.length < len) {
          ??????????? int newLen = len * 2;
          ??????????? if (newLen < 0) {
          ??????????????? newLen = Integer.MAX_VALUE;
          ??????????? }
          ??????????? convtBuf = new char[newLen];
          ??????? }
          ??????? char aChar;
          ??????? char[] out = convtBuf;
          ??????? int outLen = 0;
          ??????? int end = off + len;

          ??????? while (off < end) {
          ??????????? aChar = in[off++];
          ??????????? if (aChar == '\\') {
          ??????????????? aChar = in[off++];
          ??????????????? if (aChar == 'u') {
          ??????????????????? // Read the xxxx
          ??????????????????? int value = 0;
          ??????????????????? for (int i = 0; i < 4; i++) {
          ??????????????????????? aChar = in[off++];
          ??????????????????????? switch (aChar) {
          ??????????????????????? case '0':
          ??????????????????????? case '1':
          ??????????????????????? case '2':
          ??????????????????????? case '3':
          ??????????????????????? case '4':
          ??????????????????????? case '5':
          ??????????????????????? case '6':
          ??????????????????????? case '7':
          ??????????????????????? case '8':
          ??????????????????????? case '9':
          ??????????????????????????? value = (value << 4) + aChar - '0';
          ??????????????????????????? break;
          ??????????????????????? case 'a':
          ??????????????????????? case 'b':
          ??????????????????????? case 'c':
          ??????????????????????? case 'd':
          ??????????????????????? case 'e':
          ??????????????????????? case 'f':
          ??????????????????????????? value = (value << 4) + 10 + aChar - 'a';
          ??????????????????????????? break;
          ??????????????????????? case 'A':
          ??????????????????????? case 'B':
          ??????????????????????? case 'C':
          ??????????????????????? case 'D':
          ??????????????????????? case 'E':
          ??????????????????????? case 'F':
          ??????????????????????????? value = (value << 4) + 10 + aChar - 'A';
          ??????????????????????????? break;
          ??????????????????????? default:
          ??????????????????????????? throw new IllegalArgumentException(
          ??????????????????????????????????? "Malformed \\uxxxx encoding.");
          ??????????????????????? }
          ??????????????????? }
          ??????????????????? out[outLen++] = (char) value;
          ??????????????? } else {
          ??????????????????? if (aChar == 't') {
          ??????????????????????? aChar = '\t';
          ??????????????????? } else if (aChar == 'r') {
          ??????????????????????? aChar = '\r';
          ??????????????????? } else if (aChar == 'n') {
          ??????????????????????? aChar = '\n';
          ??????????????????? } else if (aChar == 'f') {
          ??????????????????????? aChar = '\f';
          ??????????????????? }
          ??????????????????? out[outLen++] = aChar;
          ??????????????? }
          ??????????? } else {
          ??????????????? out[outLen++] = (char) aChar;
          ??????????? }
          ??????? }
          ??????? return new String(out, 0, outLen);
          ??? }
          }

          posted @ 2006-10-28 20:53 leon 閱讀(10692) | 評論 (3)編輯 收藏

          [ad]city8升級預告

          9月26日(下周二),city8(www.city8.com)將進行一次升級。

          更新內容:

          1、上海的中環、外環以內的數據添加,這樣一來整個上海的數據就全了,大家想去哪,就可以看到哪了。

          ?2、三維實景窗口變大,看高樓不那么累了:)

          3、操作按鈕重新設計,這樣大家可以方便實現在街道中行走、全屏瀏覽等很酷的體驗。

          4、實景地圖分享:可以方便在地圖添加文字表述,如“我的家”,并通過msn,qq,blog,論壇等方式與他人分享

          界面先睹為快:

          首頁:
          homepage

          搜索結果頁面:
          main search

          posted @ 2006-09-23 14:25 leon 閱讀(477) | 評論 (2)編輯 收藏

          [tips]Java 中十進制十六進制相互轉換

          // 十進制轉化為十六進制,結果為C8。
          Integer.toHexString(200);

          // 十六進制轉化為十進制,結果140。
          Integer.parseInt("8C",16);

          posted @ 2006-09-19 12:02 leon 閱讀(18207) | 評論 (2)編輯 收藏

          [Image]使用 Java 2D 對圖像進行縮放

          ???? /**
          ?????*?縮放?-?參數指定目標圖縮放比例。
          ?????*?
          @param ?srcImage?源圖像對象。
          ?????*?
          @param ?xscale?圖像?x?軸(寬度)上的的縮放比例。
          ?????*?
          @param ?yscale?圖像?y?軸(高度)上的的縮放比例。
          ?????*?
          @param ?hints?重新繪圖使用的?RenderingHints?對象。
          ?????*?
          @return ?縮放后的圖像對象。
          ?????
          */

          ????
          public ? static ?BufferedImage?scaleJ2D(BufferedImage?srcImage,? double ?xscale,? double ?yscale,?RenderingHints?hints)? {
          ????????
          int ?width? = ?( int )?(( double )?srcImage.getWidth()? * ?xscale);
          ????????
          int ?height? = ?( int )?(( double )?srcImage.getHeight()? * ?yscale);
          ????????
          ????????AffineTransform?affineTransform?
          = ? new ?AffineTransform();
          ????????affineTransform.scale(xscale,?yscale);
          ????????
          if (hints? == ? null ) {
          ????????????hints?
          = ? new ?RenderingHints(RenderingHints.KEY_RENDERING,?RenderingHints.VALUE_RENDER_DEFAULT);
          ????????}

          ????????AffineTransformOp?affineTransformOp?
          = ? new ?AffineTransformOp(?affineTransform,?hints);
          ????????
          ????????BufferedImage?dstImage?
          = ? new ?BufferedImage(width,?height,?srcImage.getType());
          ????????
          ????????
          return ?affineTransformOp.filter(srcImage,?dstImage);
          ????}

          posted @ 2006-08-27 18:41 leon 閱讀(1223) | 評論 (1)編輯 收藏

          [Image]使用 Java 2D 將彩色圖像轉換成灰度圖

          ???? /**
          ?????*?將彩色圖像轉換為灰度圖。
          ?????*?
          @param ?srcImage?源彩色圖像。
          ?????*?
          @param ?hints?重新繪圖使用的?RenderingHints?對象。
          ?????*?
          @return ?目標灰度圖。
          ?????
          */

          ????
          public ? static ?BufferedImage?transformGrayJ2D(BufferedImage?srcImage,RenderingHints?hints)? {
          ????????BufferedImage?dstImage?
          = ? new ?BufferedImage(srcImage.getWidth(),?srcImage.getHeight(),?srcImage.getType());
          ????????
          ????????
          if ?(hints? == ? null )? {
          ????????????Graphics2D?g2?
          = ?dstImage.createGraphics();
          ????????????hints?
          = ?g2.getRenderingHints();
          ????????????g2.dispose();
          ????????????g2?
          = ? null ;
          ????????}

          ????????
          ????????ColorSpace?grayCS?
          = ?ColorSpace.getInstance(ColorSpace.CS_GRAY);
          ????????ColorConvertOp?colorConvertOp?
          = ? new ?ColorConvertOp(grayCS,?hints);
          ????????colorConvertOp.filter(srcImage,?dstImage);
          ????????
          ????????
          return ?dstImage;
          ????}

          posted @ 2006-08-27 14:33 leon 閱讀(1623) | 評論 (0)編輯 收藏

          [Image]使用 Java 2D 取得圖像上指定位置像素的 rgb 顏色分量

          ???? /**
          ?????*?取得圖像上指定位置像素的?rgb?顏色分量。
          ?????*?
          @param ?image?源圖像。
          ?????*?
          @param ?x?圖像上指定像素位置的?x?坐標。
          ?????*?
          @param ?y?圖像上指定像素位置的?y?坐標。
          ?????*?
          @return ?返回包含?rgb?顏色分量值的數組。元素?index?由小到大分別對應?r,g,b。
          ?????
          */

          ????
          public ? static ? int []?getRGB(BufferedImage?image, int ?x, int ?y) {
          ????????
          int []?rgb? = ? null ;
          ????????
          ????????
          if (image? != ? null ? && ?x? < ?image.getWidth()? && ?y? < ?image.getHeight()) {
          ????????????rgb?
          = ? new ? int [ 3 ];
          ????????????
          int ?pixel? = ?image.getRGB(x,y);
          ????????????rgb[
          0 ]? = ?(pixel? & ? 0xff0000 )? >> ? 16 ;
          ????????????rgb[
          1 ]? = ?(pixel? & ? 0xff00 )? >> ? 8 ;
          ????????????rgb[
          2 ]? = ?(pixel? & ? 0xff );
          ????????}

          ????????
          ????????
          return ?rgb;
          ????}


          使用這個方法前需要先將圖像文件從磁盤上讀到一個 java.awt.image.BufferedImage 對象中,我們可以用 J2SE 包含的 ImageIO 庫。

          try ? {
          ????BufferedImage?bi?
          = ?ImageIO.read( new ?File( " ?test.jpg? " ));
          }
          ? catch ?(IOException?ex)? {
          ????ex.printStackTrace();
          }

          posted @ 2006-08-16 10:55 leon 閱讀(2964) | 評論 (0)編輯 收藏

          胃痙攣

          胃痙攣,疼痛,瞬間失去意識。

          只剩觸覺,全身抽搐,十幾到幾十秒鐘后意識逐漸清晰,發現躺在地上。

          后遺癥是身體多處劃傷和脖子扭了。

          人生經驗:一大早不要喝冰可樂。

          posted @ 2006-07-03 12:06 leon 閱讀(21350) | 評論 (69)編輯 收藏

          [Download] Java 2 圖形設計卷Ⅰ:AWT

          Java2AWT_s.jpg
          Java 2 圖形設計卷Ⅰ:AWT
          Graphic Java 1.2 Mastering the JFC Volume Ⅰ:AWT
          [美]David M.Geary 著 馬欣民等譯
          機械工業出版社

          http://www.aygfsteel.com/Files/leon/Java2圖形設計卷1AWT.rar

          posted @ 2006-06-21 11:07 leon 閱讀(2089) | 評論 (9)編輯 收藏

          [zt] Swing是MVC設計的典范

          不管你的項目是否用到了Swing技術,我都要說,Swing是一個設計優秀的Java包,它充滿了大師的智慧。如果你學了Java卻連一個Button還不會寫,就象你學習Visual Basic卻不會用Button,那可絕對是不能被原諒的。Swing技術的應用已經在國外大行其道,由于java的免費、易學以及大家對于java技術的充分信賴,好多公司早早的就把應用程序的一切,從后臺服務到前臺人機交互界面,統統移到了java開發上。Swing出現了快10年了,憑借其先進的設計思想,一直未曾落后于哪種語言的界面開發技術,使用和理解Swing的設計思想,對軟件開發者大有裨益。

          Swing的設計是MVC的典范。雖然MVC的概念有點泛濫,可是真正能夠理解并熟練掌握、在設計和開發里面自然流露的并不多見。記得用VC++開發程序時候,MFC向導也是生成Document和View兩個類,當時一直奇怪為什么這么繞圈子。再看Swing的設計,則到處充滿了MVC的痕跡。仔細研究Swing中事件監聽、Model-View分離、Renderer/Editor機制、可插拔的LookAndFeel等機制,簡直就是一門藝術,充滿了美感。而如果你非常痛恨這些設計并覺得他們怪異,很可能你是剛從VB或者Delphi轉過來,這些快速開發工具幫助了你也“害”了你。

          Swing設計的不錯,不過可能過度學術化的設計也使得Swing跑起來并不靈巧,學習難度也大。這客觀上確實使得Swing一直沒有被廣泛使用,而且廣受詬病。記得以前“Swing有什么成功的應用嗎?”之類的帖子一直是熱門話題。IBM等則趁機抓住小辮子弄了SWT吸引了不少人,使得Java GUI技術面臨分裂的危險。

          不過隨著JAVA的不斷升級和優化,Swing的速度一直在提高,美觀性也在改善,基于Swing的成功應用也越來越多了。關于Swing是否消亡或被SWT代替或是否能作桌面應用的爭論逐漸少了。不過喜歡并精通Swing技術的開發者,尤其在國內,依舊非常少。

          好在情況在轉好。Sun正意識到Eclipse和SWT所帶來的威脅,下了大力氣發展NetBeans,其最新版本對Swing GUI可視化設計的支持已經超過了所有對手,其Rich Client框架也走向成熟,這對Swing的發展和應用是一個很大的推動。隨著WEB熱潮的減退,人們又更多的開始理性的思考B/S和C/S架構的選擇,某些領域Swing技術已經成為首選的解決方案。隨著JGoodies、JIDE、TWaver等優秀Swing產品的不斷涌現,Swing會以更快速度在桌面應用中普及。




          原文地址http://www.matrix.org.cn/resource/article/44/44417_Swing+MVC.html

          posted @ 2006-06-13 10:28 leon 閱讀(468) | 評論 (0)編輯 收藏

          [tips] Java中的四舍五入

          Java.lang.Math的round()方法返回的是整型,如果要保留小數位的話可以先乘以(小數位數 *? 10),使用Java.lang.Math的round()方法計算之后再除以(小數位數 *? 10)。

          ???? /**
          ?????*?浮點數的四舍五入。
          ?????*?
          @param ?f?float?代表源浮點數
          ?????*?
          @param ?digits?int?保留的小數點后位數
          ?????*?
          @return ?float
          ?????
          */

          ????
          public ? static ? float ?round( float ?f,? int ?digits)? {
          ????????
          float ?offset? = ?1f;
          ????????
          if ?(digits? == ? 0 )? {
          ????????????offset?
          = ?1f;
          ????????}
          ? else ? if ?(digits? > ? 0 )? {
          ????????????offset?
          = ?digits? * ?10f;
          ????????}
          ? else ? if ?(digits? < ? 0 )? {
          ????????????
          return ?f;
          ????????}


          ????????f?
          = ?java.lang.Math.round(f? * ?offset)? / ?offset;
          ????????
          return ?f;
          ????}

          posted @ 2006-06-07 11:50 leon 閱讀(509) | 評論 (1)編輯 收藏

          縱橫四海

          ?我喜歡的一張海報,一部電影。

          100分鐘的光影,一個縱橫四海的夢。

          英文片名卻叫做《Once A Thief》,曾經是個賊。Once,只一個單詞,埋葬了所有過往。


          OnecAThief.jpg

          posted @ 2006-06-03 20:45 leon 閱讀(319) | 評論 (0)編輯 收藏

          [tips] 獲取當前系統的所有可用字體

          ?//?返回一個數組,它包含此?GraphicsEnvironment?中所有可用字體的像素級實例。
          ?
          Font[]?fonts =?GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();

          //?返回一個包含此?GraphicsEnvironment?中所有字體系列名稱的數組,它針對默認語言環境進行了本地化,由?Locale.getDefault()?返回。
          ?
          String fontNames?=??GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();

          posted @ 2006-06-03 14:51 leon 閱讀(734) | 評論 (0)編輯 收藏

          [Image] 讀取數碼照片中的EXIF信息

          相信大家都有使用數碼相機拍照的經歷,一張數碼照片可以包含的內容遠遠超過了我們當前觀察到的景物,他可能包括攝影時的光圈、快門、ISO、日期時間等各種與當時攝影條件相關的訊息,相機品牌型號,色彩編碼,拍攝時錄制的聲音以及全球定位系統(GPS)等信息。這些信息都是存放在一個叫做Exif的文件里,然后把Exif文件放置在我們熟知的 JPEG/TIFF 文件的頭部,也就是說 EXIF 信息是鑲嵌在 JPEG/TIFF 圖像文件格式內的一組拍攝參數。

          我在網上找到一個開源的開發工具包Metadata-Extractor,使用它可以像ACDSee等圖像軟件一樣讀取數碼照片的Exif信息。

          我寫了一個小Demo程序演示通過使用metadata-extractor-2.2.2讀取數碼照片的Exif信息并從Exif中讀取圖像縮略圖。
          import?java.io.*;
          import?java.nio.*;
          import?java.nio.channels.*;
          import?java.util.*;

          import?com.drew.imaging.jpeg.*;
          import?com.drew.metadata.*;
          import?com.drew.metadata.exif.*;


          ?
          public?class?ExifExtractor?{
          ??
          public?ExifExtractor()?{
          ??}


          ??
          public?static?void?main(String[]?args)?{
          ????
          try?{
          ??????Metadata?metadata?
          =?JpegMetadataReader.readMetadata(new?File("o_P4140147.JPG.jpg"));

          ??????Iterator?directories?
          =?metadata.getDirectoryIterator();
          ??????
          while?(directories.hasNext())?{
          ????????Directory?directory?
          =?(Directory)?directories.next();

          ????????Iterator?tags?
          =?directory.getTagIterator();
          ????????
          while?(tags.hasNext())?{
          ??????????Tag?tag?
          =?(Tag)?tags.next();

          ??????????
          //?modify?Exif
          //??????????if?(tag.getTagName().equalsIgnoreCase("User?Comment"))?{
          //??????????????????????Directory?exifDirectory?=?metadata.getDirectory(ExifDirectory.class);
          //??????????????????????exifDirectory.setString(tag.getTagType(),?"LeonChen");
          //??????????}

          ??????????
          //?read?thumbnail
          ??????????if?(tag.getTagName().equalsIgnoreCase("Thumbnail?Data"))?{
          ????????????Directory?exifDirectory?
          =?metadata.getDirectory(ExifDirectory.class);

          ????????????
          byte[]?dataBuffer?=?exifDirectory.getByteArray(tag.getTagType());
          ????????????FileChannel?channel?
          =?new?RandomAccessFile(new?File("thumbnail.jpg"),
          ????????????????
          "rw").getChannel();
          ????????????MappedByteBuffer?fileBuffer?
          =?channel.map(FileChannel.MapMode.
          ????????????????READ_WRITE,?
          0,?dataBuffer.length);
          ????????????fileBuffer.put(dataBuffer);
          ????????????fileBuffer.force();
          ????????????channel.close();
          ??????????}


          ??????????
          //?print?exif
          ??????????System.out.println(tag);
          ????????}

          ??????}

          ????}

          ????
          catch?(FileNotFoundException?ex)?{
          ??????ex.printStackTrace();
          ????}

          ????
          catch?(IOException?ex)?{
          ??????ex.printStackTrace();
          ????}

          ????
          catch?(MetadataException?ex)?{
          ??????ex.printStackTrace();
          ????}

          ????
          catch?(JpegProcessingException?ex)?{
          ??????ex.printStackTrace();
          ????}

          ??}

          }


          我在上面的測試程序里注釋了一段代碼,他們可以在內存中修改Exif中某一節點的信息,但是我不知道怎樣才能將修改后的Exif信息保存到文件,如果你知道方法,請給我留言。

          測試圖片下載地址:
          http://www.aygfsteel.com/images/blogjava_net/leon/2174/o_P4140147.JPG

          EXIF參考:
          http://www.exif.org

          posted @ 2005-11-29 17:04 leon 閱讀(2595) | 評論 (5)編輯 收藏

          [Swing] 布局管理器 - OverlayLayout

          OverlayLayout是用于排列重疊組件的布局管理器。它的用途是以一些對齊的點為基準將一些組件層疊的放置在布局容器中。

          組件的橫軸和縱軸的對齊點介于0.0和1.0之間。橫軸(X軸)上0.0代表組件的左側面,1.0代表組件的右側面;縱軸(Y軸)上0.0和1.0分別代表組件的頂部和底部。

          構造函數
          public OverlayLayout(Container target)

          因為構造函數不會為target對象安裝結果布局管理器,所以我們還必須調用setLayout()來完成此功能。
          JPanel p1 = new JPanel();
          OverlayLayout overlay 
          = new OverlayLayout(p1);
          p1.setLayout(overlay); 

          在OverlayLayout布局管理器中,每個組件都有一對橫縱坐標值,每個組件的位置只和它本身的橫縱坐標值有關,換句話說就是組件以他自己的位置作為基準,橫軸上0.0和1.0分別代表組件的左側面和右側面;縱軸上0.0和1.0分別代表組件的頂部和底部,和容器位置無關。如果一個組件的alignmentX屬性設置為0.5,原本左側面的位置對應0.0,現在變成了0.5,那么,現在組件的位置就要向左移動width/2的距離,使左側面的位置對應現在的0.0。縱軸亦是如此,明白了嗎?

          為了容易理解,我們來看《Java Swing》中關于OverlayLayout的一段樣例程序,它可以編譯運行。如圖,你可以在輸入框中調節容器中3個按鈕的X,Y軸的值來看他們在容器中的位置是怎樣改變的,多試幾次,你就可以完全理解OverlayLayout。

          OverlayTest.jpg
          // OverlayTest.java
          // A test of the OverlayLayout manager allowing experimentation.
          //

          import java.awt.*;
          import java.awt.event.*;
          import javax.swing.*;

          public class OverlayTest extends JFrame {

              
          public OverlayTest() {
                  
          super("OverlayLayout Test");
                  setSize(
          500300);
                  setDefaultCloseOperation(EXIT_ON_CLOSE);

                  
          final Container c = getContentPane();
                  c.setLayout(
          new GridBagLayout());

                  
          final JPanel p1 = new GridPanel();
                  
          final OverlayLayout overlay = new OverlayLayout(p1);
                  p1.setLayout(overlay);

                  
          final JButton jb1 = new JButton("B1");
                  
          final JButton jb2 = new JButton("B2");
                  
          final JButton jb3 = new JButton("B3");

                  Dimension b1 
          = new Dimension(6050);
                  Dimension b2 
          = new Dimension(8040);
                  Dimension b3 
          = new Dimension(10060);

                  jb1.setMinimumSize(b1);
                  jb1.setMaximumSize(b1);
                  jb1.setPreferredSize(b1);
                  jb2.setMinimumSize(b2);
                  jb2.setMaximumSize(b2);
                  jb2.setPreferredSize(b2);
                  jb3.setMinimumSize(b3);
                  jb3.setMaximumSize(b3);
                  jb3.setPreferredSize(b3);

                  SimpleReporter reporter 
          = new SimpleReporter();
                  jb1.addActionListener(reporter);
                  jb2.addActionListener(reporter);
                  jb3.addActionListener(reporter);

                  p1.add(jb1);
                  p1.add(jb2);
                  p1.add(jb3);

                  JPanel p2 
          = new JPanel();
                  p2.setLayout(
          new GridLayout(2,6));
                  p2.add(
          new JLabel("B1 X", JLabel.CENTER));
                  p2.add(
          new JLabel("B1 Y", JLabel.CENTER));
                  p2.add(
          new JLabel("B2 X", JLabel.CENTER));
                  p2.add(
          new JLabel("B2 Y", JLabel.CENTER));
                  p2.add(
          new JLabel("B3 X", JLabel.CENTER));
                  p2.add(
          new JLabel("B3 Y", JLabel.CENTER));
                  p2.add(
          new JLabel(""));

                  
          final JTextField x1 = new JTextField("0.0"4); // Button1 x alignment
                  final JTextField y1 = new JTextField("0.0"4); // Button1 y alignment
                  final JTextField x2 = new JTextField("0.0"4); 
                  
          final JTextField y2 = new JTextField("0.0"4); 
                  
          final JTextField x3 = new JTextField("0.0"4); 
                  
          final JTextField y3 = new JTextField("0.0"4); 

                  p2.add(x1);
                  p2.add(y1);
                  p2.add(x2);
                  p2.add(y2);
                  p2.add(x3);
                  p2.add(y3);


                  GridBagConstraints constraints 
          = new GridBagConstraints();
                  c.add(p1, constraints);

                  constraints.gridx 
          = 1;
                  JButton updateButton 
          = new JButton("Update");
                  updateButton.addActionListener(
          new ActionListener() {
                      
          public void actionPerformed(ActionEvent ae) {
                          jb1.setAlignmentX(
                              Float.valueOf(x1.getText().trim()).floatValue());
                          jb1.setAlignmentY(
                              Float.valueOf(y1.getText().trim()).floatValue());
                          jb2.setAlignmentX(
                              Float.valueOf(x2.getText().trim()).floatValue());
                          jb2.setAlignmentY(
                              Float.valueOf(y2.getText().trim()).floatValue());
                          jb3.setAlignmentX(
                              Float.valueOf(x3.getText().trim()).floatValue());
                          jb3.setAlignmentY(
                              Float.valueOf(y3.getText().trim()).floatValue());

                          p1.revalidate();
                      }

                  }
          );
                  c.add(updateButton, constraints);

                  constraints.gridx 
          = 0;
                  constraints.gridy 
          = 1;
                  constraints.gridwidth 
          = 2;
                  c.add(p2, constraints);
              }


              
          public static void main(String args[]) {
                  OverlayTest ot 
          = new OverlayTest();
                  ot.setVisible(
          true);
              }


              
          public class SimpleReporter implements ActionListener {
                  
          public void actionPerformed(ActionEvent ae) {
                      System.out.println(ae.getActionCommand());
                  }

              }


              
          public class GridPanel extends JPanel {
                  
          public void paint(Graphics g) {
                      
          super.paint(g);
                      
          int w = getSize().width;
                      
          int h = getSize().height;

                      g.setColor(Color.red);
                      g.drawRect(
          0,0,w-1,h-1);
                      g.drawLine(w
          /2,0,w/2,h);
                      g.drawLine(
          0,h/2,w,h/2);
                  }

              }

          }



          最后提醒,使用OverlayLayout布局管理器關鍵要記住X,Y軸對應組件位置,和容器沒有關系。只要明白這一點,使用還是很簡單方便的,我用OverlayLayout布局管理器clone了一個PhotoShop的工具面板。
          ToolWidget.jpg

          posted @ 2005-11-02 23:08 leon 閱讀(3871) | 評論 (0)編輯 收藏

          [Image] 將屏幕截圖保存成圖像文件

          import ?java.io. * ;
          import ?java.awt. * ;
          import ?java.awt.image. * ;
          import ?javax.imageio. * ;

          public ? class ?CropScreen? {
          ??
          public ? static ? void ?main(String[]?args)? {
          ????
          try ? {
          ??????Toolkit?toolkit?
          = ?Toolkit.getDefaultToolkit();
          ??????Dimension?screenSize?
          = ?toolkit.getScreenSize();
          ??????Rectangle?screenRect?
          = ? new ?Rectangle(screenSize);

          ??????Robot?robot?
          = ? new ?Robot();
          ??????BufferedImage?image?
          = ?robot.createScreenCapture(screenRect);
          ??????ImageIO.write(image,?
          " jpg " ,? new ?File( " screen.jpg " ));
          ????}

          ????
          catch ?(Exception?ex)? {
          ??????ex.printStackTrace();
          ????}

          ??}

          }

          posted @ 2005-10-26 11:39 leon 閱讀(1268) | 評論 (0)編輯 收藏

          [Image] 使用JAI將實現RenderedImage接口的圖像對象序列化

          我們都知道,圖像對象可以編碼成指定圖像格式文件保存在硬盤上,需要時再對其進行解碼讀入內存。但是除了這樣還有別的辦法可以將圖像對象保存在硬盤上嗎?熟悉Java I/O 的人也許可以想到采用對象序列化(Object serialization)試一試,很好,但是如果你研究了 BufferedImage?類的結構后就會大失所望(至少當時我是這樣)。
          BufferedImage.jpg

          BufferedImage?提供一般圖像管理。BufferedImage 對象包括另外兩個對象:Raster 和 ColorModel。Raster 對象包含另外兩個對象:DataBuffer 和 SampleModel。不幸的是,他們都沒有實現序列化所必需的 Serializable 接口,所以無法直接對他們進行對象序列化。

          我在學習 JAI 的時候發現了 javax.media.jai.remote 包里有一個類 SerializableRenderedImage,這個類實現了RenderedImage, Serializable 接口,可以將 RanderedImage 對象作為構造函數的參數實例化一個可以序列化的圖像對象。

          javax.media.jai.remote.SerializableRenderedImage

          public final class SerializableRenderedImage
          extends Object
          implements RenderedImage, Serializable

          SerializableRenderedImage(RenderedImage?source)
          ??????????Constructs a SerializableRenderedImage wrapper for a RenderedImage source.
          SerializableRenderedImage(RenderedImage?source, boolean?useDeepCopy)
          ??????????Constructs a SerializableRenderedImage wrapper for a RenderedImage source.
          SerializableRenderedImage(RenderedImage?source, boolean?useDeepCopy, OperationRegistry?registry, String?formatName, TileCodecParameterList?encodingParam, TileCodecParameterList?decodingParam)
          ??????????Constructs a SerializableRenderedImage wrapper for a RenderedImage source.

          查看JDK的文檔可以知道無論 Java 2D 中的 BufferedImage 還是 JAI 中的 PlanarImage 都實現自 RenderedImage 接口,也就是說所有實現自 RenderedImage 接口的對象均可作為參數包裝出一個 SerializableRenderedImage 類型對象,將其序列化。

          下面是一個簡單的例子說明了這個類的使用方法:

          import?java.io.*;
          import?javax.media.jai.remote.*;

          import?java.awt.image.*;

          public?class?SomeSerializableClass
          ????
          implements?Serializable?{
          ??
          protected?transient?RenderedImage?image;

          ??
          //?Fields?omitted.

          ??
          public?SomeSerializableClass(RenderedImage?image)?{
          ????
          this.image?=?image;
          ??}


          ??
          //?Methods?omitted.

          ??
          //?Serialization?method.
          ??private?void?writeObject(ObjectOutputStream?out)?throws?IOException?{
          ????out.defaultWriteObject();
          ????out.writeObject(
          new?SerializableRenderedImage(image,?true));
          ??}


          ??
          //?Deserialization?method.
          ??private?void?readObject(ObjectInputStream?in)?throws?IOException,
          ??????ClassNotFoundException?
          {
          ????in.defaultReadObject();
          ????image?
          =?(RenderedImage)?in.readObject();
          ??}

          }

          posted @ 2005-10-18 17:36 leon 閱讀(2842) | 評論 (1)編輯 收藏

          [Image] AWT使用ImageProducer/ImagConsumer模式加載和顯示圖像的原理

          以前寫過2篇關于AWT中圖像加載顯示方法的文章,最近又多了一些對于 ImageProducer / ImagConsumer 模式的一些理解,嘗試著用文字總結了一下,接著還想再寫一篇介紹 AWT 中圖像過濾的原理和方法。你可能認為現在學習 AWT 中的成像方法對于開發中已經沒有太大的意義,因為已經有了 Java 2D 和 JAI ,但是我在實際工作中感到還是無法完全離開 AWT,特別是在一些基本的應用上。而且我覺得理解 AWT 的 Producer / Consumer (push) model 對于理解 Java 2D 的 Immediate mode model 和 JAI 的 Pipeline (pull) model 的都是有好處的。

          因為水平有限,這方面學習資料相對也不豐富,我也不知道我的理解或想法是否完全正確或者表述清楚,感興趣的朋友可以當作學習參考,希望能夠和我聯系進行進一步的討論。



          AWT 使用 ImageProducer / ImagConsumer 模式,支持加載和顯示 GIF 圖像文件格式和 JPEG 圖像文件格式。因為圖像的加載和顯示是異步方式進行的,所以有大量加載和顯示的技術。

          在 AWT 中,提供了一個 java.awt.Image 類。java.awt.Image 類代表一個圖像對象被作為參數傳遞給其他用來顯示和處理圖像的其他 AWT 對象使用。例如,通過調用 Graphics.drawImage(java.awt.Image, int, int, ImageObserver) 方法,可以在組件中畫出圖像。

          java.awt.Image 是一個定義方法的抽象類,它定義的方法提供的對圖像信息的訪問。而創建和處理圖像的基本結構則在 java.awt.image 包中。注意,這里不要和 java.awt.Image 發生混淆。

          AWT? 加載和顯示圖像使用的是 ImageProducer / ImagConsumer 模式,我們必須了解3個術語,ImageProducer(圖像生產者),ImageConsumer(圖像消費者)和ImageObserver(圖像觀察者)。

          ImageProducer 負責生產圖像的位,ImagConsumer 接受圖像的位,ImageObserver 監視 ImageProducer 的圖像生產過程。ImageProducer 生產傳遞給 ImagConsumer 與圖像相關的位。因為圖像生產過程是異步進行的,并不是一次性生產所有圖像位,所以當 ImageProducer 加載圖像時,ImageObserver 用來監視它的進展情況。因為 java.awt.Component 實現了 ImageObserver 接口,所以 AWT 中的每個組件都可以是ImageObserver,當一個給定的 ImageProducer 進行異步操作時,這個 ImageObserver 可以選擇是否被更新。java.awt.image 包為 ImageProducer,ImagConsumer 和 ImageObserver 都定義了接口。

          ImageProducer
          和圖像相關的位并不存儲在 java.awt.Image 中,每個圖像都維護一個和一個 ImageProducer?的關聯。這個 ImageProducer?的責任是生產圖像的位并將它們傳送給 ImagConsumer,用于過濾該圖像。

          java.awt.image軟件包中,FilteredImageSource(被過濾的圖像源)和 MemoryImageSource(內存的圖像源)實現了 ImageProducer? 接口,是 ImageProducer?。


          ImagConsumer
          java.awt.image軟件包中,ImageFilter(圖像過濾器)和 PixelGrabber(像素抓取器)實現了 ImagConsumer 接口,是 ImagConsumer。


          ImageProducer?和 ImagConsumer 的詳細介紹請閱讀 使用 ImageProducer? / ImagConsumer 進行圖像過濾


          ImageObserver
          ImageObserver接口中,定義了一個常數集合和一個方法:

          public boolean imageUpdate(image img, int flags, int x, int y, int width, int height);

          ImageObserver的常數
          標志 含義
          ABORT 圖像加載被中斷
          ALLBITS 所有的位都已加載給圖像
          ERROR 在加載過程中發生錯誤
          FRAMEBITS 多幀圖像的一個幀被傳送,一般用于GIF
          HEIGHT 圖像的高度已經可用
          PROPERTIES 圖像的屬性已經可用
          SOMEBITS 圖像的縮放變體的多個位已經可用
          WIDTH 圖像的寬度已經可用

          參數 flags 的作用是通知圖像觀察者圖像生產的進展情況。這些常數代表傳遞給 ImageObserver.imageUpdate() 的 flags 參數中的位。

          當 Component 作為 ImageObserver 時,一旦圖像有新的部分被加載,就會調用 Component.imageUpdate() 方法,imageUpdate() 再調用 repaint() 重新繪制圖像。repaint() 將先調用 update() 方法清除組件背景,再由 update() 方法調用 paint() 方法繪制圖像。我們可以通過重載 imageUpdate() 方法控制組件何時被更新,重載 update() 方法控制是否每次重繪都要清除背景圖像(每次重繪都清除背景圖像會造成畫面閃爍)。


          為了更好的理解,下面我們來看幾個樣例程序:

          例1,圖像位在需要之前不被生產

          import?java.net.URL;
          import?java.applet.Applet;
          import?java.awt.Graphics;
          import?java.awt.Image;

          public?class?ImageTestAppletSimple?extends?Applet{
          ????
          private?Image?im;
          ????
          ????
          public?void?init(){
          ????????URL?codebase?
          =?getCodeBase();
          ????????System.out.println(codebase);
          ????????
          ????????im?
          =?getImage(codebase,"flower.jpg");
          ????????
          ????????System.out.print(
          "Image?width?=?"?+?im.getWidth(this));
          ????????System.out.println(
          " hight?=?"?+?im.getHeight(this));
          ????}

          ????
          ????
          public?void?paint(Graphics?g){
          ????????g.drawImage(im,
          0,0,this);
          ????}

          }

          輸出結果:
          image width = -1 height = -1

          圖像的高度和寬度只有在圖像被完全加載后才是有效的,輸出結果說明 java.awt.image 相關的圖像位在需要之前不被生產。


          例2,圖像異步生產

          import?java.net.URL;
          import?java.applet.Applet;
          import?java.awt.Graphics;
          import?java.awt.Image;

          public?class?ImageTestAppletSimple2?extends?Applet{
          ????
          private?Image?im;
          ????
          ????
          public?void?init(){
          ????????im?
          =?getImage(getCodeBase(),"flower.jpg");
          ????}

          ????
          ????
          public?void?paint(Graphics?g){
          ????????System.out.println(
          "drawing?image...");
          ????????System.out.println(g.drawImage(im,
          0,0,this));
          ????}

          }

          輸出結果:
          drawing?image...
          false
          drawing?image...
          false
          drawing?image...
          false
          drawing?image...
          true

          輸出結果說明組件作為 ImageObserver ,監視 ImageProducer 異步生產圖像,一旦有新的圖像位被生產時就重繪圖像,圖像完全加載后 drawImage() 方法返回 true。


          例3,重載 ImageObserver 的 imageUpdate() 方法,在圖像完全加載前不調用 repaint()

          import?java.applet.Applet;
          import?java.awt.Graphics;
          import?java.awt.Image;

          public?class?ImageTestAppletWithUpdate?extends?Applet{
          ????
          private?Image?im;
          ????
          ????
          public?void?init(){
          ????????im?
          =?getImage(getCodeBase(),"flower.jpg");
          ????????
          ????????System.out.print(
          "Image?width?=?"?+?im.getWidth(this));
          ????????System.out.println(
          "hight?=?"?+?im.getHeight(this));
          ????}

          ????
          ????
          public?void?paint(Graphics?g){
          ????????g.drawImage(im,
          0,0,this);
          ????}

          ????
          ????
          public?boolean?imageUpdate(Image?image,int?flags,int?x,int?y,int?w,int?h){
          ????????System.out.println(
          "imageUpdate():x="?+?x?+?",y="?+?y?+?",w="?+?w?+?",h="?+?h);
          ????????
          ????????
          if((flags?&?ALLBITS)?==?0)
          ????????????
          return?true;
          ????????
          else
          ????????
          {
          ????????????repaint();
          ????????????
          return?false;
          ????????}

          ????}

          }



          例4,重載? Component.update() 方法,被調用時不清除背景圖像,直接調用 paint() 方法繪制圖像,消除閃爍

          import?java.applet.Applet;
          import?java.awt.Graphics;
          import?java.awt.Image;

          public?class?ImageTestAppletWithSmoothDynamicUpdate?extends?Applet{
          ????
          private?Image?im;
          ????
          ????
          public?void?init(){
          ????????im?
          =?getImage(getCodeBase(),"hl.jpg");
          ????????
          ????????System.out.print(
          "Image?width?=?"?+?im.getWidth(this));
          ????????System.out.println(
          "hight?=?"?+?im.getHeight(this));
          ????}

          ????
          ????
          public?void?paint(Graphics?g){
          ????????g.drawImage(im,
          0,0,this);
          ????}

          ????
          ????
          public?boolean?imageUpdate(Image?image,int?flags,int?x,int?y,int?w,int?h){
          ????????System.out.println(
          "imageUpdate():x="?+?x?+?",y="?+?y?+?",w="?+?w?+?",h="?+?h);
          ????????
          ????????repaint();
          ????????
          ????????
          if((flags?&?ALLBITS)?==?0)
          ????????????
          return?true;
          ????????
          else
          ????????????
          return?false;
          ????}

          ????
          ????
          public?void?update(Graphics?g){
          ????????paint(g);
          ????}

          }

          ?

          posted @ 2005-10-11 10:35 leon 閱讀(2633) | 評論 (3)編輯 收藏

          導航

          統計

          公告

          DSC_0106.jpg
          本博客已經搬家到CSDN
          http://blog.csdn.net/chenweionline




          常用鏈接

          留言簿(5)

          隨筆分類

          隨筆檔案

          About Technology

          My Favorite Website

          搜索

          積分與排名

          最新評論

          • 1.?re: 胃痙攣
          • 兄弟們你們都做胃鏡了嗎開的啥藥?有什么養胃秘方啊?請賜教啊!
          • --我也進來了
          • 2.?re: 胃痙攣
          • @痛啊
            我感覺比生孩子還疼,生孩子還能有意識呢!這種疼還叫不出來連說話的力氣都沒了
          • --我也進來了
          • 3.?re: 胃痙攣
          • 評論內容較長,點擊標題查看
          • --我也進來了
          • 4.?re: 胃痙攣
          • 我都周期性的發作,算來有4年了 。每年最少一次,一次最少2天。吃了好多藥就差沒去做胃鏡了。 剛剛發作就隨便煮了點姜湯喝下就好了些,不知道還會不會發作了。
          • --許家洛
          • 5.?re: 胃痙攣
          • 我昨晚也疼的要死。。上次疼的直接120送醫院了,一上120我竟然就不疼了,醫院里掉了瓶鹽水就放回家了。這次正好國外旅游中,幾乎疼了一整晚,整個在床上翻滾狀態了。今天不疼了,就是整個人難受。。。求助阿
          • --胃疼
          • 6.?re: [Swing]在 JFileChooser 中進行文件驗證的小技巧
          • 輸入*還是會有問題
          • --ngh
          • 7.?re: 胃痙攣[未登錄]
          • 昨晚一夜的身不如死的感覺,胃痙攣兄不要來了吧 ,求你了
          • --李飛
          • 8.?re: 胃痙攣
          • 評論內容較長,點擊標題查看
          • --daidai
          • 9.?re: 胃痙攣
          • 評論內容較長,點擊標題查看
          • --痛啊
          • 10.?re: 胃痙攣
          • 媽啊 痛的快死了~!第一次感覺過這樣的痛啊~!和女的生孩子有的一比了吧~!哭哭哭~!
          • --痛啊

          閱讀排行榜

          主站蜘蛛池模板: 原平市| 宜宾市| 定陶县| 鄄城县| 铁力市| 上虞市| 文成县| 独山县| 宜丰县| 乐业县| 儋州市| 盘山县| 营山县| 巩留县| 济阳县| 绵竹市| 高雄市| 肇东市| 利津县| 宝应县| 龙南县| 治县。| 长垣县| 洛阳市| 吐鲁番市| 酒泉市| 鄯善县| 黑河市| 托里县| 莒南县| 宿松县| 波密县| 惠安县| 鲜城| 云林县| 汉寿县| 新龙县| 康平县| 刚察县| 高邮市| 宜州市|