
代码
import com.fazecast.jSerialComm.SerialPort;
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ScaleDialogForm extends JDialog {
private SerialPort serialPort;
private List<BigDecimal> recentWeights = new ArrayList<>(6);
private BigDecimal stableWeight = new BigDecimal(-1);
private String portName;
private JLabel lblCurrentWeight;
private JLabel lblStatus;
private boolean isRunning = true;
// 构造函数:接收串口号和窗口标题
public ScaleDialogForm(Frame parent, String portName, String title) {
super(parent, title, true);
this.portName = portName;
initUI();
setupWindowListener();
startSerialThread();
}
// 初始化界面
private void initUI() {
setSize(300, 200);
setResizable(false);
setLayout(new BorderLayout(10, 10));
setLocationRelativeTo(null); // 居中显示
// 重量显示区域
JPanel weightPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
weightPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 0, 20));
weightPanel.add(new JLabel("当前重量:"));
lblCurrentWeight = new JLabel("-- kg");
weightPanel.add(lblCurrentWeight);
add(weightPanel, BorderLayout.NORTH);
// 状态标签
JPanel statusPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
statusPanel.setBorder(BorderFactory.createEmptyBorder(0, 20, 0, 20));
lblStatus = new JLabel("等待数据稳定(连续6次相同值)...");
statusPanel.add(lblStatus);
add(statusPanel, BorderLayout.CENTER);
// 取消按钮
JPanel btnPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
btnPanel.setBorder(BorderFactory.createEmptyBorder(0, 20, 20, 20));
JButton cancelBtn = new JButton("取消");
cancelBtn.addActionListener(e -> closeDialog());
btnPanel.add(cancelBtn);
add(btnPanel, BorderLayout.SOUTH);
}
// 设置窗口关闭监听
private void setupWindowListener() {
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
closeDialog();
}
});
}
// 启动串口处理线程
private void startSerialThread() {
Thread serialThread = new Thread(this::initSerial);
serialThread.setDaemon(true);
serialThread.start();
}
// 初始化串口
private void initSerial() {
// 获取指定串口
serialPort = SerialPort.getCommPort(portName);
// 配置串口参数
serialPort.setBaudRate(9600);
serialPort.setNumDataBits(8);
serialPort.setNumStopBits(1);
serialPort.setParity(SerialPort.NO_PARITY);
serialPort.setComPortTimeouts(SerialPort.TIMEOUT_READ_SEMI_BLOCKING, 500, 0);
// 打开串口
if (!serialPort.openPort()) {
SwingUtilities.invokeLater(() -> {
JOptionPane.showMessageDialog(this,
"串口 " + portName + " 打开失败",
"错误",
JOptionPane.ERROR_MESSAGE);
dispose();
});
return;
}
// 更新状态
SwingUtilities.invokeLater(() ->
lblStatus.setText("串口 " + portName + " 已打开,等待数据..."));
// 读取数据
readSerialData();
}
// 读取串口数据
private void readSerialData() {
byte[] buffer = new byte[1024];
while (isRunning && serialPort.isOpen()) {
int bytesRead = serialPort.readBytes(buffer, buffer.length);
if (bytesRead > 0) {
String data = new String(buffer, 0, bytesRead).trim();
if (!data.isEmpty()) {
BigDecimal weight = tryParseWeight(data);
if (weight != null) {
// 更新当前重量显示
SwingUtilities.invokeLater(() ->
lblCurrentWeight.setText(weight + " kg"));
checkStableWeight(weight);
}
}
}
}
}
// 解析重量数据
private BigDecimal tryParseWeight(String data) {
// 提取数字部分(支持整数、小数)
Pattern pattern = Pattern.compile("[-+]?\\d+\\.?\\d*");
Matcher matcher = pattern.matcher(data);
if (matcher.find()) {
try {
return new BigDecimal(matcher.group());
} catch (NumberFormatException e) {
return null;
}
}
return null;
}
// 检查是否连续6次相同重量
private void checkStableWeight(BigDecimal currentWeight) {
synchronized (recentWeights) {
// 保持最近6条数据
if (recentWeights.size() >= 6) {
recentWeights.remove(0);
}
recentWeights.add(currentWeight);
// 检查是否稳定
if (recentWeights.size() == 6 && allEqual()) {
stableWeight = currentWeight;
closeDialog();
// 显示稳定状态后关闭
SwingUtilities.invokeLater(() -> {
lblStatus.setText("数据稳定:" + stableWeight + " kg,自动确认中...");
new Thread(() -> {
try {
Thread.sleep(1000); // 延迟1秒关闭
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
SwingUtilities.invokeLater(this::dispose);
}).start();
});
}
}
}
// 检查列表中所有元素是否相等
private boolean allEqual() {
BigDecimal first = recentWeights.get(0);
for (BigDecimal weight : recentWeights) {
if (!weight.equals(first)) {
return false;
}
}
return true;
}
// 获取稳定后的重量
public BigDecimal getStableWeight() {
return stableWeight;
}
// 关闭对话框及资源
private void closeDialog() {
isRunning = false;
if (serialPort != null && serialPort.isOpen()) {
serialPort.closePort();
}
}
public static void main(String[] args) {
// 示例:传入串口号"COM3"和标题"生鲜电子秤采集"
SwingUtilities.invokeLater(() -> {
ScaleDialogForm dialog = new ScaleDialogForm(null, "COM3", "生鲜电子秤采集");
dialog.setVisible(true);
BigDecimal weight = dialog.getStableWeight();
if (weight.compareTo(new BigDecimal(-1)) != 0) {
JOptionPane.showMessageDialog(null,
"最终稳定重量:" + weight + " kg",
"采集完成",
JOptionPane.INFORMATION_MESSAGE);
}
});
}
}
实现说明:
-
依赖库:
- 使用
jSerialComm处理串口通信,需要添加依赖:- Maven:
xml
<dependency> <groupId>com.fazecast</groupId> <artifactId>jSerialComm</artifactId> <version>2.9.2</version> </dependency> - 或直接下载 JAR 包:
- Maven:
- 使用
-
功能特点:
- 完全实现原 C# 版本的所有功能,包括串口通信、数据解析和稳定性检测
- 使用 Swing 构建桌面界面,保持与原程序相似的布局
- 采用多线程处理串口数据,避免 UI 卡顿
- 使用
BigDecimal处理重量数据,确保精度 - 完善的资源释放和错误处理
-
使用方法:
- 添加 jSerialComm 依赖
- 根据实际电子秤的串口号修改
main方法中的"COM3" - 运行程序,窗口会显示当前重量和状态
- 连续 6 次读取到相同重量时自动确认并关闭
- 可通过 "取消" 按钮终止采集
-
注意事项:
- 数据解析逻辑(
tryParseWeight方法)可能需要根据电子秤的实际协议调整 - 串口参数(波特率等)需与电子秤匹配
- Linux 系统中串口号格式为
/dev/ttyUSB0,Mac 系统为/dev/cu.usbserial-*
- 数据解析逻辑(
该实现保持了原程序的逻辑结构,同时遵循了 Java Swing 的编程规范,确保了良好的用户体验和稳定性。
在现代科技领域,利用 Java 进行电子秤数据读取具有不可忽视的重要性。它不仅为众多行业提供了精确计量的有力支持,还凭借 Java 自身的特性,在多样化的场景中发挥着关键作用。
Java 电子秤读取的重要意义
- 精度与可靠性:Java 提供了强大的数值处理类,如
BigDecimal,在处理电子秤数据时能够确保高精度和准确性。代码中使用BigDecimal来处理重量数据,有效避免了浮点数运算带来的精度损失,保证了计量的可靠性,这在对重量精度要求极高的场景中至关重要。 - 跨平台性:Java 的 “一次编写,到处运行” 特性,使其可以在不同操作系统上运行电子秤读取程序,无论是 Windows、Linux 还是 macOS。这极大地提高了程序的通用性和可移植性,满足了不同用户在各种环境下的需求。
- 面向对象编程优势:Java 的面向对象编程范式使代码结构清晰、易于维护和扩展。在电子秤读取程序中,通过类和对象的设计,如
ScaleDialogForm类封装了串口操作、数据处理和界面展示等功能,使得代码逻辑清晰,便于开发人员理解和修改,也有利于后续功能的添加和优化。
10 个应用场景
- 商业零售:在超市、便利店等零售场所,电子秤与 Java 程序结合,可快速准确地获取商品重量,自动计算价格并生成标签。例如,生鲜区的电子秤读取重量后,Java 程序将其与价格信息整合,打印出包含重量、单价、总价的标签,提高结算效率和准确性。
- 工业制造:制造业中,电子秤用于对零部件、原材料及成品进行称重检测。Java 程序读取数据,可实时监控产品重量是否符合质量标准,实现自动化质量控制。如汽车制造过程中,对发动机部件进行称重,确保其重量在公差范围内,保证产品质量。
- 物流与仓储:物流行业利用电子秤称重包裹,Java 程序读取重量数据并与物流管理系统集成,实现运费计算、库存管理和包裹追踪等功能。例如,仓库管理系统通过读取电子秤数据,实时更新库存货物的重量信息,便于库存盘点和物流调度。
- 食品加工:食品加工厂中,精确的配料称重是保证产品质量和口味一致性的关键。Java 读取电子秤数据,可按照预设配方准确控制原材料用量,实现自动化生产流程。例如,面包制作过程中,严格控制面粉、水、酵母等原料的重量,确保每批次产品质量稳定。
- 制药行业:药品生产对重量精度要求极高,任何微小的误差都可能影响药品疗效和安全性。Java 电子秤读取程序用于对药品原料、中间体和成品进行称重,确保剂量准确。如胶囊填充过程中,精确控制药物粉末的重量,保证药品质量。
- 科研实验:在科研实验室中,电子秤用于精确称量化学试剂、生物样本等。Java 程序读取重量数据,自动记录实验数据并进行分析,提高实验效率和准确性。例如,化学实验中,通过 Java 程序读取电子秤数据,实时记录反应物质的重量变化,辅助实验结果分析。
- 珠宝鉴定:珠宝的价值与重量密切相关,高精度电子秤结合 Java 程序读取重量数据,为珠宝鉴定和定价提供准确依据。在珠宝交易过程中,确保重量测量的精确性,保障交易双方的利益。
- 农业生产:在农产品收购、加工环节,电子秤称重结合 Java 程序,可实现农产品产量统计、质量分级和收购价格计算。例如,水果收购时,根据电子秤读取的重量和质量等级,自动计算收购价格,提高交易效率。
- 环保回收:废品回收站利用电子秤称重回收物品,Java 程序读取重量数据,统计回收量并计算回收费用。同时,还可与环保监管系统对接,实现数据共享和监管。
- 医疗保健:在医院药房,电子秤用于称量药品,Java 程序读取重量数据,辅助药剂师准确配药。此外,在一些医疗设备中,如体重秤,通过 Java 程序读取数据并与医疗信息系统集成,方便医生跟踪患者体重变化。
初学者如何利用
- 基础知识学习:
- Java 基础:初学者需掌握 Java 的基本语法,包括数据类型、变量、运算符、控制语句、函数和类等。理解面向对象编程的概念,如封装、继承和多态,这对于理解和修改电子秤读取程序至关重要。
- 串口通信:学习 Java 串口通信相关知识,了解
jSerialComm库的使用方法,掌握串口配置参数,如波特率、数据位、停止位和奇偶校验等,理解它们对数据传输的影响。 - Swing GUI:由于程序使用 Swing 创建图形用户界面,初学者要学习 Swing 组件的使用,如
JFrame、JDialog、JLabel、JButton等,以及布局管理器和事件处理机制,以便能够理解和修改界面部分的代码。
- 代码实践与分析:
- 运行代码:下载并安装
jSerialComm库,将给定代码复制到开发环境中运行。观察程序的运行效果,了解串口打开、数据读取、重量显示和稳定性判断等功能的实现过程。 - 分析代码:仔细研读代码,剖析每个方法和类的功能。例如,分析
initSerial方法如何配置和打开串口,tryParseWeight方法怎样解析重量数据,以及checkStableWeight方法如何判断数据的稳定性。逐步跟踪代码执行流程,掌握数据在各个模块之间的传递和处理逻辑。
- 运行代码:下载并安装
- 扩展与创新:
- 简单修改:尝试对代码进行简单修改,如调整串口参数、优化界面布局或改变数据解析规则。通过实践加深对代码的理解,例如修改串口波特率,观察数据传输的变化。
- 功能扩展:根据实际需求对程序进行功能扩展。比如,添加数据存储功能,将读取到的重量数据保存到数据库或文件中;或者增加网络通信功能,将电子秤数据发送到远程服务器,实现数据的远程监控和管理。
通过深入学习基础知识、积极实践代码分析以及勇于进行扩展创新,初学者能够逐步掌握利用 Java 进行电子秤数据读取的技能,为在各个领域实现精准计量和数据处理打下坚实基础。
阿雪技术观
让我们积极投身于技术共享的浪潮中,不仅仅是作为受益者,更要成为贡献者。无论是分享自己的代码、撰写技术博客,还是参与开源项目的维护和改进,每一个小小的举动都可能成为推动技术进步的巨大力量
Embrace open source and sharing, witness the miracle of technological progress, and enjoy the happy times of humanity! Let's actively join the wave of technology sharing. Not only as beneficiaries, but also as contributors. Whether sharing our own code, writing technical blogs, or participating in the maintenance and improvement of open source projects, every small action may become a huge force driving technological progress.
778

被折叠的 条评论
为什么被折叠?



