|
|
《JavaTM 程序设计语言 基础》第
2 部分 在《JavaTM 程序设计语言基础 - 第 1 部分》中,您已经掌握了如何使用 Java 基本类 (JFC)的Project Swing (Project Swing) 组件来创建具有基本功能的简单用户 界面。也掌握了如何使用远程方法调用(RMI)应用编程接口(API)把来自客户 机程序的数据发送给网络上的服务器程序,以供其它客户机程序访问。 本课采用 第 1 部分、第 8 课:远程方 法调用中的 RMI 应用程序创建一个更加复杂的用户界面,并使用一个不同的 布局管理器。这些改变为您提供了由两类客户机程序组成的非常简单的电子商务 应用的入门知识:第一个客户机程序让终端用户填交采购订单,第二个客户机程 序使用订单处理器查看订单。 关于示例程序的说明这是一个仅用来作为指导且非常简单的电子商务示例程序。它由三个程序组成: 两个客户程序(一个用于订购水果,另一个用于查看订单)和一个可供客户查看订 单信息的服务器程序。 水果订购客户程序FruitClient程序产生一个用户界面,用于提示终端用户订购单价为 1.25 美 元的苹果、桃和梨。
可利用 Tab 键或鼠标把光标移动到下一个文本域中。在界面底部,终端用户 可提供信用卡卡号和客户 ID 号。 终端用户点击 终端用户必需按下回车键才能更新累计值。如果没有按下回车键,通过网络传 输的订单累计值就不正确。本课最后要求您对程序进行修改,以便使终端用户即 使没有按下回车键,也不会有传输错误累计值的危险。 服务器程序
RemoteServer程序提供可远程访问的 查看订单的客户程序
OrderClient程序将创建一个用户界面,在终端用户点击 编译和运行示例程序第 1 部分、第 8 课:远程方法调用 中已介绍了如何运行示例程序。本课采用第 1 部分第 8 课中的说明,但采用本课 提供的源代码。以下是对这些运行步骤的综合说明: 编译: 以下这些指令假设开发工作是在 Unix: cd /home/zelda/classes javac Send.java javac RemoteServer.java javac RMIClient2.java javac RMIClient1.java rmic -d . RemoteServer cp RemoteServer*.class /home/zelda/public_html/classes cp Send.class /home/zelda/public_html/classes Win32: cd \home\zelda\classes javac Send.java javac RemoteServer.java javac RMIClient2.java javac RMIClient1.java rmic -d . RemoteServer copy RemoteServer*.class \home\zelda\public_html\classes copy Send.class \home\zelda\public_html\classes Start rmi Registry: Unix: cd /home/zelda/public_html/classes unsetenv CLASSPATH rmiregistry & Win32: cd \home\zelda\public_html\classes set CLASSPATH= start rmiregistry Start Remote Server: Unix: cd /home/zelda/public_html/classes java -Djava.rmi.server.codebase=http://kq6py/~zelda/classes -Djava.rmi.server.hostname=kq6py.eng.sun.com -Djava.security.policy=java.policy RemoteServer Win32: cd \home\zelda\public_html\classes java -Djava.rmi.server.codebase= file:c:\home\zelda\public_html\classes -Djava.rmi.server.hostname=kq6py.eng.sun.com -Djava.security.policy=java.policy RemoteServer Start RMIClient1: Unix: cd /home/zelda/classes java -Djava.rmi.server.codebase= http://kq6py/~zelda/classes/ -Djava.security.policy=java.policy RMIClient1 kq6py.eng.sun.com/~zelda Win32: cd \home\zeldzeldaa\classes java -Djava.rmi.server.codebase= file:c:\home\zelda\classes\ -Djava.security.policy=java.policy RMIClient1 kq6py.eng.sun.com\home\zelda\public\html Start RMIClient2: Unix: cd /home/zelda/classes java -Djava.rmi.server.codebase= http://kq6py/~zelda/classes -Djava.rmi.server.hostname=kq6py.eng.sun.com -Djava.security.policy=java.policy RMIClient2 kq6py.eng.sun.com Win32: cd \home\zelda\classes java -Djava.rmi.server.codebase= file:c:\home\zelda\public_html\classes -Djava.rmi.server.hostname=kq6py.eng.sun.com -Djava.security.policy=java.policy RMIClient2 kq6py.eng.sun.com 水果订购客户程序RMIClient1.java程序利用标签、文本域、文本区和按钮等组件创建订购水果 的用户界面。
终端用户在文本域中输入自己的水果订购数量,输入每一种水果的数量后都应 按下回车键。按下回车键后文本域操作就会更新文本区中显示的总数量和总费用。
实例变量以下几行程序声明了 JLabel col1, col2; JLabel totalItems, totalCost; JLabel cardNum, custID; JLabel applechk, pearchk, peachchk; JButton purchase, reset; JPanel panel; JTextField appleqnt, pearqnt, peachqnt; JTextField creditCard, customer; JTextArea items, cost; static Send send; int itotal=0; double icost=0; 构造函数构造函数特别长,这是因为它要创建所有程序组件、设置界面中两栏表格的布 局、把所有组件放置在面板上的表格中。面板是容纳其它组件的容器。
正如在 第
1 部分、第 4 课:创建用 户界面中所解释的那样,类用于对 //Create left and right column labels
col1 = new JLabel("Select Items");
col2 = new JLabel("Specify Quantity");
//Create labels and text field components
applechk = new JLabel(" Apples");
appleqnt = new JTextField();
appleqnt.addActionListener(this);
pearchk = new JLabel(" Pears");
pearqnt = new JTextField();
pearqnt.addActionListener(this);
peachchk = new JLabel(" Peaches");
peachqnt = new JTextField();
peachqnt.addActionListener(this);
cardNum = new JLabel(" Credit Card:");
creditCard = new JTextField();
customer = new JTextField();
custID = new JLabel(" Customer ID:");
//Create labels and text area components
totalItems = new JLabel("Total Items:");
totalCost = new JLabel("Total Cost:");
items = new JTextArea();
cost = new JTextArea();
//Create buttons and make action listeners
purchase = new JButton("Purchase");
purchase.addActionListener(this);
reset = new JButton("Reset");
reset.addActionListener(this);
以下程序行中,将创建一个 JPanel 组件并把该组件添加到顶级窗 体中,而且指定了布局管理器(layout
manager)和背景颜色。布局管理器确定 用户界面组件在面板上的布置。
第
1 部分、第 4 课:创建用户界面 中的示例程序采用了 布局管理器和颜色在面板中设置,通过调用 //Create a panel for the components panel = new JPanel(); //Set panel layout to 2-column grid //on a white background panel.setLayout(new GridLayout(0,2)); panel.setBackground(Color.white); //Add components to panel columns //going left to right and top to bottom getContentPane().add(panel); panel.add(col1); panel.add(col2); panel.add(applechk); panel.add(appleqnt); panel.add(peachchk); panel.add(peachqnt); panel.add(pearchk); panel.add(pearqnt); panel.add(totalItems); panel.add(items); panel.add(totalCost); panel.add(cost); panel.add(cardNum); panel.add(creditCard); panel.add(custID); panel.add(customer); panel.add(reset); panel.add(purchase); 事件处理
actionPerformed 方法完整显示外,本节对其它方法仅介 绍 purchase
按钮和 pearQnt 文本域的行为。Reset 按钮与 purchase
按钮类似,而其它文本域的操作也类似于 pearQnt。
Purchase 按钮:
if(source == purchase){
cardnum = creditCard.getText();
custID = customer.getText();
apples = appleqnt.getText();
peaches = peachqnt.getText();
pears = pearqnt.getText();
try{
send.sendCreditCard(cardnum);
send.sendCustID(custID);
send.sendAppleQnt(apples);
send.sendPeachQnt(peaches);
send.sendPearQnt(pears);
send.sendTotalCost(icost);
send.sendTotalItems(itotal);
} catch (Exception e) {
System.out.println("Cannot send data to server");
}
}
pearQnt 文本域: 文本域 pearQnt 的作用是: 获取终端用户欲订购的梨的数量,把得到的数据添加到总数量项中,用该数量计算所需费
用,然后再将其添加到总费用项中。本代码中有两个很有意义的作用:控制光标位置和把 字符串信息转换成计算所需要的数字信息。这两个方面都将在下文进行讨论。
if(source == pearqnt){
number = pearqnt.getText();
if(number.length() > 0){
pearsNo = Integer.valueOf(number);
itotal += pearsNo.intValue();
pearqnt.setNextFocusableComponent(creditCard);
} else {
itotal += 0;
pearqnt.setNextFocusableComponent(creditCard);
}
}
光标焦点终端用户可以在用户界面中利用 Tab 键把光标从一个组件移动到另一个组件。 Tab 键的默认动作是在包括文本区在内的所有用户界面组件之间逐步移动。 由于终端用户并不与文本区互操作,所以光标就不需要进入文本区。示例程序 中包含一个在其构造函数中对 applechk = new JLabel(" Apples");
appleqnt = new JTextField();
appleqnt.addActionListener(this);
pearchk = new JLabel(" Pears");
pearqnt = new JTextField();
pearqnt.addActionListener(this);
peachchk = new JLabel(" Peaches");
peachqnt = new JTextField();
peachqnt.addActionListener(this);
cardNum = new JLabel(" Credit Card:");
creditCard = new JTextField();
//Make cursor go to creditCard component
pearqnt.setNextFocusableComponent(creditCard);
customer = new JTextField();
custID = new JLabel(" Customer ID:");
把字符串转换成数值或相反若要计算订购数量及订购费用,就必须把从 字符串的值由 如果串长度值大于零,就会由串创建 if(number.length() > 0){
pearsNo = Integer.valueOf(number);
itotal += pearsNo.intValue();
} else {
itotal += 0;
}
若要显示各文本区的累计数量及费用总和,就必须把得到的总和值转换成字符串 的形式。方法 actionPerformed
末尾的程序代码就是用来完成这 一操作的。
若要显示总数量,就需要利用
num = new Integer(itotal); text = num.toString(); this.items.setText(text); icost = (itotal * 1.25); cost = new Double(icost); text2 = cost.toString(); this.cost.setText(text2);到目前为止,示例中使用的全部数据类型都已是类了。但是 int 和 double 这两种数据类型并不是类,它们是基本数据类型。
.
数据类型
数据类型 服务器程序代码服务器程序由
RemoteServer.java类组成。这些类实现在
Send.java接口中声明的方法。见第
1 部 分、第 8 课:远程方法调用,与在本课中的唯一不同是,需要声明和实现的
值得特别注意的是,任意类型和大小的数据都可以使用 RMI API通过服务器从 一个客户机传递到另一个客户机。不需要针对大量数据的特殊处理,也不需要对不 同数据类型作特别考虑,而这些因素在使用网络接口通信时,有时会成为需要考虑 的问题。 查看订单的客户程序OrderClient.java 类利用文本区和按钮来显示订单信息。
第一部分是检索信用卡号和通过服务器订购的苹果、桃和梨的数量,并把这些 值置于对应的文本区中。 第二部分是检索数据类型分别为 if(source == view){
try{
//Retrieve and display text
text = send.getCreditCard();
creditNo.setText(text);
text = send.getCustID();
customerNo.setText(text);
text = send.getAppleQnt();
applesNo.setText(text);
text = send.getPeachQnt();
peachesNo.setText(text);
text = send.getPearQnt();
pearsNo.setText(text);
//Convert Numbers to Strings
cost = send.getTotalCost();
price = new Double(cost);
unit = price.toString();
icost.setText(unit);
items = send.getTotalItems();
itms = new Integer(items);
i = itms.toString();
itotal.setText(i);
} catch (Exception e) {
System.out.println("Cannot send data to server");
}
}
程序的改进本部分示例程序对水果订购客户而言有两个主要的设计缺陷。第一,为了进行 计算必须按回车键;第二,要处理订购苹果、桃和梨时输入非数字字符所引发的 错误。 计算和按回车键: 如果输入苹果、桃和梨的数量值后终端 用户没有按下回车键而进下一文本域,程序就不会执行计算操作。也就是说,终 端用户点击 Purchase(购买)键后,订单被发送,但是所发送的订货数量和费用 并不正确。因此,在此特定的应用中,需要依赖于回车键动作事件的设计并不是 好设计。 应该对 非数字字符错误: 如果终端用户在苹果、桃或梨域中输入 了非数字值,程序发生栈跟踪,指示出现非法数字格式。一个好的程序应该能够 捕获并处理这类错误,以避免发生栈跟踪。 提示: 要求您的程序能够指出代码中哪一部分代码抛出错 误,并把所发生的错误封装在 在查看程序修改的参考 答案 前,请先亲自尝试。 更多信息在 Java 教程 的 编写事件监视程序 课中,您将看到有关事件监视的更多信息。 Java 教程 的 变量及数据类型 部分提供了基本数据类型的更详细说明。 有关 Project Swing 的详细说明见 JFC Swing 教 程:GUI 构造指南。 术语“Java virtual machine(Java 虚拟机)”和“JVM”在本网站中引 用时,是指 Java 平台虚拟机。 [TOP] |
|
||||||||||||||||||||||||||||||||||||