您的位置:首页 > 编程语言 > Java开发

JAVA 国际化基础知识(二)

2011-11-16 20:59 351 查看

输入法

实际上,以上所有讨论都涉及操作或显示数据。然而,必须以某种方式输入数据。对于最终用户,最常用的是键盘。但是,如果键盘不支持某种语言输入所需的字符,您该怎么办呢?

输入法(Inputmethod)是允许数据输入的软件组件的一个技术术语。Java平台既允许使用主机OS输入法也允许使用基于Java语言的输入法。如果您需要实现输入法,您可以使用输入法框架(InputMethodFramework)。您可以在JDK文档中Internationalization一节中的InputMethodFramework(可以从参考资料中访问该文档)中找到输入法客户机
API(InputMethodClientAPI)及输入法引擎SPI(InputMethodEngineSPI)的规范、参考和教程

Unicode与Java字符

Java字符与char数据类型

Java程序员的一个最知名的抱怨是“我只看到程序输出是问号(或方块),我的数据是怎么被破坏的呢?”通常,作为Java开发人员,您应该理解实际发生了什么以及这一表面问题后面的原因,而这种知识在处理国际化问题时尤为重要。

Java语言规范(JavaLanguageSpecification)将char定义为原始的、数值型和整型的类型。此外,char是唯一的无符号(unsigned)数字类型,它允许一些有趣的(或讨厌的,这取决于您的观点)窍门。char在另一方面也十分特殊,因为将它们送到诸如显示器或打印机的输出设备时,会将其值从字符映射或字体映射成字形。然而,从根本上来说,char是数值类型,支持所有整数运算。因此Unicode支持注释道:可以使用字母或
Unicode转义符设置char。因为char是数值型,所以您也可以使用八进制、十进制或十六进制表示法甚至反转位来赋值。

假设出现上述情况并假定没有程序错误,上面问题的答案是:字符映射或字体不支持该字符,显示问号或方块来作为替代。该char本身的值仍然有效。但是,这样您就不能可视地验证数据;您不得不核对数值。下面的示例显示了这一行为。

这幅图像显示了日本象形文字中的“Go”或5,以Unicode表示为‘\u4E94’。该字符导致在下面的charExample程序中显示成问号和方块:

importjavax.swing.*;


publicclasscharExample

{

publicstaticvoidmain(String[]args)

{

booleanbFirst=true;

charaChar[]={

'A',//character

65,//decimal

0x41,//hex

0101,//octal

'\u0041'//Unicodeescape

};


charmyChar=256;


for(inti=0;i<aChar.length;i++)

{

System.out.print(aChar[i]+++"");

if(i==(aChar.length-1))

{

System.out.println("\n---------");

if(bFirst)

{

i=-1;

bFirst=!bFirst;

}

}

}//endfor

//theresultofaddingtwocharsisanint

System.out.println("aChar[0]+aChar[1]equals:"+

(aChar[0]+aChar[1]));

System.out.println("myCharat256:"+myChar);

System.out.println("myCharat20116or\\u4E94:"+

(myChar=20116));

//showintegervalueofthechar

System.out.println("myCharnumericvalue:"+

(int)myChar);


JFramejf=newJFrame();

JOptionPane.showMessageDialog(jf,

"myCharat20116or\\u4E94:"+

(myChar=20116)+

"\nmyCharnumericvalue:"+

(int)myChar,

"charExample",JOptionPane.ERROR_MESSAGE);


jf.dispose();

System.exit(0);


}//endmain


}//EndclasscharExample


首先,程序用字母“A”的各种表示法初始化一个char数组,并将一个char变量设置成256(‘\u0100’)。程序在一个循环中打印两次数组的值。打印之后递增每个元素的值(char是数值型,记得吗?)。接下来,将头两个元素加到一起,然后打印其结果(int)。然后,打印char变量,首先用其初始值,然后用值20116或‘\u4E94’,它是5的日本象形文字“Go”。如预期的那样在使用代码页cp1252的WindowsNT上,会在显示器上将这两个值打印成问号。根据您的系统使用的代码页,显示可能略微有些不同。要核查其值,接下来将变量作为int打印。最后,JOptionPane显示其值,对于不受支持的char‘\u4E94’,它显示一个方块。

下面是charExample的输出:

AAAAA

---------

BBBBB

---------

aChar[0]+aChar[1]equals:134

