圖一:
圖二:
提問:圖一圖二可不可以都用下面的代碼獲取數據:(圖二可以用下面的代碼獲取數據,但是圖一不知道行不行,請各位大佬路過看看)
package com.lyf.test2;
import java.awt.Button;
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.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JOptionPane;
import com.lyf.test2.SerialTool;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import serialException.ExceptionWriter;
import serialException.NoSuchPort;
import serialException.NotASerialPort;
import serialException.PortInUse;
import serialException.ReadDataFromSerialPortFailure;
import serialException.SendDataToSerialPortFailure;
import serialException.SerialPortInputStreamCloseFailure;
import serialException.SerialPortOutputStreamCloseFailure;
import serialException.SerialPortParameterFailure;
import serialException.TooManyListeners;
/**
* 主程序
* @author zhong
*
*/
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;
private static SerialPort serialPort = null; //保存串口对象
private Font font = new Font("微软雅黑", Font.BOLD, 25);//文本框字體
private Label weight = new Label("暫無數據", Label.CENTER); //重量
private Button saveButton = new Button("保存");//设置button按钮
Image offScreen = null; //用于双缓冲
//设置window的icon(这里我自定义了一下Windows窗口的icon图标,因为实在觉得哪个小咖啡图标不好看 = =)
Toolkit toolKit = getToolkit();//返回此窗体的工具包
Image icon = toolKit.getImage(Client.class.getResource("computer.png"));//獲取當前類所在的包下面的圖片
/**
* 主方法
* @param args
* @throws SerialPortOutputStreamCloseFailure
* @throws SendDataToSerialPortFailure
* @throws PortInUse
* @throws NoSuchPort
* @throws NotASerialPort
* @throws SerialPortParameterFailure
*/
public static void main(String[] args) throws SendDataToSerialPortFailure, SerialPortOutputStreamCloseFailure, SerialPortParameterFailure, NotASerialPort, NoSuchPort, PortInUse {
new Client().launchFrame();
}
/**
* 主菜单窗口显示;
* 添加Label、按钮、下拉条及相关事件监听;
*/
public void launchFrame() {
this.setBounds(LOC_X, LOC_Y, WIDTH, 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);
}
});
//设置文本框位置、背景颜色、是否粗体、字体颜色
weight.setBounds(140, 103, 225, 50);
weight.setBackground(Color.black);
weight.setFont(font);
weight.setForeground(Color.white);
add(weight);
//添加保存按钮
saveButton.setBounds(250, 490, 300, 50);
saveButton.setBackground(Color.lightGray);
saveButton.setFont(new Font("微软雅黑", Font.BOLD, 20));
saveButton.setForeground(Color.darkGray);
add(saveButton);
//添加打开串口按钮的事件监听
try {
//指定端口名及波特率的串口对象
serialPort = SerialTool.openPort("COM1", 4800);
//在该串口对象上添加监听器
SerialTool.addListener(serialPort, new SerialListener());
} catch (SerialPortParameterFailure | NotASerialPort | NoSuchPort | PortInUse | TooManyListeners e1) {
//发生错误时使用一个Dialog提示具体的错误信息
JOptionPane.showMessageDialog(null, e1, "错误", JOptionPane.INFORMATION_MESSAGE);
}
this.setResizable(false);//设置此框架是否可由用户调整大小。
this.setVisible(true); //显示窗口
new Thread(new RepaintThread()).start(); //启动重画线程
}
/**
* 画出主界面组件元素
* 设置button的字体颜色、设置字体样式 是否粗体 字体大小、文本、位置
*/
public void paint(Graphics g) {
g.setColor(Color.black);
g.setFont(new Font("微软雅黑", Font.BOLD, 25));
g.drawString(" 重量: ", 45, 130);
}
/**
* 双缓冲方式重画界面各元素组件
*/
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); //将新画好的画布“贴”在原画布上
}
/**
* 以内部类形式创建一个串口监听类
* @author zhong
*
*/
private class SerialListener implements SerialPortEventListener {
/**
* 处理监控到的串口事件
*/
public void serialEvent(SerialPortEvent serialPortEvent) {
try {
// 等待1秒钟让串口把数据全部接收后在处理
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
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 串口存在可用数据
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) { //检查数据是否读取正确
try {
weight.setText(new String(data) + " g");
} catch (ArrayIndexOutOfBoundsException e) {
JOptionPane.showMessageDialog(null, "数据解析过程出错,更新界面数据失败!请检查设备或程序!", "错误", JOptionPane.INFORMATION_MESSAGE);
System.exit(0);
}
}else {
JOptionPane.showMessageDialog(null, "读取数据过程中未获取到有效数据!请检查设备或程序!", "错误", JOptionPane.INFORMATION_MESSAGE);
System.exit(0);
}
}
} catch (ReadDataFromSerialPortFailure | SerialPortInputStreamCloseFailure e) {
JOptionPane.showMessageDialog(null, e, "错误", JOptionPane.INFORMATION_MESSAGE);
System.exit(0); //发生读取错误时显示错误信息后退出系统
}
break;
}
}
}
/**
* 重画线程(每隔30毫秒重画一次)
*/
private class RepaintThread implements Runnable {
public void run() {
while(true) {
//调用重画方法
repaint();
try {
Thread.sleep(30);
} catch (InterruptedException e) {
String err = ExceptionWriter.getErrorInfoFromException(e);
JOptionPane.showMessageDialog(null, err, "错误", JOptionPane.INFORMATION_MESSAGE);
System.exit(0);
}
}
}
}
}
package com.lyf.test2;
import java.io.IOException;
import java.io.InputStream;
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;
import serialException.*;
/**
* 串口服务类,提供打开、关闭串口,读取、发送串口数据等服务(采用单例设计模式)
* @author zhong
*
*/
public class SerialTool {
private static SerialTool serialTool = null;
static {
//在该类被ClassLoader加载时就初始化一个SerialTool对象
if (serialTool == null) {
serialTool = new SerialTool();
}
}
//私有化SerialTool类的构造方法,不允许其他类生成SerialTool对象
private SerialTool() {}
/**
* 获取提供服务的SerialTool对象
* @return serialTool
*/
public static SerialTool getSerialTool() {
if (serialTool == null) {
serialTool = new SerialTool();
}
return serialTool;
}
/**
* 打开串口
* @param portName 端口名称
* @param baudrate 波特率
* @return 串口对象
* @throws SerialPortParameterFailure 设置串口参数失败
* @throws NotASerialPort 端口指向设备不是串口类型
* @throws NoSuchPort 没有该端口对应的串口设备
* @throws PortInUse 端口已被占用
*/
public static final SerialPort openPort(String portName, int baudrate) throws SerialPortParameterFailure, NotASerialPort, NoSuchPort, PortInUse {
try {
//通过端口名识别端口
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
//打开端口,并给端口名字和一个timeout(打开操作的超时时间)
CommPort commPort = portIdentifier.open(portName, 2000);
//判断是不是串口
if (commPort instanceof SerialPort) {
SerialPort serialPort = (SerialPort) commPort;
try {
//设置一下串口的波特率等参数
serialPort.setSerialPortParams(baudrate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
} catch (UnsupportedCommOperationException e) {
throw new SerialPortParameterFailure();
}
//System.out.println("Open " + portName + " sucessfully !");
return serialPort;
} else {
//不是串口
throw new NotASerialPort();
}
} catch (NoSuchPortException e1) {
throw new NoSuchPort();
} catch (PortInUseException e2) {
throw new PortInUse();
}
}
/**
* 关闭串口
* @param serialport 待关闭的串口对象
*/
public static void closePort(SerialPort serialPort) {
if (serialPort != null) {
serialPort.close();
serialPort = null;
}
}
/**
* 从串口读取数据
* @param serialPort 当前已建立连接的SerialPort对象
* @return 读取到的数据
* @throws ReadDataFromSerialPortFailure 从串口读取数据时出错
* @throws SerialPortInputStreamCloseFailure 关闭串口对象输入流出错
*/
public static byte[] readFromPort(SerialPort serialPort) throws ReadDataFromSerialPortFailure, SerialPortInputStreamCloseFailure {
InputStream in = null;
byte[] bytes = null;
try {
in = serialPort.getInputStream();//取入数据
int bufflenth = in.available(); //获取buffer里的数据长度
while (bufflenth != 0) {
bytes = new byte[bufflenth]; //初始化byte数组为buffer中数据的长度
in.read(bytes);
bufflenth = in.available();
}
} catch (IOException e) {
throw new ReadDataFromSerialPortFailure();
} finally {
try {
if (in != null) {
in.close();
in = null;
}
} catch(IOException e) {
throw new SerialPortInputStreamCloseFailure();
}
}
return bytes;
}
/**
* 添加监听器
* @param port 串口对象
* @param listener 串口监听器
* @throws TooManyListeners 监听类对象过多
*/
public static void addListener(SerialPort port, SerialPortEventListener listener) throws TooManyListeners {
try {
//给串口添加监听器
port.addEventListener(listener);
//设置当有数据到达时唤醒监听接收线程
port.notifyOnDataAvailable(true);
//设置当通信中断时唤醒中断线程
port.notifyOnBreakInterrupt(true);
} catch (TooManyListenersException e) {
throw new TooManyListeners();
}
}
}