RFID作业,要求实现软硬结合,全部使用自己的页面完成;
找了几个教程发现安卓我做不到,就用了Java实现;
图书管理系统。
可以通过写卡来绑定15693卡和书籍,实现增删改查功能;刷卡会改变书的出入库状态;好像没了哈哈哈哈
首先感谢这位大佬的串口通信博文容华谢后使用Java实现串口通信(二)
当时遇到了问题也是看到了博主的评论才解决的,实在是万分感谢。
运行截图如下:
串口通信的包和sqlite的包都在【File->Project Structure->Moudle->Denpendicies】里的+号添加。
我的目录:
六个frame对应六个页面。三个Utils是博主的,我没有仔细去看;剩下两个分别是数据库和串口操作了。
硬件部分比较简单,单片机的代码是等待串口的数据,收到数据后存下来。在读到卡的时候写到卡里,实现交互。
串口操作
说实话我没仔细看,就是能够获取数据和传递数据就行了。是直接用的博主的代码
获取数据:
【其中,setText是让textview显示。append则是显示下一行】
而收到的数据是先保存在data里,然后显示在textview上,所以这里可以把data截下来做自己的事情;data是byte[]数组,先转成自己想要的类型。
我这里是把data作为参数插入数据库了。
/**
* 打开串口
*
* @param evt
* 点击事件
*/
private void openSerialPort(java.awt.event.ActionEvent evt) {
// 获取串口名称
String commName = (String) mCommChoice.getSelectedItem();
// 获取波特率,默认为9600
int baudrate = 9600;
String bps = (String) mBaudrateChoice.getSelectedItem();
baudrate = Integer.parseInt(bps);
// 检查串口名称是否获取正确
if (commName == null || commName.equals("")) {
ShowUtils.warningMessage("没有搜索到有效串口!");
} else {
try {
mSerialport = SerialPortManager.openPort(commName, baudrate);
if (mSerialport != null) {
mDataView.setText("串口已打开" + "\r\n");
mSerialPortOperate.setText("关闭串口");
}
} catch (PortInUseException e) {
ShowUtils.warningMessage("串口已被占用!");
}
}
// 添加串口监听
SerialPortManager.addListener(mSerialport, new SerialPortManager.DataAvailableListener() {
@Override
public void dataAvailable() {
byte[] data = null;
try {
if (mSerialport == null) {
ShowUtils.errorMessage("串口对象为空,监听失败!");
} else {
// 读取串口数据
data = SerialPortManager.readFromPort(mSerialport);
// 以字符串的形式接收数据
if (mDataASCIIChoice.isSelected()) {
mDataView.append(new String(data) + "\r\n");
new DBSqlite().insertsql(sendname,"在库",mDataInputAdress.getText(),ByteUtils.byteArrayToHexString(data));
}
// 以十六进制的形式接收数据
if (mDataHexChoice.isSelected()) {
mDataView.append(ByteUtils.byteArrayToHexString(data) + "\r\n");
}
}
} catch (Exception e) {
ShowUtils.errorMessage(e.toString());
// 发生读取错误时显示错误信息后退出系统
System.exit(0);
}
}
});
}
发送数据:
这里其实是把要发送的数据作为参数放到数据库了
/**
* 发送数据
*
* @param evt
* 点击事件
*/
private void sendData(java.awt.event.ActionEvent evt) {
// 待发送数据
String data = mDataInput.getText().toString();
if (mSerialport == null) {
ShowUtils.warningMessage("请先打开串口!");
return;
}
if ("".equals(data) || data == null) {
ShowUtils.warningMessage("请输入要发送的数据!");
return;
}
sendname=data;
// 以字符串的形式发送数据
if (mDataASCIIChoice.isSelected()) {
SerialPortManager.sendToPort(mSerialport, data.getBytes());
}
// 以十六进制的形式发送数据
if (mDataHexChoice.isSelected()) {
SerialPortManager.sendToPort(mSerialport, ByteUtils.hexStr2Byte(data));
}
}
数据库操作
这个才是重点我觉得。
我也算是第一次用数据库做东西,但是数据库都是sql语句嘛,逻辑是很好理解的。
而且Java连sqlite的方式比较简单,连接然后执行就行了。
我的函数列表(方法?)
创建数据库:
【UNIQUE,一个表中这个值只允许出现一次;我的是15693的卡号,不允许一张卡出现两次。】
void createSql(){
Connection c = null;
try {
Class.forName("org.sqlite.JDBC");
// 此条语句执行完,如果不存在test.db库,将会自动创建一个test.db文件
c = DriverManager.getConnection("jdbc:sqlite:"+db);
System.out.println("create database success");
// 建表的sql
String sql = "CREATE TABLE Books4 " +
"(ID INTEGER PRIMARY KEY AUTOINCREMENT ," +
" NAME TEXT NOT NULL, " +
" STATUS TEXT NOT NULL, " +
" ADDRESS TEXT NOT NULL , " +
" IDCARD TEXT NOT NULL UNIQUE)";
Statement st = c.createStatement();
// 执行命令
st.executeUpdate(sql);
c.close();
st.close();
} catch ( Exception e ) {
//String sql = "CREATE UNIQUE INDEX ON Books4 (ADDRESS)";
System.err.println( e.getMessage() );
}
}
插入:
public void insertsql(String name,String status,String address,String idcard){
Connection c = null;
Statement stmt = null;
try {
Class.forName("org.sqlite.JDBC");
c = DriverManager.getConnection("jdbc:sqlite:"+db);
c.setAutoCommit(false);
System.out.println("Opened database successfully");
stmt = c.createStatement();
String sql = "INSERT INTO Books4 (NAME,STATUS,ADDRESS,IDCARD) " +
"VALUES ('"+name+"','"+status+"','"+address+"','"+idcard+"');";
stmt.executeUpdate(sql);
stmt.close();
c.commit();
c.close();
} catch ( Exception e ) {
System.err.println( e.getClass().getName() + ": :::" + e.getMessage() );
ShowUtils.errorMessage("卡号已存在,请注意!");
//System.exit(0);
}
System.out.println("Records created successfully");
}
查询:
like是模糊查询,=是限定查询
还可以自己加东西比如:
"select * from Books4 where status = '在库' AND name like '%"+name+"%';"
public String queryname(String name) throws ClassNotFoundException, SQLException {
String text="";
Class.forName("org.sqlite.JDBC");
Connection conn = DriverManager.getConnection("jdbc:sqlite:" + db);
Statement state = conn.createStatement();
ResultSet rs = state.executeQuery("select * from Books4 where name like '%"+name+"%';"); //查询数据
while (rs.next()) { //将查询到的数据打印出来
text=text+"ID = " + rs.getString("ID")
+ "NAME = " + rs.getString("NAME")
+ "STATUS = " + rs.getString("STATUS")
+ "ADDRESS = " + rs.getString("ADDRESS")
+ "IDCARD = " + rs.getString("IDCARD")+"\n";
}
rs.close();
conn.close();
return text;
}
修改:
public String updatastatus(String name) throws ClassNotFoundException, SQLException {
String text="修改成功!书籍信息如下:\n";
Class.forName("org.sqlite.JDBC");
Connection conn = DriverManager.getConnection("jdbc:sqlite:" + db);
Statement state = conn.createStatement();
ResultSet rs = state.executeQuery("select * from Books4 where name= '"+name+"';"); //查询数据
conn.setAutoCommit(false);
while (rs.next()) {
if("在库".equals(rs.getString("STATUS"))){
String sql = "UPDATE Books4 set status = '"+"出库"+"' where ID="+rs.getString("ID")+";";
state.executeUpdate(sql);
conn.commit();
}
else{
String sql = "UPDATE Books4 set status = '"+"在库"+"' where ID="+rs.getString("ID")+";";
state.executeUpdate(sql);
conn.commit();
}
ResultSet rs2 = state.executeQuery("select * from Books4 where name= '"+name+"';"); //查询数据
while (rs2.next()) { //将查询到的数据打印出来
text=text+"ID = " + rs2.getString("ID")
+ "NAME = " + rs2.getString("NAME")
+ "STATUS = " + rs2.getString("STATUS")
+ "ADDRESS = " + rs.getString("ADDRESS")
+"\n";}
}
rs.close();
conn.close();
return text;
}
删除:
public String deletesql(String name){//id,根据id删除
String text="";
Connection c = null;
Statement stmt = null;
try {
Class.forName("org.sqlite.JDBC");
c = DriverManager.getConnection("jdbc:sqlite:"+db);
c.setAutoCommit(false);
System.out.println("Opened database successfully");
stmt = c.createStatement();
String sql = "DELETE from Books4 where NAME='"+name+"';";
stmt.executeUpdate(sql);
c.commit();
text="删除成功!目前全部库存如下:\n"+queryname("");//查询所有数据
stmt.close();
c.close();
} catch ( Exception e ) {
System.err.println( e.getClass().getName() + ": " + e.getMessage() );
System.exit(0);
}
System.out.println("Operation done successfully");
return text;
}
GUI界面设计部分
,有一些乱,学过安卓会比较好理解。
拿其中一个举例。整个大弹窗是一个frame,然后可以包含一些控件(Java里是叫容器吧);上图蓝色框框是一个panel面板,她处于frame里,又包含着button这些控件;他们的位置是由上一级决定的,左上角的坐标是(0,0)
// 程序界面宽度
public final int WIDTH = 530;
// 程序界面高度
public final int HEIGHT = 390;
private JButton querybutton = new JButton("查询");
private JButton deletebutton = new JButton("删除");
private JButton insertbutton = new JButton("增加");
private JButton updatabutton = new JButton("修改");
private JPanel userPanel = new JPanel();
private JTextField inputText=new JTextField();
private JTextArea sqlView = new JTextArea();
private JScrollPane sqlScrollDataView = new JScrollPane(sqlView);
private ButtonGroup mDataChoice = new ButtonGroup();
private JRadioButton statusChoice = new JRadioButton("在库");
private JRadioButton allChoice = new JRadioButton("全部",true);
public ManageFrame() throws SQLException, ClassNotFoundException {
initUserView();
initUserComponents();
actionUserListener();
}
/**
* 初始化窗口:大小,位置,标题
*/
private void initUserView() {
// 关闭程序
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
// 禁止窗口最大化
setResizable(false);
// 设置程序窗口居中显示
Point p = GraphicsEnvironment.getLocalGraphicsEnvironment().getCenterPoint();
setBounds(p.x - WIDTH / 2, p.y - HEIGHT / 2, WIDTH, HEIGHT);
this.setLayout(null);
setTitle("图书管理系统-管理界面-查询");
}
//设置按钮位置
private void initUserComponents() {
// 数据显示
sqlView.setFocusable(false);
sqlScrollDataView.setBounds(10, 10, 505, 200);
add(sqlScrollDataView);
userPanel.setBorder(BorderFactory.createTitledBorder("行使您的管理权限"));
userPanel.setBounds(50, 220, 415, 130);
userPanel.setLayout(null);
add(userPanel);
inputText.setBounds(25, 25, 265, 50);
userPanel.add(inputText);
querybutton.setFocusable(false);
querybutton.setBounds(45, 95, 90, 20);
userPanel.add(querybutton);
statusChoice.setBounds(140, 95, 55, 20);
allChoice.setBounds(200, 95, 55, 20);
mDataChoice.add(statusChoice);
mDataChoice.add(allChoice);
userPanel.add(statusChoice);
userPanel.add(allChoice);
deletebutton.setFocusable(false);
deletebutton.setBounds(300, 15, 90, 30);
userPanel.add(deletebutton);
insertbutton.setFocusable(false);
insertbutton.setBounds(300, 55, 90, 30);
userPanel.add(insertbutton);
updatabutton.setFocusable(false);
updatabutton.setBounds(300, 95, 90, 30);
userPanel.add(updatabutton);
}
然后是按钮的监听事件,也是数据库执行的地方了。
【查询很长,但是是因为我分类比较多,其实可以去掉一半的,但是程序员的代码往往不敢动。反正每一个if与else里都是相同的东西。甚至可以只看前两个。】
querybutton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if ("".equals(inputText.getText().toString()) ) {//选择页面
if(statusChoice.isSelected()){//选中在库
try {
sqlView.setText(new DBSqlite().querystatusandname(inputText.getText().toString()));
} catch (ClassNotFoundException classNotFoundException) {
classNotFoundException.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}else{
try {
sqlView.setText(new DBSqlite().queryname(inputText.getText().toString()));
} catch (ClassNotFoundException classNotFoundException) {
classNotFoundException.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
else {
if(statusChoice.isSelected()){
try {
sqlView.setText(new DBSqlite().querystatusandname(inputText.getText().toString()));
} catch (ClassNotFoundException classNotFoundException) {
classNotFoundException.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}else{
try {
sqlView.setText(new DBSqlite().queryname(inputText.getText().toString()));
} catch (ClassNotFoundException classNotFoundException) {
classNotFoundException.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
});
删除比较简单,就是获得输入的字符串然后调用删除就行了。
deletebutton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if ("".equals(inputText.getText().toString()) ) {//选择页面
ShowUtils.warningMessage("请输入要删除的书籍名!");
} else {
sqlView.setText(new DBSqlite().deletesql(inputText.getText().toString())) ;
}
}
});
更新我这里只贴一段,就是输入名字点击更新按钮,可以把状态改成相反的状态。if语句块是进入了另一个页面了,另一个页面是输入旧信息和新信息,后台把所有查到的名字或者位置都更新。
updatabutton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if ("".equals(inputText.getText().toString()) ) {
//选择页面
try {
new updateFrame().setVisible(true);
} catch (SQLException throwables) {
throwables.printStackTrace();
} catch (ClassNotFoundException classNotFoundException) {
classNotFoundException.printStackTrace();
}
}else{
try {
sqlView.setText(new DBSqlite().updatastatus(inputText.getText()));
} catch (ClassNotFoundException classNotFoundException) {
classNotFoundException.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
});
插入的是调用串口的那一段代码,前面已经写过。
基本上就这些吧
还有8u101的jdk和sqlite的jar包
https://pan.baidu.com/s/1pzKIT0ZNBxiHRMcq01iJTg#list/path=%2F
提取码:xega