myCharat256:?

myCharat20116or\u4E94:?

myCharnumericvalue:20116


JOptionPane显示:

字体、字体特性及Lucida字体

Java平台既识别逻辑字体也识别物理字体。

逻辑字体是那些被映射到主机系统字体的字体。比如人们熟悉的Serif、Sans-serif、Monospaced、Dialog以及DialogInput字体。还有四种逻辑字体样式:普通、粗体、斜体及粗斜体。使用一个位于JRE/lib目录下的font.properties文件来实现主机字体到逻辑字体的映射。尽管细节因系统而异,但是缺省font.properties文件通常设置成英语环境,虽然JDK也有一个本地化日语版本可用。还提供了另外的font.properties文件;JDK1.3.1
Windows版包含阿拉伯语、希伯来语、日语、韩国语、俄语、泰国语字体文件以及中文的几种版本的字体文件。就象命名约定一样,搜索适当的font.properties同用于ResourceBundle的方法类似(但不全相同)。如果特定于语言的font.properties文件同您的系统的语言环境相匹配,并且安装了期望的字体(通常随OS的那一版本一起提供),那么就会对该语言进行自动映射。否则,就使用缺省的(通常是英语)文件映射。

如果您安装了适当的字体并且在调用Java应用程序时传入了相应的语言及国家或地区代码,那么也会进行自动映射。如果期望的font.properties文件存在,那么这种行为对开发非常有用。也可以将最初的缺省font.properties文件拷贝到别的地方,然后将特定文件重命名为“font.properties”,通过这样来将该语言/字体有效地设置成缺省情况。虽然对于开发人员来说很容易,但这显然不是最终用户非得做的事情。

如果您必须亲自定制或创建一个新的font.properties文件,那就完全是另一回事,而且更难。可以在JDK文档Internationalization一节中的FontProperties中找到处理font.properties文件的指示信息。

物理字体是我们始终在使用的正常字体。基于ASCII和ISO8859-1的字体不会有问题。然而,一旦超出这一范围,主机平台显然必须理解它们,并且必须对它们进行Unicode编码以使之能够用于您的Java程序。找到这些字体不象以前那么难了。例如,WindowsMSMinchoTrueType字体(主要是日语)是Unicode编码的,可以以标准方式立即投入使用。当在系统上装入了适当的物理字体时,您可以让用户选择他们想要的字体并保存他们的首选项,或者将该字体设置成整个软件包的标准字体,而不用进入
font.properties文件。

Java2SDK还提供三种物理字体系列:LucidaSans、LucidaBright和LucidaSansTypewriter。每一系列都含有四种字体―分别用于普通、斜体、粗体以及粗斜体样式―总计12种字体。虽然关于这些字体的确切功能的信息极为稀少,但LucidaSans字体处理大多数欧洲和中东语言。不包括亚洲语言。由于该字体随JDK一起提供,因此教程中的所有图形应用程序示例都使用LucidaSans字体。更多信息,请参阅JDK文档Internationalization一节中的Physical
Fonts(可以从参考资料访问)。

提供本地化的资源

创建语言环境

提供任何类型的本地化资源时,您应该做的第一件事情是创建一个适当的语言环境(参阅语言环境)。虽然有一个包含平台/浏览器变体的构造器,但通常您将使用

Localel=newLocale(Stringlanguage,Stringcountry);
其中,language是由ISO-639定义的小写、两字母代码,country是一个由ISO-3166定义的大写、两字母代码。

下面是用于特定于德国的德语语言环境:

Localel=newLocale("de","DE");
Locale有一个返回受支持的语言环境数组的staticgetAvailableLocales()方法。实际上,所有与语言环境相关的Java2PlatformAPI都有一个getAvailableLocales()方法,您可以期望它返回一致的值。其它有用的方法是staticgetDefault(),它返回缺省的语言环境,以及getDisplayName()和getDisplayName(LocaleinLocale)方法,它们分别用缺省或所请求的语言环境语言来返回适于显示的名称。您也可以获取国家或地区以及语言的代码和名称。这些方法允许没有特定语言知识的程序员为最终用户提供读、选择以及返回本地化的语言环境信息的能力。

使用资源束

ResourceBundle包含键/值结合。键总是String,而值总是PropertyResourceBundle中的String,但可以是ListResourceBundle中的任何对象或定制子类。如果没有找到请求的资源,那么ResourceBundle访问方法会抛出一个MissingResourceException。

