上篇文章已经完成了数据源和DAO的工作,现在我们就来做一个GUI的桌面应用,这里面主要用到JAVA中的AWT和Swing的知识,我们来简单梳理一下。要想完成下面的小应用,我们首先要掌握Swing容器组件JFrame 、Jpanel和jScrollPane1,掌握Swing GUI 组件JLabel、JTextField、JPasswordField、JList、JButton、JfileChooser等并能够运用以上组件进行GUI设计。除此以外,我们还要理解事件监听器,理解默认布局管理器FlowLayout,掌握菜单设计并会运用对话框JoptionPane。呵呵,大概就是这些知识点了,如果大家觉得有点吃力不妨先运行下面的示例,完了再略补下Swing方面的知识。如果没问题就继续吧!
下面主要有四个类,里面都有详细的注释,我这里就不赘述了。
1.登录窗口 LoginFrame.java
package com.wepull.client;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class LoginFrame extends JFrame implements ActionListener {
private static final long serialVersionUID = 5644283401685995671L;
// 声明窗口控件
JPanel contentPane;
JLabel nameLabel = new JLabel();
JLabel passwordLabel = new JLabel();
JTextField nameTextField = new JTextField();
JPasswordField passwordField = new JPasswordField();
JButton loginBtn = new JButton();
JButton exitBtn = new JButton();
// 声明主窗口类
MainFrame mainFrame = null;
public LoginFrame(MainFrame mainFrame) {
// 取得主窗口对象
this.mainFrame = mainFrame;
try {
jbInit();
} catch (Exception e) {
e.printStackTrace();
}
}
private void jbInit() throws Exception {
setTitle("登陆窗口");
setResizable(false);
// 取得窗口面板
contentPane = (JPanel) this.getContentPane();
// 定义窗口面板的布局
contentPane.setLayout(null);
// 定义窗口的大小和标题
this.setSize(new Dimension(400, 276));
// 定义标签的标题、字符大小和位置
nameLabel.setText("用户名:");
nameLabel.setFont(new java.awt.Font("Dialog", 0, 15));
nameLabel.setBounds(new Rectangle(65, 67, 81, 16));
passwordLabel.setText("密码:");
passwordLabel.setFont(new java.awt.Font("Dialog", 0, 15));
passwordLabel.setBounds(new Rectangle(65, 112, 79, 16));
// 定义编辑框的位置
nameTextField.setBounds(new Rectangle(194, 67, 118, 22));
passwordField.setBounds(new Rectangle(194, 112, 118, 22));
// 定义按钮的标题、动作字符串、字符大小、位置和加入动作接收器
loginBtn.setText("登陆");
loginBtn.setActionCommand("login");
loginBtn.setFont(new java.awt.Font("Dialog", 0, 15));
loginBtn.setBounds(new Rectangle(65, 180, 109, 25));
loginBtn.addActionListener(this);
exitBtn.setText("退出");
exitBtn.setActionCommand("exit");
exitBtn.setFont(new java.awt.Font("Dialog", 0, 15));
exitBtn.setBounds(new Rectangle(203, 180, 109, 25));
exitBtn.addActionListener(this);
// 为面板加入各个控件
contentPane.add(nameLabel, null);
contentPane.add(nameTextField, null);
contentPane.add(passwordLabel, null);
contentPane.add(passwordField, null);
contentPane.add(exitBtn, null);
contentPane.add(loginBtn, null);
}
protected void processWindowEvent(WindowEvent e) {
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
exit();
}
}
// 单击事件处理代码
public void actionPerformed(ActionEvent e) {
// 取得按钮的动作字符串
String actionCommand = e.getActionCommand().trim();
// 取得用户名
String userName = nameTextField.getText();
// 取得密码
// String userPassword = new String(passwordField.getPassword());
if (actionCommand.equals("login")) {
mainFrame.setTitle("管理信息系统主窗口" + ":登陆用户(" + userName + ")");
exit();
}
if (actionCommand.equals("exit")) {
exit();
}
}
// 退出方法
public void exit() {
// 将输入框的值设为空值
nameTextField.setText("");
passwordField.setText("");
// 隐藏登陆窗口
this.setVisible(false);
}
}
2.数据库数据备份和恢复的窗口 DataBackupFrame.java,是本应用的核心。
package com.wepull.client;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import com.wepull.model.OperationDAO;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
public class DataBackupFrame extends JFrame implements ActionListener {
private static final long serialVersionUID = -1193231376138917300L;
private static final String DEFAULT_DB_NAME = "java28";
JPanel contentPane;
// 创建标签控件
JLabel jLabel1 = new JLabel();
JLabel jLabel2 = new JLabel();
// 创建编辑框控件
JTextField jTextField1 = new JTextField();
// 创建滚动框控件
JScrollPane jScrollPane1 = new JScrollPane();
JScrollPane jScrollPane2 = new JScrollPane();
JScrollPane jScrollPane3 = new JScrollPane();
// 创建列表框数据类和列表框控件
DefaultListModel listData1 = new DefaultListModel();
DefaultListModel listData2 = new DefaultListModel();
DefaultListModel listData3 = new DefaultListModel();
JList jList1 = new JList(listData1);
JList jList2 = new JList(listData2);
JList jList3 = new JList(listData3);
// 创建按钮控件
JButton jButton1 = new JButton();
JButton jButton2 = new JButton();
JButton jButton3 = new JButton();
JButton jButton4 = new JButton();
JButton jButton5 = new JButton();
JButton jButton6 = new JButton();
JButton jButton7 = new JButton();
JButton jButton8 = new JButton();
// 创建字体类
Font dialog13 = new java.awt.Font("Dialog", 0, 13);
// 声明数据操作类
OperationDAO dao = null;
// 声明主窗口类
MainFrame mainFrame = null;
public DataBackupFrame(MainFrame mainFrame) {
this.mainFrame = mainFrame;
// 取得主窗口的数据操作类
dao = mainFrame.getDao();
// 检查用户权限......
try {
jbInit();
} catch (Exception e) {
e.printStackTrace();
}
}
private void jbInit() throws Exception {
contentPane = (JPanel) this.getContentPane();
contentPane.setLayout(null);
this.setTitle("数据备份恢复窗口");
this.setSize(new Dimension(668, 601));
// 设置标签控件
jLabel1.setText("备份文件目录:");
jLabel1.setBounds(new Rectangle(12, 33, 101, 16));
jLabel2.setText("信息显示框:");
jLabel2.setBounds(new Rectangle(455, 76, 92, 16));
// 设置编辑框控件
jTextField1.setBounds(new Rectangle(123, 29, 428, 22));
// 设置滚动框控件
jScrollPane1.setBounds(new Rectangle(12, 117, 192, 365));
jScrollPane2.setBounds(new Rectangle(234, 117, 192, 365));
jScrollPane3.setBounds(new Rectangle(455, 117, 192, 365));
jScrollPane3.getViewport().add(jList3, null);
jScrollPane1.getViewport().add(jList1, null);
jScrollPane2.getViewport().add(jList2, null);
// 设置列表框的属性,使可以选择列表框的多条记录
jList1.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
jList2.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
// 设置按钮控件
jButton1.setText("选择");
jButton1.setActionCommand("select");
jButton1.setBounds(new Rectangle(574, 27, 73, 25));
jButton2.setText("显示数据表");
jButton2.setActionCommand("showTable");
;
jButton2.setBounds(new Rectangle(12, 73, 192, 25));
jButton3.setText("显示备份文件");
jButton3.setActionCommand("showBackupFile");
;
jButton3.setBounds(new Rectangle(234, 73, 192, 25));
jButton4.setText("备份选择数据表");
jButton4.setActionCommand("backupSelectedTables");
;
jButton4.setBounds(new Rectangle(12, 508, 130, 25));
jButton5.setText("备份全部数据表");
jButton5.setActionCommand("backupAllTables");
;
jButton5.setBounds(new Rectangle(149, 508, 135, 25));
jButton6.setText("恢复选择文件");
jButton6.setActionCommand("restoreSelectedFiles");
;
jButton6.setBounds(new Rectangle(291, 508, 135, 25));
jButton7.setText("恢复全部文件");
jButton7.setActionCommand("restoreAllFiles");
;
jButton7.setBounds(new Rectangle(432, 508, 135, 25));
jButton8.setText("退出");
jButton8.setActionCommand("exit");
;
jButton8.setBounds(new Rectangle(574, 508, 73, 25));
contentPane.add(jLabel1, null);
contentPane.add(jLabel2, null);
contentPane.add(jTextField1, null);
contentPane.add(jScrollPane1, null);
contentPane.add(jScrollPane2, null);
contentPane.add(jScrollPane3, null);
contentPane.add(jButton1, null);
contentPane.add(jButton2, null);
contentPane.add(jButton3, null);
contentPane.add(jButton4, null);
contentPane.add(jButton5, null);
contentPane.add(jButton6, null);
contentPane.add(jButton7, null);
contentPane.add(jButton8, null);
// 设置窗口类的字体和为按钮加入动作接收器
setupFontAndListener();
}
// 设置窗口类的字体和为按钮加入动作接收器的方法
public void setupFontAndListener() {
Component[] components = contentPane.getComponents();
// 创建临时按钮控件
JButton tmpBtn = new JButton();
for (int i = 0; i < components.length; i++) {
components[i].setFont(dialog13);
if (components[i].getClass().getName()
.equals("javax.swing.JButton")) {
tmpBtn = (JButton) components[i];
tmpBtn.addActionListener(this);
}
}
}
protected void processWindowEvent(WindowEvent e) {
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
exit();
}
}
// 退出方法
public void exit() {
// 隐藏窗口
this.setVisible(false);
// 清空列表框的内容
listData1.clear();
listData2.clear();
listData3.clear();
// 清空编辑框的内容
jTextField1.setText("");
}
public void actionPerformed(ActionEvent e) {
// 取得按钮的动作字符串
String actionCommand = e.getActionCommand().trim();
// 单击按钮的处理代码
if (actionCommand.equals("select")) {
JFileChooser fc1 = new JFileChooser(); // 创建文件选择器
// 显示文件选择框
fc1.showDialog(this, "选择文件");
try {
// 取得文件类
File file = fc1.getSelectedFile();
if (file != null) {
jTextField1.setText(file.getParent());
}
} catch (Exception ex) {
ex.printStackTrace();
}
} else if (actionCommand.equals("showTable")) {
// 清空列表框的内容
listData1.clear();
// 取得数据库的数据表名字
List<String> tableNames = dao.getTableNames(DEFAULT_DB_NAME);
for (int i = 0; i < tableNames.size(); i++) {
listData1.addElement(tableNames.get(i));
}
} else if (actionCommand.equals("showBackupFile")) {
// 清空列表框的内容
listData2.clear();
// 取得文件路径
String pathName = jTextField1.getText().trim();
if (pathName.length() == 0) {
JOptionPane.showMessageDialog(null, "请选择备份文件目录.");
return;
}
// 创建文件类
File file = new File(pathName);
// 取得pathName路径的所有文件
String[] fileNameList = file.list();
// 显示pathName路径的所有文件
for (int i = 0; i < fileNameList.length; i++) {
listData2.addElement(fileNameList[i]);
}
// 单击备份选择数据表按钮的处理代码
} else if (actionCommand.equals("backupSelectedTables")) {
int[] selectedIndexes = jList1.getSelectedIndices();
if (selectedIndexes.length == 0) {
JOptionPane.showMessageDialog(null, "请选择数据表.");
return;
}
// 取得文件路径
String pathName = jTextField1.getText().trim();
if (pathName.length() == 0) {
JOptionPane.showMessageDialog(null, "请选择备份文件目录.");
return;
}
// 清空信息列表框的内容
listData3.clear();
String tableName = "";
for (int i = 0; i < selectedIndexes.length; i++) {
// 取得选择数据表的名字
tableName = (String) listData1.getElementAt(selectedIndexes[i]);
try {
// 备份数据表
backupTable(tableName, pathName);
} catch (Exception ex) {
ex.printStackTrace();
}
}
// 单击备份所有数据表按钮的处理代码
} else if (actionCommand.equals("backupAllTables")) {
if (listData1.size() == 0) {
JOptionPane.showMessageDialog(null, "请显示数据表.");
return;
}
// 取得文件路径
String pathName = jTextField1.getText().trim();
if (pathName.length() == 0) {
JOptionPane.showMessageDialog(null, "请选择备份文件目录.");
return;
}
// 清空信息列表框的内容
listData3.clear();
String tableName = "";
for (int i = 0; i < listData1.size(); i++) {
// 取得选择数据表的名字
tableName = (String) listData1.getElementAt(i);
try {
// 备份数据表
backupTable(tableName, pathName);
} catch (Exception ex) {
ex.printStackTrace();
}
}
// 单击恢复选择文件按钮的处理代码
} else if (actionCommand.equals("restoreSelectedFiles")) {
// 取得文件路径
String pathName = jTextField1.getText().trim();
if (pathName.length() == 0) {
JOptionPane.showMessageDialog(null, "请选择备份文件目录.");
return;
}
int[] selectedIndexes = jList2.getSelectedIndices();
if (selectedIndexes.length == 0) {
JOptionPane.showMessageDialog(null, "请选择备份文件.");
return;
}
if (listData1.size() == 0) {
JOptionPane.showMessageDialog(null, "请显示数据表.");
return;
}
// 清空信息列表框的内容
listData3.clear();
String fileName = "";
for (int i = 0; i < selectedIndexes.length; i++) {
fileName = (String) listData2.getElementAt(selectedIndexes[i]);
// 根据文件名取得数据表的名字
String tableName = fileName.substring(0, fileName
.indexOf(".dat"));
// 检查数据表名字是否存在
if (listData1.indexOf(tableName) == -1) {
JOptionPane.showMessageDialog(null, fileName
+ "文件的数据表在数据库不存在," + "不可以进行恢复操作.");
continue;
}
try {
restoreTable(fileName, tableName, pathName);
} catch (Exception ex) {
ex.printStackTrace();
}
}
// 单击恢复全部文件按钮的处理代码
} else if (actionCommand.equals("restoreAllFiles")) {
// 取得文件路径
String pathName = jTextField1.getText().trim();
if (pathName.length() == 0) {
JOptionPane.showMessageDialog(null, "请选择备份文件目录.");
return;
}
if (listData2.size() == 0) {
JOptionPane.showMessageDialog(null, "请显示备份文件.");
return;
}
if (listData1.size() == 0) {
JOptionPane.showMessageDialog(null, "请显示数据表.");
return;
}
// 清空信息列表框的内容
listData3.clear();
String fileName = "";
for (int i = 0; i < listData2.size(); i++) {
fileName = (String) listData2.getElementAt(i);
// 根据文件名取得数据表的名字
String tableName = fileName.substring(0, fileName
.indexOf(".dat"));
// 检查数据表名字是否存在
if (listData1.indexOf(tableName) == -1) {
JOptionPane.showMessageDialog(null, fileName
+ "文件的数据表在数据库不存在," + "不可以进行恢复操作.");
continue;
}
try {
restoreTable(fileName, tableName, pathName);
} catch (Exception ex) {
ex.printStackTrace();
}
}
} else if (actionCommand.equals("exit")) {
exit();
}
}
// 将数据表数据保存在文件的方法
public void backupTable(String tableName, String pathName) throws Exception {
String[][] data = null;
// 创建文件类
File file = new File(pathName + "//" + tableName + ".dat");
if (file.isFile()) {
// 取得信息确认框的返回值
int actionInt = JOptionPane.showConfirmDialog(null, tableName
+ ".dat" + "文件已存在,是否覆盖该文件?", "信息确认框",
JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE);
// 如果单击否按钮,不进行覆盖操作
if (actionInt == JOptionPane.NO_OPTION) {
listData3.addElement(tableName + ".dat文件已存在,不进行覆盖操作.");
return;
}
}
// 创建文件写出类
FileWriter writer = new FileWriter(pathName + "//" + tableName + ".dat");
// 取得数据表的数据
data = dao.getDataByTableName("java28", tableName);
for (int row = 0; row < data.length; row++) {
for (int col = 0; col < data[0].length; col++) {
// 如果字段值为空值,转换为null字符串,如果字段值的长度为度,加入一个空格
if (data[row][col] == null) {
data[row][col] = "null";
} else if (data[row][col].length() == 0) {
data[row][col] = " ";
}
if (col == data[0].length - 1) {
// /n是换行符
writer.write(data[row][col] + "/n");
} else {
// /t是水平制表符
writer.write(data[row][col] + "/t");
}
}
}
// 关闭文件写出类
writer.close();
listData3.addElement(tableName + "数据表成功备份,数据表的保存路径是" + pathName + ".");
}
// 将文件数据写入数据表的方法
public void restoreTable(String fileName, String tableName, String pathName)
throws Exception {
// 创建数组
String[][] data = null;
File inFile = new File(pathName + File.separator + fileName);
// 读入文件
FileReader reader = new FileReader(inFile);
// 创建集合类
List<String> list = new ArrayList<String>();
BufferedReader bufferedReader = new BufferedReader(reader);
while (bufferedReader.ready()) {
// 读入一行内容
list.add(bufferedReader.readLine());
}
if (list.size() > 0) {
// 取得行总数
int rowLength = list.size();
String tempStr = (String) list.get(0);
StringTokenizer stringToken = new StringTokenizer(tempStr, "/t");
// 取得列总数
int colLength = stringToken.countTokens();
// 根据行和列的总数创建内容数组
data = new String[rowLength][colLength];
for (int row = 0; row < rowLength; row++) {
stringToken = new StringTokenizer((String) list.get(row), "/t");
for (int col = 0; col < colLength; col++) {
tempStr = stringToken.nextToken();
// 取代/n字符串
tempStr.replace('/n', ' ');
tempStr = tempStr.trim();
// 向数组写入内容
data[row][col] = tempStr;
}
}
// 将数组数据写入数据表
dao.setDataByTableName(DEFAULT_DB_NAME, tableName, data);
listData3.addElement(fileName + "文件的数据已写入数据表" + tableName + ".");
} else {
listData3.addElement(fileName + "文件没有数据.");
}
}
}
3. 管理信息系统的主窗口 MainFrame.java,主要是菜单的设计
package com.wepull.client;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import com.wepull.model.OperationDAO;
public class MainFrame extends JFrame implements ActionListener {
private static final long serialVersionUID = -4771293602694043632L;
private LoginFrame loginFrame;
private DataBackupFrame dataBackupFrame;
// 声明数据操作类
private OperationDAO dao = null;
private JPanel contentPane;
// 创建菜单条
JMenuBar mainMenuBar = new JMenuBar();
// 创建系统设置菜单
JMenu systemMenu = new JMenu();
// 创建基础信息菜单
JMenu baseInforMenu = new JMenu();
// 创建系统设置菜单项
JMenuItem exitMenuItem = new JMenuItem();
// 创建基础信息菜单项
JMenuItem loginMenuItem = new JMenuItem();
JMenuItem changeUserMenuItem = new JMenuItem();
JMenuItem changePasswordMenuItem = new JMenuItem();
JMenuItem viewAuthorityMenuItem = new JMenuItem();
JMenuItem userManageMenuItem = new JMenuItem();
JMenuItem dataBackupMenuItem = new JMenuItem();
JMenuItem reportManageMenuItem = new JMenuItem();
JMenuItem userLogViewMenuItem = new JMenuItem();
// 创建字体类
Font dialog13 = new java.awt.Font("Dialog13", 0, 13);
public MainFrame() {
try {
jbInit();
} catch (Exception e) {
e.printStackTrace();
}
}
private void jbInit() throws Exception {
dao = new OperationDAO();
contentPane = (JPanel) this.getContentPane();
contentPane.setLayout(null);
this.setSize(new Dimension(529, 411));
this.setTitle("管理信息系统主窗口");
// 为面板加入菜单工具栏
this.setJMenuBar(mainMenuBar);
// 设置菜单的标题和动作字符串
systemMenu.setText("系统设置");
baseInforMenu.setActionCommand("baseinfor");
baseInforMenu.setText("基础信息");
// 设置系统设置的菜单项
exitMenuItem.setActionCommand("exit");
exitMenuItem.setText("退出");
// 设置基础信息模块的菜单项
loginMenuItem.setActionCommand("login");
loginMenuItem.setText("用户登陆");
changeUserMenuItem.setActionCommand("changeUser");
changeUserMenuItem.setText("切换用户");
changePasswordMenuItem.setActionCommand("changePassword");
changePasswordMenuItem.setText("修改密码");
viewAuthorityMenuItem.setActionCommand("viewAuthority");
viewAuthorityMenuItem.setText("查看用户权限");
userManageMenuItem.setActionCommand("userManage");
userManageMenuItem.setText("用户管理");
dataBackupMenuItem.setActionCommand("dataBackup");
dataBackupMenuItem.setText("数据备份");
reportManageMenuItem.setActionCommand("reportManage");
reportManageMenuItem.setText("报表管理");
userLogViewMenuItem.setActionCommand("userLogView");
userLogViewMenuItem.setText("用户日志查看");
// 为系统设置菜单加入菜单项
systemMenu.add(exitMenuItem);
// 为基础信息菜单加入菜单项
baseInforMenu.add(loginMenuItem);
baseInforMenu.add(changeUserMenuItem);
baseInforMenu.add(changePasswordMenuItem);
baseInforMenu.add(viewAuthorityMenuItem);
baseInforMenu.add(userManageMenuItem);
baseInforMenu.addSeparator();
baseInforMenu.add(dataBackupMenuItem);
baseInforMenu.add(reportManageMenuItem);
baseInforMenu.add(userLogViewMenuItem);
// 为菜单工具栏加入菜单
mainMenuBar.add(systemMenu);
mainMenuBar.add(baseInforMenu);
// 为菜单项加入单击事件接收器和设置菜单的字体
setupMenuItem();
}
public void setupMenuItem() {
// 设置菜单工具栏的菜单控件的字体
Component[] components = mainMenuBar.getComponents();
for (int i = 0; i < components.length; i++) {
JMenu tempMenu = ((JMenu) components[i]);
tempMenu.setFont(dialog13);
// 设置各菜单的菜单项的事件接收器和字体
Component[] tempcomponents = tempMenu.getMenuComponents();
for (int j = 0; j < tempcomponents.length; j++) {
if (tempcomponents[j].getClass().getName().equals(
"javax.swing.JPopupMenu$Separator")) {
continue;
}
JMenuItem tempMenuItem = (JMenuItem) tempcomponents[j];
tempMenuItem.setFont(dialog13);
tempMenuItem.addActionListener(this);
}
}
}
protected void processWindowEvent(WindowEvent e) {
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
this.exit();
}
}
// 退出程序
public void exit() {
// 清空系统占用内存
System.exit(0);
}
public void actionPerformed(ActionEvent e) {
// 取得动作字符串
String actionCommand = e.getActionCommand().trim();
// 单击的处理代码
if (actionCommand.equals("login")) {
if (loginFrame == null) {
loginFrame = new LoginFrame(this);
}
loginFrame.setVisible(true);
} else if (actionCommand.equals("dataBackup")) {
if (dataBackupFrame == null) {
dataBackupFrame = new DataBackupFrame(this);
}
dataBackupFrame.setVisible(true);
}
}
public OperationDAO getDao() {
return dao;
}
}
4. 管理信息系统的入口类MainApp.java,主要是创建并初始化主窗口对象
package com.wepull.client;
import java.awt.Dimension;
import java.awt.Toolkit;
public class MainApp {
public MainApp() {
// 创建窗口类
MainFrame frame = new MainFrame();
// 取得屏幕大小和窗口大小
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Dimension frameSize = frame.getSize();
// 使窗口居中对齐
if (frameSize.height > screenSize.height) {
frameSize.height = screenSize.height;
}
if (frameSize.width > screenSize.width) {
frameSize.width = screenSize.width;
}
frame.setLocation((screenSize.width - frameSize.width) / 2,
(screenSize.height - frameSize.height) / 2);
frame.setVisible(true);
}
public static void main(String[] args) {
new MainApp();
}
}
上面我们只是简单地设计了4个类,这里尤其要注意是各个窗口的事件监听以及主窗口和其它窗口的界面切换和数据交换。由于我们的关注点在数据备份上,所以重点设计了DataBackupFrame类,它能够完成数据表的备份和备份文件的恢复,并做了相应的容错处理。这样,一个简易的桌面应用就初具雏形了。我们注意到桌面应用的好处就是及时响应和很方便的界面更新。下篇文章我们将在WEB应用程序中也领略到这一好处,并且引入一个优秀的AJAX框架—DWR !