Open houyouliang opened 7 years ago
package com.usb.usbtest;
import java.awt.Button; import java.awt.Choice; import java.awt.Color; import java.awt.Font; import java.awt.Frame; import java.awt.Graphics; import java.awt.Image; import java.awt.Label; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.List;
import javax.swing.JOptionPane;
import gnu.io.SerialPort; import gnu.io.SerialPortEvent; import gnu.io.SerialPortEventListener;
/**
*/ public class DataView extends Frame {
/**
*/ private static final long serialVersionUID = 1L;
Client client = null;
private List
private Font font = new Font("微软雅黑", Font.BOLD, 25);
private Label tem = new Label("暂无数据", Label.CENTER); //温度 private Label hum = new Label("暂无数据", Label.CENTER); //湿度 private Label pa = new Label("暂无数据", Label.CENTER); //压强 private Label rain = new Label("暂无数据", Label.CENTER); //雨量 private Label win_sp = new Label("暂无数据", Label.CENTER); //风速 private Label win_dir = new Label("暂无数据", Label.CENTER); //风向
private Choice commChoice = new Choice(); //串口选择(下拉框) private Choice bpsChoice = new Choice(); //波特率选择
private Button openSerialButton = new Button("打开串口");
Image offScreen = null; //重画时的画布
//设置window的icon //Toolkit toolKit = getToolkit(); //Image icon = toolKit.getImage(DataView.class.getResource("computer.png"));
/**
/**
添加Label、按钮、下拉条及相关事件监听; */ public void dataFrame() { this.setBounds(client.LOC_X, client.LOC_Y, client.WIDTH, client.HEIGHT); this.setTitle("CDIO工程项目"); //this.setIconImage(icon); this.setBackground(Color.white); this.setLayout(null);
this.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent arg0) { if (serialPort != null) { //程序退出时关闭串口释放资源 SerialTool.closePort(serialPort); } System.exit(0); }
});
tem.setBounds(140, 103, 225, 50); tem.setBackground(Color.black); tem.setFont(font); tem.setForeground(Color.white); add(tem);
hum.setBounds(520, 103, 225, 50); hum.setBackground(Color.black); hum.setFont(font); hum.setForeground(Color.white); add(hum);
pa.setBounds(140, 193, 225, 50); pa.setBackground(Color.black); pa.setFont(font); pa.setForeground(Color.white); add(pa);
rain.setBounds(520, 193, 225, 50); rain.setBackground(Color.black); rain.setFont(font); rain.setForeground(Color.white); add(rain);
win_sp.setBounds(140, 283, 225, 50); win_sp.setBackground(Color.black); win_sp.setFont(font); win_sp.setForeground(Color.white); add(win_sp);
win_dir.setBounds(520, 283, 225, 50); win_dir.setBackground(Color.black); win_dir.setFont(font); win_dir.setForeground(Color.white); add(win_dir);
//添加串口选择选项 commChoice.setBounds(160, 397, 200, 200); //检查是否有可用串口,有则加入选项中 if (commList == null || commList.size()<1) { JOptionPane.showMessageDialog(null, "没有搜索到有效串口!", "错误", JOptionPane.INFORMATION_MESSAGE); } else { for (String s : commList) { commChoice.add(s); } } add(commChoice);
//添加波特率选项 bpsChoice.setBounds(526, 396, 200, 200); bpsChoice.add("1200"); bpsChoice.add("2400"); bpsChoice.add("4800"); bpsChoice.add("9600"); bpsChoice.add("14400"); bpsChoice.add("19200"); bpsChoice.add("115200"); add(bpsChoice);
//添加打开串口按钮 openSerialButton.setBounds(250, 490, 300, 50); openSerialButton.setBackground(Color.lightGray); openSerialButton.setFont(new Font("微软雅黑", Font.BOLD, 20)); openSerialButton.setForeground(Color.darkGray); add(openSerialButton); //添加打开串口按钮的事件监听 openSerialButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//获取串口名称
String commName = commChoice.getSelectedItem();
//获取波特率
String bpsStr = bpsChoice.getSelectedItem();
//检查串口名称是否获取正确
if (commName == null || commName.equals("")) {
JOptionPane.showMessageDialog(null, "没有搜索到有效串口!", "错误", JOptionPane.INFORMATION_MESSAGE);
}
else {
//检查波特率是否获取正确
if (bpsStr == null || bpsStr.equals("")) {
JOptionPane.showMessageDialog(null, "波特率获取错误!", "错误", JOptionPane.INFORMATION_MESSAGE);
}
else {
//串口名、波特率均获取正确时
int bps = Integer.parseInt(bpsStr);
try {
//获取指定端口名及波特率的串口对象
serialPort = SerialTool.openPort(commName, bps);
//在该串口对象上添加监听器
SerialTool.addListener(serialPort, new SerialListener());
//监听成功进行提示
JOptionPane.showMessageDialog(null, "监听成功,稍后将显示监测数据!", "提示", JOptionPane.INFORMATION_MESSAGE);
} catch (Exception e1) {
//发生错误时使用一个Dialog提示具体的错误信息
JOptionPane.showMessageDialog(null, e1, "错误", JOptionPane.INFORMATION_MESSAGE);
}
}
}
}
});
this.setResizable(false);
new Thread(new RepaintThread()).start(); //启动重画线程
}
/**
画出主界面组件元素 */ public void paint(Graphics g) { Color c = g.getColor();
g.setColor(Color.black); g.setFont(new Font("微软雅黑", Font.BOLD, 25)); g.drawString(" 温度: ", 45, 130);
g.setColor(Color.black); g.setFont(new Font("微软雅黑", Font.BOLD, 25)); g.drawString(" 湿度: ", 425, 130);
g.setColor(Color.black); g.setFont(new Font("微软雅黑", Font.BOLD, 25)); g.drawString(" 压强: ", 45, 220);
g.setColor(Color.black); g.setFont(new Font("微软雅黑", Font.BOLD, 25)); g.drawString(" 雨量: ", 425, 220);
g.setColor(Color.black); g.setFont(new Font("微软雅黑", Font.BOLD, 25)); g.drawString(" 风速: ", 45, 310);
g.setColor(Color.black); g.setFont(new Font("微软雅黑", Font.BOLD, 25)); g.drawString(" 风向: ", 425, 310);
g.setColor(Color.gray); g.setFont(new Font("微软雅黑", Font.BOLD, 20)); g.drawString(" 串口选择: ", 45, 410);
g.setColor(Color.gray); g.setFont(new Font("微软雅黑", Font.BOLD, 20)); g.drawString(" 波特率: ", 425, 410);
}
/**
/*
重画线程(每隔30毫秒重画一次) */ private class RepaintThread implements Runnable { public void run() { while(true) { //调用重画方法 repaint();
//扫描可用串口
commList = SerialTool.findPort();
if (commList != null && commList.size()>0) {
//添加新扫描到的可用串口
for (String s : commList) {
//该串口名是否已存在,初始默认为不存在(在commList里存在但在commChoice里不存在,则新添加)
boolean commExist = false;
for (int i=0; i<commChoice.getItemCount(); i++) {
if (s.equals(commChoice.getItem(i))) {
//当前扫描到的串口名已经在初始扫描时存在
commExist = true;
break;
}
}
if (commExist) {
//当前扫描到的串口名已经在初始扫描时存在,直接进入下一次循环
continue;
}
else {
//若不存在则添加新串口名至可用串口下拉列表
commChoice.add(s);
}
}
//移除已经不可用的串口
for (int i=0; i<commChoice.getItemCount(); i++) {
//该串口是否已失效,初始默认为已经失效(在commChoice里存在但在commList里不存在,则已经失效)
boolean commNotExist = true;
for (String s : commList) {
if (s.equals(commChoice.getItem(i))) {
commNotExist = false;
break;
}
}
if (commNotExist) {
//System.out.println("remove" + commChoice.getItem(i));
commChoice.remove(i);
}
else {
continue;
}
}
}
else {
//如果扫描到的commList为空,则移除所有已有串口
commChoice.removeAll();
}
try {
Thread.sleep(30);
} catch (InterruptedException e) {
String err = e.getMessage();
JOptionPane.showMessageDialog(null, err, "错误", JOptionPane.INFORMATION_MESSAGE);
System.exit(0);
}
}
}
}
/**
*/ private class SerialListener implements SerialPortEventListener {
/**
处理监控到的串口事件 */ public void serialEvent(SerialPortEvent serialPortEvent) {
switch (serialPortEvent.getEventType()) {
case SerialPortEvent.BI: // 10 通讯中断
JOptionPane.showMessageDialog(null, "与串口设备通讯中断", "错误", JOptionPane.INFORMATION_MESSAGE);
break;
case SerialPortEvent.OE: // 7 溢位(溢出)错误
case SerialPortEvent.FE: // 9 帧错误
case SerialPortEvent.PE: // 8 奇偶校验错误
case SerialPortEvent.CD: // 6 载波检测
case SerialPortEvent.CTS: // 3 清除待发送数据
case SerialPortEvent.DSR: // 4 待发送数据准备好了
case SerialPortEvent.RI: // 5 振铃指示
case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 2 输出缓冲区已清空
break;
case SerialPortEvent.DATA_AVAILABLE: // 1 串口存在可用数据
//System.out.println("found data");
byte[] data = null;
try {
if (serialPort == null) {
JOptionPane.showMessageDialog(null, "串口对象为空!监听失败!", "错误", JOptionPane.INFORMATION_MESSAGE);
}
else {
data = SerialTool.readFromPort(serialPort); //读取数据,存入字节数组
//System.out.println(new String(data));
// 自定义解析过程,你在实际使用过程中可以按照自己的需求在接收到数据后对数据进行解析
if (data == null || data.length < 1) { //检查数据是否读取正确
JOptionPane.showMessageDialog(null, "读取数据过程中未获取到有效数据!请检查设备或程序!", "错误", JOptionPane.INFORMATION_MESSAGE);
System.exit(0);
}
else {
String dataOriginal = new String(data); //将字节数组数据转换位为保存了原始数据的字符串
String dataValid = ""; //有效数据(用来保存原始数据字符串去除最开头*号以后的字符串)
String[] elements = null; //用来保存按空格拆分原始字符串后得到的字符串数组
//解析数据
if (dataOriginal.charAt(0) == '*') { //当数据的第一个字符是*号时表示数据接收完成,开始解析
dataValid = dataOriginal.substring(1);
elements = dataValid.split(" ");
if (elements == null || elements.length < 1) { //检查数据是否解析正确
JOptionPane.showMessageDialog(null, "数据解析过程出错,请检查设备或程序!", "错误", JOptionPane.INFORMATION_MESSAGE);
System.exit(0);
}
else {
try {
//更新界面Label值
/*for (int i=0; i<elements.length; i++) {
System.out.println(elements[i]);
}*/
//System.out.println("win_dir: " + elements[5]);
tem.setText(elements[0] + " ℃");
hum.setText(elements[1] + " %");
pa.setText(elements[2] + " hPa");
rain.setText(elements[3] + " mm");
win_sp.setText(elements[4] + " m/s");
win_dir.setText(elements[5] + " °");
} catch (ArrayIndexOutOfBoundsException e) {
JOptionPane.showMessageDialog(null, "数据解析过程出错,更新界面数据失败!请检查设备或程序!", "错误", JOptionPane.INFORMATION_MESSAGE);
System.exit(0);
}
}
}
}
}
} catch (Exception e) {
JOptionPane.showMessageDialog(null, e.getMessage(), "错误", JOptionPane.INFORMATION_MESSAGE);
System.exit(0); //发生读取错误时显示错误信息后退出系统
}
break;
}
}
}
}
package com.usb.usbtest;
import java.awt.Color; import java.awt.Font; import java.awt.Frame; import java.awt.Graphics; import java.awt.Image; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent;
import javax.swing.JOptionPane;
public class Client extends Frame{
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* 程序界面宽度
*/
public static final int WIDTH = 800;
/**
* 程序界面高度
*/
public static final int HEIGHT = 620;
/**
* 程序界面出现位置(横坐标)
*/
public static final int LOC_X = 200;
/**
* 程序界面出现位置(纵坐标)
*/
public static final int LOC_Y = 70;
Color color = Color.WHITE;
Image offScreen = null; //用于双缓冲
//设置window的icon(这里我自定义了一下Windows窗口的icon图标,因为实在觉得哪个小咖啡图标不好看 = =)
// Toolkit toolKit = getToolkit(); //Image icon = toolKit.getImage(Client.class.getResource("computer.png"));
//持有其他类
DataView dataview = new DataView(this); //主界面类(显示监控数据主面板)
/**
* 主方法
* @param args //
*/
public static void main(String[] args) {
new Client().launchFrame();
}
/**
* 显示主界面
*/
public void launchFrame() {
this.setBounds(LOC_X, LOC_Y, WIDTH, HEIGHT); //设定程序在桌面出现的位置
this.setTitle("CDIO工程项目"); //设置程序标题
//this.setIconImage(icon);
this.setBackground(Color.white); //设置背景色
this.addWindowListener(new WindowAdapter() {
//添加对窗口状态的监听
public void windowClosing(WindowEvent arg0) {
//当窗口关闭时
System.exit(0); //退出程序
}
});
this.addKeyListener(new KeyMonitor()); //添加键盘监听器
this.setResizable(false); //窗口大小不可更改
this.setVisible(true); //显示窗口
new Thread(new RepaintThread()).start(); //开启重画线程
}
/**
* 画出程序界面各组件元素
*/
public void paint(Graphics g) {
Color c = g.getColor();
g.setFont(new Font("微软雅黑", Font.BOLD, 40));
g.setColor(Color.black);
g.drawString("欢迎使用上位机实时监控系统", 45, 190);
g.setFont(new Font("微软雅黑", Font.ITALIC, 26));
g.setColor(Color.BLACK);
g.drawString("Version:1.0 Powered By:ZhongLei", 280, 260);
g.setFont(new Font("微软雅黑", Font.BOLD, 30));
g.setColor(color);
g.drawString("————点击Enter键进入主界面————", 100, 480);
//使文字 "————点击Enter键进入主界面————" 黑白闪烁
if (color == Color.WHITE) color = Color.black;
else if (color == color.BLACK) color = Color.white;
}
/**
* 双缓冲方式重画界面各元素组件
*/
public void update(Graphics g) {
if (offScreen == null) offScreen = this.createImage(WIDTH, HEIGHT);
Graphics gOffScreen = offScreen.getGraphics();
Color c = gOffScreen.getColor();
gOffScreen.setColor(Color.white);
gOffScreen.fillRect(0, 0, WIDTH, HEIGHT); //重画背景画布
this.paint(gOffScreen); //重画界面元素
gOffScreen.setColor(c);
g.drawImage(offScreen, 0, 0, null); //将新画好的画布“贴”在原画布上
}
/*
* 内部类形式实现对键盘事件的监听
*/
private class KeyMonitor extends KeyAdapter {
public void keyReleased(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == KeyEvent.VK_ENTER) { //当监听到用户敲击键盘enter键后执行下面的操作
setVisible(false); //隐去欢迎界面
dataview.setVisible(true); //显示监测界面
dataview.dataFrame(); //初始化监测界面
}
}
}
/*
* 重画线程(每隔250毫秒重画一次)
*/
private class RepaintThread implements Runnable {
public void run() {
while(true) {
repaint();
try {
Thread.sleep(250);
} catch (InterruptedException e) {
//重画线程出错抛出异常时创建一个Dialog并显示异常详细信息
String err = e.getMessage();
JOptionPane.showMessageDialog(null, err, "错误", JOptionPane.INFORMATION_MESSAGE);
System.exit(0);
}
}
}
}
}
RXTXcomm.jar 需要jar
package com.usb.usbtest;
import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.TooManyListenersException;
import gnu.io.CommPort; import gnu.io.CommPortIdentifier; import gnu.io.NoSuchPortException; import gnu.io.PortInUseException; import gnu.io.SerialPort; import gnu.io.SerialPortEventListener; import gnu.io.UnsupportedCommOperationException;
public class SerialTool { private SerialTool() { }
}