参阅本地化的资源以获得更多常规信息。本教程将集中于PropertyResourceBundle,因为它们适合于大多数情形,并且易于生成和修改而无须编写任何新代码。

ResourceBundle.getBundle(StringbaseName)和ResourceBundle.getBundle(StringbaseName,Localelocale)提供一种内置的搜索机制,当这些束的结构恰当时,这种机制工作得非常好。正常的搜索从base_language_country_variant到base_language_country,再到base_language,最后到base。注:如果请求一个特定的、非缺省的语言环境,并且同资源一起存在一个缺省的语言环境束,那么搜索将会停在那儿而不是继续搜索到基础束。我们的示例程序(参阅PropertyResourceBundle代码示例)支持英语、法语、德语和俄语并使用PropertyResourceBundle。支持的
.properties文件被命名为:

·ByTheNumbersrb.properties

·ByTheNumbersrb_de.properties

·ByTheNumbersrb_en.properties

·ByTheNumbersrb_fr.properties

·ByTheNumbersrb_ru.properties

所有文件都含有全部所需资源。英语用作缺省值,ByTheNumbersrb.properties和ByTheNumbersrb_en.properties是相同的。这种做法略微有些偏离传统认知,即:对于基础缺省语言,不需要专门命名的.properties文件,因此我们不需要ByTheNumbersrb_en.properties。然而,当一段特定信息使用非缺省语言环境时,这种设置却是必需的,我们的示例程序就是这种情形。假定一个英语语言环境将被用来在一台法语为缺省语言环境机器上显示某项。如果_fr
束中存在相同的键,_en搜索失败时,将会选择该值。这完全不是所请求的或所期待的那样。如果在程序的任意一次给定运行中只使用一种语言环境,那么专门命名的副本就不是必需的。但无论如何,在任何情况下这种做法都不需要新的代码并且起作用。

如果我们需要更特定的语言环境支持,例如奥地利语、瑞士语和德语(分别是_de_AT、_de_CH和_de_DE),那么只将国家或地区细节置于以适当的国家或地区命名的特性文件(例如,myprops_de_CH.properties)中,而将更一般的元素置于_de束级别,这样做会很有意义。在那种情形下,需要其它元素时,将总能找到_de束。

您也应该为束实现几种命名约定。我们的示例使用这种通用格式:Object.getClass().getName()+"rb"。主要规则是:对于.properties文件,不要只使用类名称作为其基础名称。忽视该规则在有些平台上照样能行,但在其它一些平台上您会大吃一惊。记入文档的准则是:如果类和具有相同名称的.properties文件同时存在,那么被选中和装入的将是类。就是这样。这一行为的一个好结果是:使用适当命名的束,您可以在ListResourceBundle和PropertyResourceBundle之间转换,而不用更改代码;只要将期望的类型移到类路径即可。

您可能会发现让不同的信息类型具有多个ResourceBundle更加合适。它们可以为许多不同的程序提供资源。特定的前缀或后缀约定对于避免类名冲突仍然有用。

使用PropertyResourceBundle

PropertyResourceBundle的语义同其父束ResourceBundle的语义相同。不同之处在于数据存储的位置。PropertyResourceBundle由符合Properties约定的.properties文件支持。下面是创建文件所要知道的内容:

·文件被格式化为ISO8859-1编码的基本文本,因此您可以使用任何编辑器来创建和编辑文件。

·以#开头的行是注释。

·每个资源以key=value的形式被设置成键/值对。

·文件扩展名必须是.properties。名称必须遵守下列格式,其中language由ISO-639定义,country由ISO-3166定义(参阅创建语言环境):

1.baseName.properties

2.baseName_language.properties

3.baseName_language_country.properties

4.baseName_language_country_variant.properties

下面是ByTheNumbersrb_en.properties的一个示例项:

1=One:
下面是ByTheNumbersrb_ru.properties的一个示例项:

1=\u041E\u0434\u0438\u043D:
上面两个示例中的冒号实际上是值的一部分而不是所需的项。注:一旦我们超越了ISO8859-1而进入其它Unicode范围,我们必须使用JavaUnicode转义。您可以使用JDKnative2ascii工具来从不同编码进行转换。

PropertyResourceBundle代码示例

