📄 databasemanager.java
字号:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
import java.util.ArrayList;
// 描述:实现数据库管理器的基础类,具体的数据库的管理可在此类基础上扩展
// 作者:周晓聪
// 版本:1.0
// 日期:2003.09.12
class DatabaseManager {
// 属性描述
protected JPanel managerPane = null; // 存放管理器界面的面板
protected JScrollPane tablePane = null; // 存放管理器的表格的滚动面板
protected JTable table = null; // 管理器中的表格
protected JPanel controlPane = null; // 存放管理器操作按钮的面板
protected Container ground;
protected DatabaseTableModel model;
// 功能:创建用于管理数据库的面板
// 参数:Container ground - 创建的面板可以放置的容器
// DatabaseTableModel model - 用于创建面板中表格的数据模型
// boolean modifiable - 是否可使用管理器修改数据库中的数据
public void createManagerPane(Container ground, DatabaseTableModel model) {
this.ground = ground; this.model = model;
model.addTableModelListener(new DatabaseTableModelListener());
table = new JTable(model);
// 设置表格每一列的最佳宽度,该宽度还与字体有关,先计算一下表格使用的缺省字体的宽度
int fontSize = table.getFont().getSize();
TableColumn column = null;
for (int i = 0; i < model.getColumnCount(); i++) {
column = table.getColumnModel().getColumn(i); // 获取列对象
column.setPreferredWidth(model.getColumnWidth(i)*fontSize);
}
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
table.setRowSelectionInterval(1, 1);
// 将表格放置在一滚动窗格中
tablePane = new JScrollPane(table);
// 创建一面板用于放置操作数据的按钮
controlPane = new JPanel();
// 创建一面板用于放置控制面板和表格滚动面板
managerPane = new JPanel();
managerPane.setLayout(new BorderLayout());
managerPane.add(controlPane, BorderLayout.NORTH);
managerPane.add(tablePane, BorderLayout.CENTER);
// 将管理器面板加入到所要放置的容器ground
ground.add(managerPane);
}
// 功能:设置管理器选中关键字段值为keyId的表格行, 通常由DatabaseTableModel指明那一列是关键
// 字段列
// 参数:Object keyId - 指定关键字段的值
// 返回:如果管理器的表格中存在关键字段值为keyId的值,则选中该表格行,并返回true,
// 返回false表示不存在该表格行
public boolean setSelectionRow(Object keyId) {
int row = model.getKeyIdRow(keyId);
if (row >= 0) { table.setRowSelectionInterval(row, row); return true; }
else return false;
}
// 功能:返回当前选中的表格行的关键字段的值
// 返回:当前选中的表格行的关键字段值
public Object getSelectionRowKey() {
int row = table.getSelectedRow();
if (row < 0) return null;
int col = model.getKeyFieldColumn();
return model.getValueAt(row, col);
}
// 功能:如果该管理器是可修改数据库中的数据的,则调用下述方法对数据库进行真正的修改
// 参数:Object keyId - 要修改的数据记录的关键字段值
// String modifyField - 要修改的数据域的名称
// Object newValue - 数据域的新的值
// 备注:缺省的数据管理器没有实现该方法
public void updateFieldValue(Object keyId, String modifyField, Object newValue) {
}
// 功能:删除表格中的一行
// 参数:Object keyId - 要删除的数据记录的关键字段值
public void removeRow(Object keyId) {
int currentRow = model.getKeyIdRow(keyId);
int nextRow = currentRow;
if (nextRow > model.getRowCount()) nextRow = model.getRowCount();
if (nextRow <= 0) nextRow = 0;
model.removeRow(keyId);
table.setRowSelectionInterval(nextRow, nextRow);
}
// 功能:在表格中增加一行
// 参数:Object[] rowData - 要增加的数据记录内容
public void addRow(Object[] rowData) {
model.addRow(rowData);
int nextRow = model.getRowCount();
table.setRowSelectionInterval(nextRow-1, nextRow-1);
}
// 功能:为该管理器增加对数据库的操作按钮
// 参数:String label - 显示在按钮上的文本
// char mnemonic - 按钮的快捷键
// String toolTipText - 按钮的工具提示
// String actionCommand - 按钮的动作命令名称
// ActionListener listener - 按钮的动作监听器
public void addOperationButton(String label, char mnemonic, String toolTipText,
String actionCommand, ActionListener listener) {
JButton button = new JButton(label);
button.setMnemonic(mnemonic);
button.setToolTipText(toolTipText);
button.setActionCommand(actionCommand);
button.addActionListener(listener);
// 使用面板缺省的顺序布局管理器将按钮加入到控制面板
controlPane.add(button);
}
// 功能:关闭管理器
public void close() throws Exception {
ground.remove(managerPane);
ground.repaint();
}
// 描述:管理器所使用的表格数据模型上的监听器,监听对表格单元的变化,并调用方法
// updateFieldValue()修改相应数据库的内容,如果用户允许直接在表格中修改
// 则需要重定义方法updateFieldValue()。
// 作者:周晓聪
// 版本:1.0
// 日期:2003.09.12
class DatabaseTableModelListener implements TableModelListener {
public void tableChanged(TableModelEvent evt) {
int row = evt.getFirstRow(); // 改变的表格行
int col = evt.getColumn(); // 改变的表格列
// 忽略除修改以外的事件
if (evt.getType() != TableModelEvent.UPDATE) return;
Object value = model.getValueAt(row, col);
int keyCol = model.getKeyFieldColumn();
Object keyId = model.getValueAt(row, keyCol);
String fieldName = model.getFieldName(col);
// 调用真正修改数据库的方法修改数据库中相应的内容
updateFieldValue(keyId, fieldName, value);
}
}
}
// 描述:描述数据库字段(也是数据库管理器中的表列)信息
// 作者:周晓聪
// 版本:1.0
// 日期:2003.09.12
class DatabaseTableColumn {
private String name; // 表格列名(列标题)
private String field; // 表列所对应的字段名称
private Class type; // 表列的类型所属的类
private int width; // 表列宽度
private int sqlType; // 表列类型在Sql中的编码值
public DatabaseTableColumn(String name, String field, Class type,
int width, int sqlType) {
this.name = name; this.field = field;
this.type = type; this.width = width;
this.sqlType = sqlType;
}
public String getName() { return name; }
public String getField() { return field; }
public Class getType() { return type; }
public int getWidth() { return width; }
public int getSqlType() { return sqlType; }
}
// 描述:数据库管理器的表格所使用的缺省数据模型,用户也可对此进行扩展
// 作者:周晓聪
// 版本:1.0
// 日期:2003.09.12
class DatabaseTableModel extends AbstractTableModel {
protected DatabaseTableColumn[] columns; // 表列信息
// 表格中的数据,ArrayList的元素类型是Object[],长度为columnNames.length
protected ArrayList data;
protected int keyCol; // 关键字段所在的列
// 指明使用该模型的表格是否可修改表格单元,注意关键字段所在的列总是不可修改的
protected boolean modifiable;
public DatabaseTableModel(ArrayList data, DatabaseTableColumn[] columns,
String keyField, boolean modifiable) {
this.data = data;
this.columns = columns;
keyCol = 0;
int i;
for (i = 0; i < columns.length; i++) {
if (keyField.equals(columns[i].getField())) { keyCol = i; break; }
}
// 程序员不应该发生如下错误,因此只打印信息供调试用,没有抛出异常!
if (i >= columns.length) System.out.println("传入了错误的关键字段参数:" + keyField);
this.modifiable = modifiable;
}
// 功能:返回表列数
public int getColumnCount() { return columns.length; }
// 功能:返回表列名称
public String getColumnName(int col) { return columns[col].getName(); }
// 功能:返回表行数
public int getRowCount() { return data.size(); }
// 功能:返回表格第col列的首选宽度
public int getColumnWidth(int col) { return columns[col].getWidth(); }
// 功能:返回表格第col列所对应的数据字段名称
public String getFieldName(int col) { return columns[col].getField(); }
// 功能:返回关键字段名称
public String getKeyFieldName() { return columns[keyCol].getField(); }
// 功能:返回关键字段在表格中的列下标
public int getKeyFieldColumn() { return keyCol; }
// 功能:返回关键字段值为keyId的记录在表格中的行下标
// 返回:关键字段值为keyId的记录在表格中的行下标
public int getKeyIdRow(Object keyId) {
for (int i = 0; i < data.size(); i++) {
Object[] rowData = (Object[])data.get(i);
if (rowData[keyCol].equals(keyId)) return i;
}
return -1;
}
// 功能:表格需要下面的方法获得每列数据所属的类型来创建缺省的表单元粉刷器与编辑器继承下来的方法不
// 能给出更准确的类型,因为只有应用程序才知道数据的准确类型
public Class getColumnClass(int col) { return columns[col].getType(); }
// 功能:返回列的表格单元是否可修改
public boolean isCellEditable(int row, int col) {
// 屏幕上显示的表格列可由用户拖动,但用户拖动列不会改变内部数据模型的列的顺序
if (col == keyCol) return false; // 关键字段所在的列不可编辑
else return modifiable;
}
// 功能:返回某个表格单元的数据
public Object getValueAt(int row, int col) {
Object[] rowData = (Object[])data.get(row);
return rowData[col];
}
// 功能:设置某个表格单元的数据
public void setValueAt(Object value, int row, int col) {
Object[] rowData = (Object[])data.get(row);
rowData[col] = value;
data.set(row, rowData);
fireTableCellUpdated(row, col);
}
// 功能:删除由关键字段值keyId所指定的一行
public void removeRow(Object keyId) {
int currentRow = getKeyIdRow(keyId);
data.remove(currentRow);
fireTableRowsDeleted(currentRow, currentRow);
}
// 功能:增加一行数据
public void addRow(Object[] rowData) {
data.add(rowData);
fireTableRowsInserted(data.size(), data.size());
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -