| 分类: 大学实验报告 |
一、实验目的和要求
1. 掌握基本GUI部件的使用
2. 理解并掌握GUI事件驱动的程序设计
3. 理解并掌握MVC(模型-视图-控制器)模式
二、实验内容和原理
| http://s10/middle/6ea6cd6a496503bc82109&690 |
采用MVC的方式重新实现地址薄维护程序。界面如图1所示:
图1 地址薄应用程序的用户界面
MVC三者之间的关系可参考图2。视图类AddressBookJFrame中的方法setAddress用于将参数的值在界面上显示,而方法getAddress()用于将界面上的值生成一个Address类型的对象。在控制器AddressBookController中有相应的实现了ActionListerner接口的类(如图3),用来侦听视图中相应命令按钮的事件,视图中的一类add方法(如addAddActionListerner)用于注册侦听器。对模型,书中的例子是用随机访问文件,你可以使用数据库,通过JDBC建立与数据库的连接;也可以用顺序文本文件,先把文件读入到一个Collection(如ArrayList)中,再在从集合上读指定位置记录,或者把记录添加到集合中,最后再把集合中的数据写入文件中。
三、实验环境
1. 硬件环境:
2. 软件环境:JDK1.5
图2 模型-视图-控制器参考实现图
|
class AddActionListener implements ActionListener { public void actionPerformed(ActionEvent e) { Address address; try { address = addressBookJFrame.getAddress(); addressBookModel.writeAddress(address); } catch (IOException ex) { ex.printStackTrace(); } } } class FirstActionListener implements ActionListener { public void actionPerformed(ActionEvent e) { Address address; try { address = addressBookModel.readFirst(); addressBookJFrame.setAddress(address); } catch (IOException ex) { ex.printStackTrace(); } } } |
|
图3 侦听Add按钮和First按钮的侦听器例 |
四、算法描述及实验步骤
1. 算法描述(可以用类图、流程图、伪代码或源程序描述)
http://s11/middle/6ea6cd6a496503bfeec7a&690
2. 实验步骤
l 分别为问题设计模型类、视图类和控制类
l 进行编译
l 进行测试,使用的测试用例:
输入: 预期输出:
五、调试过程
1. 编译过程
(1)、返回语句之后的语句无法执行:
return readAddress(currentPosition); FixedLengthStringDB.getRst().absolute(length - 1);因为return语句执行完了之后,就直接返回而不会执行下面的语句。
改正:把下面的语句直接删掉,因为放在return语句之前就失去意义了。
2. 调试过程
(1)、读完最后一条语句之后无法停止读取而是读取第一条记录。这是因为读完只有一条语句之后,结果集指向的位置为rst.afterLast(),而对应的位置的行号为rst.getRow()的值为0,在直径rst.next();之后又会循环读取记录。
改正:改变readFixedLengthString(int position, String columnName)方法中的部分代码:
原来:else {
rst.absolute(position);
rst.next();
}
改成:else {
rst.absolute(position);
str = rst.getString(1);
if (position != getLengthOfRow()) {
rst.absolute(position);
rst.next();
}
这样子改是为了判断是否已经读到最后一条记录,如果是的话,就不执行rst.next();语句,而rst.absolute(position);语句则是把指针设为原来的位置,然后再执行rst.next();因为getLengthOfRow()已经把指针放到末尾了所以要重新设位置。
(2)、读到最后一条记录,然后往回读的过程中,倒数第二条记录被隐藏掉,不能读取。原因是通过上面的修改,读取最后一条记录时,并没有执行rst.next();语句,而在readPrevious()方法中返回值为return readAddress(currentPosition - 2);这就直接导致倒数第二条记录无法读取。
改正:在原来的基础上加上else if语句,如下所示:
if (currentPosition > 1 && currentPosition!=length){
return readAddress(currentPosition - 2);
}
else if(currentPosition == length)
return readAddress(currentPosition - 1);
使得读取最后一条记录时返回值为:return readAddress(currentPosition - 1);
六、实验结果
输入:往数据库增加5条记录,具体内容如下:
+--------------+------------+-----------+--------+--------+
| studentName | street | city | state | zip |
+--------------+------------+-----------+--------+--------+
| ganwenxin | zhetiaojie | nanping | fujian | 125478 |
| huangronghan | natiaojie | zhangzhou | fujian | 123547 |
| huangzhitan | natiaojie | putian | fujian | 356214 |
| liteng | natiaojie | zhangzhou | fujian | 145269 |
| xuyouliang | natiaojie | xiamen | fujian | 123654 |
+--------------+------------+-----------+--------+--------+
在界面中进行查找:
点First按钮:
http://s2/middle/6ea6cd6a496503c0c0951&690
点Next按钮:
http://s10/middle/6ea6cd6a496503c789599&690
点Last按钮:
http://s11/middle/6ea6cd6a496503c88c22a&690
点Previous按钮:
http://s10/middle/6ea6cd6a496503c978f99&690
增加操作:加入一条记录,xuqihong zhetiaojie quanzhou fujian 125478
这是数据库就多出一条记录:
http://s1/middle/6ea6cd6a496503ca4b1e0&690
在界面上也可以找到记录:
http://s9/middle/6ea6cd6a496503caac5c8&690
结果分析:结果正确
七、总结
通过这次上机实验,我主要学到以下内容:
(1)、使用MVC的设计模式,同个这种设计模式,把视图层,模式层,控制层分开了,能够更清晰的进行设计,并且带来良好的扩展性。
(2)、巩固了GUI的知识,并且对GUI的相关应用更加熟悉,比如说三种常用的布局管理器,如何把组件添加到容器中,并设置组件的属性等。
(3)、掌握了对事件的处理,如何给按钮添加事件。
(4)、在这次实验中,实验涉及的范围很广,设计的灵活性也较高,特别是将数据库与界面之间进行关联,通过各种方法来传递值,在这次实验中,更重要的是获得程序设计上的经验。
这次实验,还存在很清晰,特别是数据库方面的内容,比如说程序中ResultSet这个类,以下几点不足:
(1)、逻辑不是类里面的方法很多,但是要通过选择这些适合的方法来进行设计却不容易,很容易出现BUG。
(2)、对知识的综合应用的能力还欠缺,设计的时候经常拆东墙补西墙,一个BUG修护好了,又有新的问题出现。
附录:
package com.john.project5;
public class Address {
// Specify the size of five string fields in the record
final static int NAME_SIZE = 32;
final static int STREET_SIZE = 32;
final static int CITY_SIZE = 12;
final static int STATE_SIZE = 5;
final static int ZIP_SIZE = 5;
final static int RECORD_SIZE =
(NAME_SIZE + STREET_SIZE + CITY_SIZE + STATE_SIZE + ZIP_SIZE);
private String name;
private String street;
private String city;
private String state;
private String zip;
public Address() {
this("","", "", "", "");
}
public Address(String name, String street, String city,
String state, String zip) {
this.setName(name);
this.setStreet(street);
this.setCity(city);
this.setState(state);
this.setZip(zip);
}
public String getName() {
return name;
}
public void setName(String name) {
name = name.trim();
this.name = name;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getZip() {
return zip;
}
public void setZip(String zip) {
this.zip = zip;
}
public String getFullAddress() {
return street + '\n' + city + ", " + state + ' ' + zip + '\n';
}
}
package com.john.project5;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JLabel;
import javax.swing.border.BevelBorder;
import java.awt.GridLayout;
import java.awt.BorderLayout;
import java.io.IOException;
import java.sql.SQLException;
public class AddressBookJFrame extends JFrame{
//存储的默认情况下为e:\new_raf.sql
private AddressBookModelRAF abm = new AddressBookModelRAF();
private Address address = new Address();
//类属性 5个文本框 + 5个按钮
//创建文本框,用于显示Name\Sreeet\City\State\Zip
private JTextField jtfName = new JTextField(Address.NAME_SIZE);
private JTextField jtfStreet = new JTextField(Address.STREET_SIZE);
private JTextField jtfCity = new JTextField(Address.CITY_SIZE);
private JTextField jtfState = new JTextField(Address.STATE_SIZE);
private JTextField jtfZip = new JTextField(Address.ZIP_SIZE);
//创建按钮
private JButton jbtAdd = new JButton("Add");
private JButton jbtFirst = new JButton("First");
private JButton jbtNext = new JButton("Next");
private JButton jbtPrevious = new JButton("Previous");
private JButton jbtLast = new JButton("Last");
//类方法
//构造方法
public AddressBookJFrame(){
//初始化数据库连接
FixedLengthStringDB db = new FixedLengthStringDB();
System.out.println(" *****数据库连接成功***** ");
//调用事件侦听器的函数,使按钮产生相应事件
add_All_ActionListener();
System.out.println("*****添加事件侦听器成功*****");
//调用initComponents方法,使容器用户界面可以显示
initComponents();
System.out.println(" ****用户界面加载成功**** ");
}
//用于设计应用程序的窗口界面
private void initComponents(){
//生成Zip模块
JPanel zip = new JPanel();
zip.add(new JLabel("Zip"),new BorderLayout().WEST);
zip.add(jtfZip,new BorderLayout().CENTER);
//生成State模块
JPanel state = new JPanel();
state.add(new JLabel("State"),new BorderLayout().WEST);
state.add(jtfState,new BorderLayout().CENTER);
JPanel z_s = new JPanel();
z_s.add(state,new BorderLayout().WEST);
z_s.add(zip,new BorderLayout().CENTER);
JPanel city = new JPanel();
city.add(new JLabel("City "),new BorderLayout().WEST);
city.add(jtfCity,new BorderLayout().CENTER);
JPanel z_s_City = new JPanel();
z_s_City.add(city,new BorderLayout().CENTER);
z_s_City.add(z_s,new BorderLayout().EAST);
JPanel street = new JPanel();
street.add(new JLabel("Street"),new BorderLayout().WEST);
street.add(jtfStreet,new BorderLayout().CENTER);
JPanel name = new JPanel();
name.add(new JLabel("Name"),new BorderLayout().EAST);
name.add(jtfName,new BorderLayout().CENTER);
JPanel show_Panel = new JPanel(new GridLayout(3,1,0,0));
show_Panel.add(name);
show_Panel.add(street);
show_Panel.add(z_s_City);
//
show_Panel.setBorder(new BevelBorder(BevelBorder.RAISED));
JPanel control_Panel = new JPanel();
control_Panel.add(jbtAdd);
control_Panel.add(jbtFirst);
control_Panel.add(jbtNext);
control_Panel.add(jbtPrevious);
control_Panel.add(jbtLast);
JPanel window = new JPanel();
window.add(show_Panel,new BorderLayout().CENTER);
window.add(control_Panel,new BorderLayout().SOUTH);
//添加部件window,使之可以在程序运行后显示在窗口中
add(window);
}
public void setAddress(Address address){
jtfName.setText(address.getName());
jtfStreet.setText(address.getStreet());
jtfCity.setText(address.getCity());
jtfState.setText(address.getState());
jtfZip.setText(address.getZip());
}
public void getAddress(){
//把文本框的值以字符串的形式传递到Address类中相应的属性
address.setName(jtfName.getText());
address.setStreet(jtfStreet.getText());
address.setCity(jtfCity.getText());
address.setState(jtfState.getText());
address.setZip(jtfZip.getText());
// return address;
}
//创建5个按钮的侦听器,使单击按钮时产生相应的事件
public void add_All_ActionListener(){
//Add按钮
jbtAdd.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
try {
getAddress();
abm.writeAddress(address);
Address newAddress = new Address();
setAddress(newAddress);
} catch (SQLException e2) {
e2.printStackTrace();
}
};
});
//First按钮
jbtFirst.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
try {
address = abm.readFirst();
setAddress(address);
} catch (SQLException e1) {
e1.printStackTrace();
}
};
});
//Next按钮
jbtNext.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
try {
address = abm.readNext();
setAddress(address);
} catch (SQLException e1) {
e1.printStackTrace();
}
};
});
//Previous按钮
jbtPrevious.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
try {
address = abm.readPrevious();
setAddress(address);
} catch (SQLException e1) {
e1.printStackTrace();
}
};
});
//Last按钮
jbtLast.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
try {
address = abm.readLast();
setAddress(address);
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
};
});
}
//定义主函数,在主函数中通过创建对象来调用构造函数,使窗体添加
public static void main(String[] args) {
AddressBookJFrame frame = new AddressBookJFrame();
frame.setLocation(200, 150);
frame.setSize(500, 250);
frame.setTitle("Address Book Input Frame");
frame.setDefaultCloseOperation
frame.setVisible(true);
}
}
package com.john.project5;
public abstract class AddressBookModel {
public abstract void writeAddress(Address address) throws Exception ;
public abstract Address readFirst() throws Exception ;
public abstract Address readNext() throws Exception ;
public abstract Address readPrevious() throws Exception;
public abstract Address readLast() throws Exception;
}
package com.john.project5;
import java.io.*;
import java.sql.SQLException;
import javax.swing.JOptionPane;
public class AddressBookModelRAF extends AddressBookModel{
public AddressBookModelRAF() {
}
public void writeAddress(Address address) throws SQLException {
FixedLengthStringDB.writeFixedLengthString(FixedLengthStringDB.toString(address));
}
public Address readFirst() throws SQLException {
return readAddress(0);
}
public Address readNext() throws SQLException {
int currentPosition = FixedLengthStringDB.getRst().getRow();
FixedLengthStringDB.getRst().last();
int length = FixedLengthStringDB.getRst().getRow();
if (currentPosition <= length)
return readAddress(currentPosition);
else{
JOptionPane.showMessageDialog(null,"已经是最后一条记录!");
return readAddress(currentPosition - 1);
}
}
public Address readPrevious() throws SQLException {
int currentPosition = FixedLengthStringDB.getRst().getRow();
int length = FixedLengthStringDB.getLengthOfRow();
FixedLengthStringDB.getRst().absolute(currentPosition);
if (currentPosition > 1 && currentPosition!=length){
return readAddress(currentPosition - 2);
}
else if(currentPosition == length)
return readAddress(currentPosition - 1);
else{
JOptionPane.showMessageDialog(null,"已经是第一条记录!");
return readAddress(0);
}
}
public Address readLast() throws SQLException {
FixedLengthStringDB.getRst().last();
int lastPosition = FixedLengthStringDB.getRst().getRow();
return readAddress(lastPosition);
}
private Address readAddress(int position) throws SQLException{
// int length = FixedLengthStringDB.getLengthOfRow();
if ( position >=0 ) {
String name = FixedLengthStringDB.readFixedLengthString(
position,"studentName");
String street = FixedLengthStringDB.readFixedLengthString(
position,"street");
String city = FixedLengthStringDB.readFixedLengthString(
position,"city");
String state = FixedLengthStringDB.readFixedLengthString(
position,"state");
String zip = FixedLengthStringDB.readFixedLengthString(
position,"zip");
return new Address(name, street, city, state, zip);
} else {
return null;
}
}
}
package com.john.project5;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.sql.*;
import javax.sound.midi.SysexMessage;
import javax.swing.JOptionPane;
public class FixedLengthStringDB {
//定义类属性
private static Connection conn;
private static Statement stmt;
private static ResultSet rst;
private static String driverName = new String("com.mysql.jdbc.Driver");
private static String url = new String("jdbc:mysql://localhost/addressBook");
private static String user = new String("john");
private static String password = new String("john");
//定义类方法
//定义构造函数,用于加载数据库
public FixedLengthStringDB() {
initalizeDB();
}
public static ResultSet getRst() {
return rst;
}
private static void initalizeDB() {
try {
//加载驱动
Class.forName(driverName);
System.out.println("驱动器已加载...");
} catch (ClassNotFoundException e) {
System.out.println("驱动器无法加载,请检查驱动路径是否正确!");
System.out.println(e.getMessage());
}
try {
//建立连接
conn = DriverManager.getConnection(url, user, password);
System.out.println("MySQL连接已建立...");
} catch (SQLException e) {
System.out.println("MySql连接无法建立,请检查连接路径是否正确!");
System.out.println(e.getMessage());
}
try {
//创建Statement
stmt = conn.createStatement();
System.out.println("Statement创建完毕!");
} catch (SQLException e) {
System.out.println("创建Statement的时候出现异常!");
System.out.println(e.getMessage());
}
try {
rst = stmt.executeQuery("select * from Address;");
System.out.println("ResultSet初始化完毕!");
} catch (SQLException e) {
System.out.println("ResultSet初始化异常!");
System.out.println(e.getMessage());
}
}
public static String readFixedLengthString(int position, String columnName)
throws SQLException {
String queryString = "Select " + columnName + " From Address ;";
rst = stmt.executeQuery(queryString);
String str = new String("");
if (position == 0) {
rst.first();
str = rst.getString(1);
rst.next();
} else {
rst.absolute(position);
str = rst.getString(1);
if (position != getLengthOfRow()) {
rst.absolute(position);
rst.next();
}
}
return new String(str);
}
public static String toString(Address address) {
String value = new String("");
value += "('" + address.getName() + "','"
+ address.getStreet() + "','" + address.getCity() + "','"
+ address.getState() + "','" + address.getZip() + "')";
String column = new String("");
column += "(studentName,street,city,state,zip)";
String updateString = "insert into Address" + column + " values "
+ value + ";\n";
return new String(updateString);
}
public static void writeFixedLengthString(String updateString)
throws SQLException {
System.out.println("语句没语法问题!");
try {
stmt.executeUpdate(updateString);
System.out.println("执行语句没有问题!");
} catch (SQLException e) {
JOptionPane.showMessageDialog(null, "无法实现添加功能,请检查Name是否重复!");
System.out.println(e.getMessage());
System.exit(0);
}
}
public static int getLengthOfRow() throws SQLException {
getRst().last();
return rst.getRow();
}
}

加载中…