显示在右侧的ByTheNumbers示例使用俄语语言环境―ru_RU。

ByTheNumbers.java(参阅ByTheNumbers.java:PropertyResourceBundle示例)以几种不同的语言显示数字0到10的名称。进入时,将缺省的语言环境同支持的语言环境(英语、法语、德语和俄语)相比较。如果缺省语言环境与其中的某一种不匹配,那么就将英语选做缺省,将基础ResourceBundle用于资源;否则,使用缺省语言环境ResourceBundle。通过使用缺省语言环境获得支持的语言的语言环境显示名称(Locale
DisplayName),并将其装入JComboBox。用户可以键入适当名称的号码然后按OK。程序验证这些输入项并显示祝贺消息或重试消息。我们提供一个按钮以随机顺序显示号码名称。用户可以从JComboBox选择任何语言,并且字段初始将以数值顺序显示选中的语言。程序使用LucidaSans字体,因此可以正确地显示所有受支持的语言。遗憾的是,我们的翻译还没有返回我们对标题翻译的请求,因此“title=Keyinnumberstomatchthewords:”键/值对仅仅出现在基础名称文件中,它给了我们一个机会,让我们明白不位于层次结构较低位置的键可以在祖先文件中找到。

要运行该程序,使用下列任意一条命令:

ljavaByTheNumbers//如果支持缺省语言环境,就使用它,否则,就使用英语。

ljava-Duser.language=de-Duser.region=DEByTheNumbers//德语

ljava-Duser.language=en-Duser.region=USByTheNumbers//英语

ljava-Duser.language=fr-Duser.region=FRByTheNumbers//法语

ljava-Duser.language=ru-Duser.region=RUByTheNumbers//俄语

下面显示了五个.properties文件中的两个:

ByTheNumbersrb.properties(与ByTheNumbersrb_en.properties相同)

#DefaultpropertiesinEnglish
0=Zero:
1=One:
2=Two:
3=Three:
4=Four:
5=Five:
6=Six:
7=Seven:
8=Eight:
9=Nine:
10=Ten:
random=Random
title=Keyinnumberstomatchthewords:
ByTheNumbersrb_ru.properties

#DefaultpropertiesinRussian
0=\u041D\u0443\u043B\u044C:
1=\u041E\u0434\u0438\u043D:
2=\u0414\u0432\u0430:
3=\u0422\u0440\u0438:
4=\u0427\u0435\u0442\u044B\u0440\u0435:
5=\u041F\u044F\u0442\u044C:
6=\u0428\u0435\u0441\u0442\u044C:
7=\u0441\u0435\u043C\u044C:
8=\u0412\u043E\u0441\u0435\u043C\u044C:
9=\u0414\u0435\u0432\u044F\u0442\u044C:
10=\u0414\u0435\u0441\u044F\u0442\u044C:
random=\u041D\u0430\u0443\u0433\u0430\u0434

PropertyResourceBundle代码示例:I18N详细信息

让我们看一看同I18N有关的代码部分。首先,建立支持的语言环境和ResourceBundle基础名称。
Locale[]alSupported={
Locale.US,
Locale.FRANCE,
Locale.GERMANY,
newLocale("ru","RU")
};
...

StringsRBName=getClass().getName()+"rb";
接下来,使用与OK按钮的字体相同的样式和大小创建LucidaSans字体,然后获得缺省语言环境语言所支持的语言的显示名称(DisplayNames)。此外,对缺省语言环境进行比较以确定是否支持它。如果不支持,英语数字将是首先被显示的集合。

FontfJB=jbOK.getFont();
fLucida=newFont("LucidaSans",
fJB.getStyle(),
fJB.getSize());

...

asDNames=newString[alSupported.length];
LocalelDefault=Locale.getDefault();
for(i=0;i<alSupported.length;i++)
{
asDNames[i]=
alSupported[i].getDisplayName();

if(iSelIndex==0&&
lDefault.equals(alSupported[i]))
{iSelIndex=i;}
}//endfor
接下来,在一个循环中创建JLabel和JTextField并将它们装入数组。设置每个JLabel的Font和Name。一旦构建了数组,就调用loadFromResourceBundle()来设置每个JLabel的文本值。接下来设置本地化jbRandom按钮和标题文本。请注意,这两个组件的属性只设置了一次,这是典型程序中所有组件的正常情况,在那里,语言环境在给定的运行期间不会改变。

jlTemp.setFont(fLucida);
jlTemp.setName(i+"");//setName
...
loadFromResourceBundle();//getlocalizedlabels
...
jbRandom.setFont(fLucida);
jbRandom.setText(rb.getString("random"));
...
jlTemp=newJLabel(rb.getString("title"));
jlTemp.setFont(fLucida);
下面是loadFromResourceBundle()方法,它使用选中的语言环境访问适当的ResourceBundle。使用JLabel.Name属性作为getString(Stringkey)的键来设置JLabel的文本。如果没有找到特别的资源,就显示一个错误对话框。从JComboBox选择语言时,也会调用这一方法。

publicvoidloadFromResourceBundle()
{
try
{//getthePropertyResourceBundle
rb=ResourceBundle.getBundle(
sRBName,
alSupported[iSelIndex]);
//getdataassociatedwithkeys
for(inti=0;i<sfiSIZE;i++)
{
aiOrder[i]=i;
ajl[i].setText(rb.getString(ajl[i].getName()));
}
bRandomize=false;
}//endtry
catch(MissingResourceExceptionmre)
{
JOptionPane.showMessageDialog(this,
"ResourceBundleproblem;\n"+
"Specificerror:"+mre.getMessage(),
"",JOptionPane.ERROR_MESSAGE);
}
}//endloadFromResourceBundle
同样,有关完整的程序清单及所有.properties文件的内容,请参阅ByTheNumbers.java:PropertyResourceBundle示例。

使用日期、数字和货币

日期、数字和货币

对于任何那些从未出过国,或从未接触过日期、数字和货币的“外国”用法的人来说,格式化和解析日期、数字和货币显得很简单。毕竟,所有人都能理解lundi1avril2002或至少4.1.02的月和日部分,对吗?虽然我们极少有人能实际以150,75购买321500,7项东西,但我们能够很容易地理解以欧元表示的价格有多少项。或者可能不是这样。这些示例看起来可能不典型,但他们确实发生了,并且表示了为什么非本国人在理解本国的日期、数字和货币格式方面经常会有问题。

结果是,全世界使用的日期有各种各样的顺序和符号。数字和货币也是如此。此外,货币符号可能不止一个字符,它可能出现在值的前面或后面,和值之间有或没有空格。在大多数编程语言中,您几乎总是靠自己来处理这些情形。但JavaAPI却能够处理每个受支持语言环境的所有的不同格式。而且,通过使用DateFormatSymbols和DecimalFormatSymbols类,您可以获得诸如这样的信息:本地化的长短月日名称、十进制与货币分隔符以及货币与百分比符号。

API文档鼓励您为I18N应用程序使用抽象父类DateFormat和NumberFormat的getInstance()和getXXXInstance()方法。从1.3(和1.4)参考实现起,分别返回SimpleDateFormat和DecimalFormat的实例。两个类都有缺省的模式与符号用于格式化和解析,并且还允许定制。

下面几页中的示例程序都使用缺省模式来帮助您理解它们是怎样工作的。您将看到:由于API设计的缘故,三个示例中的代码都非常相似。从最终用户的观点,它们也非常相似:以本机语言环境提供一个输入域。当用户按下OK按钮时,就在表示用户选择的语言环境和标准解析的“原始”值的单独域中显示值。这三个示例都将处理由JDKAPI支持的所有语言环境。LucidaSans字体用于所有显示。“ToggleDisplayNames”按钮将语言环境名称的显示从用户的本机语言切换为特定语言环境的本机语言。当字体中没有用于本地化显示名称的第一个字符的字形时,“
-fontcan'tdisplay.”就被附加到下拉框中的语言环境名称上。程序仍然会工作,但在那种情况下,您可能会看到输出的某些部分是您熟悉的方框或问号。

使用下面的命令调用程序:

javaAppName
由于支持所有API语言环境,您也可以使用下列命令调用它们

java-Duser.language=lc-Duser.region=ccAppName
其lc是API支持的语言环境的ISO-639语言代码,cc是API支持的语言环境的ISO-3166国家或地区代码,以使输入格式化成该语言环境的样式。

注:由于要访问整个语言环境显示名称集,这些应用程序将比正常情况要花费更长的时间来启动。

日期格式化示例

这个JIBDateGUI示例使用德语作为缺省语言环境―de_DE。

JIBDateGUI(参阅JIBDateGUI.java:DateFormat示例)允许用户以其本地的格式输入日期。输入时确定本地语言环境,并且该语言环境显示在OK按钮的旁边。当用户按下OK时,则解析输入数字并以选中的语言环境显示该数字。还以ISO格式对该值进行单独解析和显示。可能使用参数“full”、“long”、“medium”或“short”调用程序。如果没有发送参数或者发送了这四个参数之外的其它参数,那么就使用“short”。这些值对应于DateFormat.FULL、DateFormat.LONG、DateFormat.MEDIUM和DateFormat.SHORT,并且被用来以选中的样式创建DateFormats。

程序通过定义缺省和选中的DateFormats和locales开始。java.sql.Date被初始化成显示标准ISO日期值的当前日期(注:没有为该示例对日期进行标准化),然后定义Lucida字体、缺省语言环境、支持的语言环境的数组以及本机和本地化的语言环境显示名称。

DateFormatdfLocal,
dfSelected;

java.sql.DatejsqlDate=newjava.sql.Date(
System.currentTimeMillis());

FontfLucida;
...
LocalelDefault=Locale.getDefault();
Locale[]alSupported;

String[]asDNames,
asLDNames;
在构造器中,创建了LucidaSans字体并将其赋给显示域。捕获请求的样式并创建缺省DateFormat。接下来,同时以缺省和本地化格式收集所有可用的显示名称。由Font.canDisplay()检查每个本地化显示名称的第一个字符;如果返回false,那么“-fontcan'tdisplay.”就被附加到该名称后面。如果JavaAPI支持缺省语言环境,那么相应的显示名称就会被选中;否则就选中第零行。此外,使用java.sql.Date的值设置和格式化输入域。DateFormat.setLenient(false)被应用到缺省DateFormat并且获取缺省显示名称以供显示。

FontfJCB=jbToggle.getFont();
fLucida=newFont("LucidaSans",
fJCB.getStyle(),
fJCB.getSize());

iFormat=argiFormat;
dfLocal=DateFormat.getDateInstance(
iFormat);

alSupported=Locale.getAvailableLocales();
asDNames=newString[alSupported.length];
asLDNames=newString[alSupported.length];
for(inti=0;i<alSupported.length;i++)
{
asDNames[i]=
alSupported[i].getDisplayName();

s1=
alSupported[i].getDisplayName(alSupported[i]);
if(fLucida.canDisplay(s1.charAt(0)))
{asLDNames[i]=s1;}
else
{asLDNames[i]=s1+"-fontcan'tdisplay.";}

if(iSelIndex==0&&
lDefault.equals(alSupported[i]))
{iSelIndex=i;}
}//endfor
...
jtI.setText(dfLocal.format(jsqlDate));
...
dfLocal.setLenient(false);
...
JLabeljlTemp=newJLabel("Default="+
lDefault.getDisplayName());
jlTemp.setFont(fLucida);
在ActionListener(actionPerformed()方法)中为显示名称JComboBox(jcb)处理所有其它I18N功能:根据选择项,创建新的DateFormat并清空显示域。如果在下一节中出现了任何错误,对话框将显示ParseException消息。代码试图从输入解析java.util.Date并使用缺省DateFormat对其重新进行格式化以供输出。接下来,格式化选中的DateFormat的显示。最后,解析该值并用它来创建java.sql.Date,java.sql.Date被用来显示
ISO值。

if(oSource==jcb)
{
dfSelected=DateFormat.getDateInstance(
iFormat,
alSupported[jcb.getSelectedIndex()]);
}//endifjcb,continueon

jtD.setText("");
jtP.setText("");

try
{
java.util.Dated=dfLocal.parse(
jtI.getText());
jtI.setText(dfLocal.format(d));
jtI.setCaretPosition(0);
jtD.setText(dfSelected.format(d));
jtD.setCaretPosition(0);
d=dfSelected.parse(jtD.getText());
//getnewjava.sql.Date
jsqlDate=newjava.sql.Date(d.getTime());

jtP.setText(jsqlDate.toString());
}
catch(ParseExceptionpe)
{
JOptionPane.showMessageDialog(this,
pe.getMessage(),"",JOptionPane.ERROR_MESSAGE);
}
同样,JIBDateGUI.java:DateFormat示例上列出了完整的程序。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: