Repository: unknowIfGuestInDream/javafxTool
Pull request #2138: feat(qe): Improve SerialPortTool
Author: login: DreamAwakenFateBroke
Labels: name: enhancement
description: New feature or request
name: size/L
name: core
name: QE
name: release
name: IDEA
Created: 2025-05-10T06:47:23Z | Merged: 2025-05-11T12:37:47Z

<!-- Please ensure your PR title is brief and descriptive for a good changelog entry -->
<!-- Link to issue if there is one -->
<!-- markdownlint-disable -->

Fixes #1900

<!-- markdownlint-restore -->

<!-- Describe what the changes are -->

## Proposed Changes

1. ...
2. ...
3. ...

## Readiness Checklist

### Author/Contributor

- [x] If documentation is needed for this change, has that been included in this pull request

### Reviewing Maintainer

- [ ] Label as either `enhancement`, `bug`, `documentation` or `dependencies`
- [ ] Verify design and implementation

## Summary by Sourcery

Enhance the SerialPortTool with improved serial port communication functionality and user interface features

New Features:
- Added flow control selector
- Implemented circular sending functionality
- Added data listener for serial port events

Enhancements:
- Improved serial port open/close handling
- Enhanced send and receive data processing
- Added hex and time display options for received data

Chores:
- Updated dependency information to include jSerialComm library

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **新功能**
  - 串口工具界面新增了“流控”选项，可在配置串口参数时选择流控方式。
  - 支持循环发送功能，采用 JavaFX 动画工具实现。
  - 新增 dispose 方法，关闭串口工具时自动释放串口资源。

- **界面优化**
  - 串口参数标签文本去除多余的冒号，使界面更简洁。

- **依赖更新**
  - 增加了 jSerialComm 库依赖。

- **构建与配置**
  - 更新了构建环境信息，支持新版 JDK 和 IDE。
  - 调整了构建产物配置，新增并更新多项依赖库，优化了 Windows 平台的打包支持。
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Linked issue #1900: [Feature Request] 串口通信
### Checklist

- [X] I searched exising issues and no one else requests similar feature.
- [X] I think that 25%+ users are positive towards this feature.

### Describe the feature
#1710 

~https://gitee.com/winter110/SerialTest~
~https://gitee.com/bluecard2020/javaFx-serialPort-web-demo~
https://gitee.com/aSingleDragon/rs232-client

### Additional context

_No response_
Linked issue comments: user: login: unknowIfGuestInDream
created_at: 2024-12-28T15:06:40Z
body: https://github.com/Fazecast/jSerialComm/wiki


<blockquote><img src="https://opengraph.githubassets.com/8294832ac95ff3b737445386b8f011a731e410a9b032335465029c790a36eb23/Fazecast/jSerialComm" width="48" align="right"><div><img src="https://github.githubassets.com/favicons/favicon.svg" height="14"> GitHub</div><div><strong><a href="https://github.com/Fazecast/jSerialComm/wiki/Home">Home</a></strong></div><div>Platform-independent serial port access for Java. Contribute to Fazecast/jSerialComm development by creating an account on GitHub.</div></blockquote>

https://github.com/Fazecast/jSerialComm/blob/master/src/test/java/com/fazecast/jSerialComm/SerialPortTest.java
author_association: OWNER
user: login: unknowIfGuestInDream
created_at: 2025-01-08T08:58:45Z
body: **https://github.com/yiaoBang/SerialPortToolFX**

<blockquote><img src="https://opengraph.githubassets.com/3a56384d8965a9c7b47a120a861bd47089646ea67f15b5bc44f4520c415577c7/yiaoBang/SerialPortToolFX" width="48" align="right"><div><img src="https://github.githubassets.com/favicons/favicon.svg" height="14"> GitHub</div><div><strong><a href="https://github.com/yiaoBang/SerialPortToolFX">GitHub - yiaoBang/SerialPortToolFX: serialPortTool</a></strong></div><div>serialPortTool. Contribute to yiaoBang/SerialPortToolFX development by creating an account on GitHub.</div></blockquote>
author_association: OWNER
user: login: unknowIfGuestInDream
created_at: 2025-01-08T09:00:20Z
body: ~https://gitee.com/wxhntmy/Java_FX_SerialAssistant~
author_association: OWNER
user: login: unknowIfGuestInDream
created_at: 2025-01-08T09:03:38Z
body: https://github.com/TalusL/serialPortHelper

<blockquote><img src="https://opengraph.githubassets.com/f574414c2ab3d82525cf3f837a00c7b1bdf022520b78c18fa4d275ad00c99a51/TalusL/serialPortHelper" width="48" align="right"><div><img src="https://github.githubassets.com/favicons/favicon.svg" height="14"> GitHub</div><div><strong><a href="https://github.com/TalusL/serialPortHelper">GitHub - TalusL/serialPortHelper: JAVA版的 串口助手 JavaFx 封装，兼容主流平台</a></strong></div><div>JAVA版的 串口助手 JavaFx 封装，兼容主流平台. Contribute to TalusL/serialPortHelper development by creating an account on GitHub.</div></blockquote>
author_association: OWNER
user: login: unknowIfGuestInDream
created_at: 2025-01-08T10:13:12Z
body: 串口监控
~https://github.com/heshanthenura/SerialMonitor-JavaFX~

<blockquote><img src="https://opengraph.githubassets.com/f803059b9b24e1973811072ceb607bf83ad13a9ced52108887515b16844aa629/heshanthenura/SerialMonitor-JavaFX" width="48" align="right"><div><img src="https://github.githubassets.com/favicons/favicon.svg" height="14"> GitHub</div><div><strong><a href="https://github.com/heshanthenura/SerialMonitor-JavaFX">GitHub - heshanthenura/SerialMonitor-JavaFX: Serial Monitor and Plotter made using JavaFX</a></strong></div><div>Serial Monitor and Plotter made using JavaFX. Contribute to heshanthenura/SerialMonitor-JavaFX development by creating an account on GitHub.</div></blockquote>
author_association: OWNER
user: login: unknowIfGuestInDream
created_at: 2025-03-30T13:07:42Z
body: ![Image](https://github.com/user-attachments/assets/3cb2af08-1158-476a-97fa-cc47b6569934)

![Image](https://github.com/user-attachments/assets/b8b39b4a-eed3-4039-8151-cbd7bccd4d54)

![Image](https://github.com/user-attachments/assets/35f0f64d-20cc-4033-868a-9a52b4cdee4c)
author_association: OWNER

Diff:
diff --git a/.idea/artifacts/javafxTool_qe_mac_jar.xml b/.idea/artifacts/javafxTool_qe_mac_jar.xml
index 50bfcbca4..f51fb161b 100644
--- a/.idea/artifacts/javafxTool_qe_mac_jar.xml
+++ b/.idea/artifacts/javafxTool_qe_mac_jar.xml
@@ -1,78 +1,80 @@
 <component name="ArtifactManager">
     <artifact type="jar" name="javafxTool-qe-mac:jar">
-        <output-path>$PROJECT_DIR$/out/artifacts/javafxTool_qe_mac_jar</output-path>
+        <output-path>$PROJECT_DIR$/out/artifacts/javafxTool_qe_win_jar</output-path>
         <root id="archive" name="javafxTool-qe.jar">
             <element id="module-output" name="javafxTool-qe" />
             <element id="module-output" name="javafxTool-frame" />
             <element id="module-output" name="javafxTool-core" />
             <element id="module-output" name="javafxTool-common" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/ch/qos/logback/logback-classic/1.5.18/logback-classic-1.5.18.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/ch/qos/logback/logback-core/1.5.18/logback-core-1.5.18.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/cn/hutool/hutool-core/5.8.37/hutool-core-5.8.37.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/cn/hutool/hutool-crypto/5.8.37/hutool-crypto-5.8.37.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/cn/hutool/hutool-log/5.8.37/hutool-log-5.8.37.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/cn/hutool/hutool-poi/5.8.37/hutool-poi-5.8.37.jar" path-in-jar="/" />
             <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/dlsc/formsfx/formsfx-core/11.6.0/formsfx-core-11.6.0.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/dlsc/preferencesfx/preferencesfx-core/11.17.0/preferencesfx-core-11.17.0.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/fasterxml/jackson/core/jackson-annotations/2.19.0/jackson-annotations-2.19.0.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/fasterxml/jackson/core/jackson-core/2.19.0/jackson-core-2.19.0.jar" path-in-jar="/" />
             <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/fasterxml/jackson/core/jackson-databind/2.19.0/jackson-databind-2.19.0.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/github/gino0631/clove-io/0.2/clove-io-0.2.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/github/gino0631/icns-core/1.2/icns-core-1.2.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/github/virtuald/curvesapi/1.08/curvesapi-1.08.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/yahoo/platform/yui/yuicompressor/2.4.8/yuicompressor-2.4.8.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/zaxxer/SparseBitSet/1.3/SparseBitSet-1.3.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/commons-beanutils/commons-beanutils/1.9.4/commons-beanutils-1.9.4.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/commons-codec/commons-codec/1.18.0/commons-codec-1.18.0.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/commons-io/commons-io/2.19.0/commons-io-2.19.0.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/slf4j/slf4j-api/2.0.17/slf4j-api-2.0.17.jar" path-in-jar="/" />
             <element id="extracted-dir" path="$MAVEN_REPOSITORY$/commons-logging/commons-logging/1.3.5/commons-logging-1.3.5.jar" path-in-jar="/" />
             <element id="extracted-dir" path="$MAVEN_REPOSITORY$/fr/brouillard/oss/cssfx/11.5.1/cssfx-11.5.1.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/io/github/java-diff-utils/java-diff-utils/4.15/java-diff-utils-4.15.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/reflections/reflections/0.10.2/reflections-0.10.2.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-base/21.0.7/javafx-base-21.0.7-mac.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/kordamp/ikonli/ikonli-javafx/12.4.0/ikonli-javafx-12.4.0.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/controlsfx/controlsfx/11.2.2/controlsfx-11.2.2.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/cn/hutool/hutool-poi/5.8.37/hutool-poi-5.8.37.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/fxmisc/wellbehaved/wellbehavedfx/0.3.3/wellbehavedfx-0.3.3.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/poi/poi/5.4.1/poi-5.4.1.jar" path-in-jar="/" />
             <element id="extracted-dir" path="$MAVEN_REPOSITORY$/jaxen/jaxen/2.0.0/jaxen-2.0.0.jar" path-in-jar="/" />
             <element id="extracted-dir" path="$MAVEN_REPOSITORY$/net/coobird/thumbnailator/0.4.20/thumbnailator-0.4.20.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/net/ifok/image/image4j/0.7.2/image4j-0.7.2.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/net/jonathangiles/tools/teenyhttpd/1.0.5/teenyhttpd-1.0.5.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/commons/commons-collections4/4.4/commons-collections4-4.4.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/commons/commons-compress/1.27.1/commons-compress-1.27.1.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/commons/commons-configuration2/2.12.0/commons-configuration2-2.12.0.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/commons/commons-imaging/1.0.0-alpha6/commons-imaging-1.0.0-alpha6.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/commons/commons-lang3/3.17.0/commons-lang3-3.17.0.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-graphics/21.0.7/javafx-graphics-21.0.7.jar" path-in-jar="/" />
             <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/commons/commons-math3/3.6.1/commons-math3-3.6.1.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/commons/commons-text/1.13.0/commons-text-1.13.0.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/logging/log4j/log4j-api/2.24.3/log4j-api-2.24.3.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/logging/log4j/log4j-core/2.24.3/log4j-core-2.24.3.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/poi/poi-ooxml-lite/5.4.1/poi-ooxml-lite-5.4.1.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/poi/poi-ooxml/5.4.1/poi-ooxml-5.4.1.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/poi/poi/5.4.1/poi-5.4.1.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/github/virtuald/curvesapi/1.08/curvesapi-1.08.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/javassist/javassist/3.30.2-GA/javassist-3.30.2-GA.jar" path-in-jar="/" />
             <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/xmlbeans/xmlbeans/5.3.0/xmlbeans-5.3.0.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/checkerframework/checker-qual/3.49.3/checker-qual-3.49.3.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/controlsfx/controlsfx/11.2.2/controlsfx-11.2.2.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/cn/hutool/hutool-crypto/5.8.37/hutool-crypto-5.8.37.jar" path-in-jar="/" />
             <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/dom4j/dom4j/2.1.4/dom4j-2.1.4.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/freemarker/freemarker/2.3.34/freemarker-2.3.34.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/fxmisc/flowless/flowless/0.7.3/flowless-0.7.3.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/fxmisc/richtext/richtextfx/0.11.5/richtextfx-0.11.5.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/fxmisc/undo/undofx/2.1.1/undofx-2.1.1.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/fxmisc/wellbehaved/wellbehavedfx/0.3.3/wellbehavedfx-0.3.3.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/javassist/javassist/3.30.2-GA/javassist-3.30.2-GA.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/kordamp/ikonli/ikonli-core/12.4.0/ikonli-core-12.4.0.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/kordamp/ikonli/ikonli-javafx/12.4.0/ikonli-javafx-12.4.0.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/kordamp/ikonli/ikonli-material-pack/12.4.0/ikonli-material-pack-12.4.0.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/commons-codec/commons-codec/1.18.0/commons-codec-1.18.0.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/commons-collections/commons-collections/3.2.2/commons-collections-3.2.2.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-swing/21.0.7/javafx-swing-21.0.7.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/commons-io/commons-io/2.19.0/commons-io-2.19.0.jar" path-in-jar="/" />
             <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-base/21.0.7/javafx-base-21.0.7.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-base/21.0.7/javafx-base-21.0.7-mac.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-controls/21.0.7/javafx-controls-21.0.7.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-controls/21.0.7/javafx-controls-21.0.7-mac.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-fxml/21.0.7/javafx-fxml-21.0.7.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-fxml/21.0.7/javafx-fxml-21.0.7-mac.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-graphics/21.0.7/javafx-graphics-21.0.7.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/fasterxml/jackson/core/jackson-annotations/2.19.0/jackson-annotations-2.19.0.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/cn/hutool/hutool-core/5.8.37/hutool-core-5.8.37.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/logging/log4j/log4j-core/2.24.3/log4j-core-2.24.3.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/reactfx/reactfx/2.0-M5/reactfx-2.0-M5.jar" path-in-jar="/" />
             <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-graphics/21.0.7/javafx-graphics-21.0.7-mac.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-smacg/21.0.7/javafx-swing-21.0.7.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/commons-beanutils/commons-beanutils/1.10.1/commons-beanutils-1.10.1.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/dlsc/preferencesfx/preferencesfx-core/11.17.0/preferencesfx-core-11.17.0.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/ch/qos/logback/logback-core/1.5.18/logback-core-1.5.18.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/kordamp/ikonli/ikonli-core/12.4.0/ikonli-core-12.4.0.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/github/gino0631/clove-io/0.2/clove-io-0.2.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/poi/poi-ooxml-lite/5.4.1/poi-ooxml-lite-5.4.1.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/fxmisc/undo/undofx/2.1.1/undofx-2.1.1.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/checkerframework/checker-qual/3.49.3/checker-qual-3.49.3.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/rhino/js/1.7R2/js-1.7R2.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/net/ifok/image/image4j/0.7.2/image4j-0.7.2.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/fazecast/jSerialComm/2.11.0/jSerialComm-2.11.0.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-controls/21.0.7/javafx-controls-21.0.7.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/commons/commons-configuration2/2.12.0/commons-configuration2-2.12.0.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/logging/log4j/log4j-api/2.24.3/log4j-api-2.24.3.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/kordamp/ikonli/ikonli-material-pack/12.4.0/ikonli-material-pack-12.4.0.jar" path-in-jar="/" />
             <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-swing/21.0.7/javafx-swing-21.0.7-mac.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/reactfx/reactfx/2.0-M5/reactfx-2.0-M5.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/reflections/reflections/0.10.2/reflections-0.10.2.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/fxmisc/flowless/flowless/0.7.4/flowless-0.7.4.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/zaxxer/SparseBitSet/1.3/SparseBitSet-1.3.jar" path-in-jar="/" />
             <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/slf4j/log4j-over-slf4j/2.0.17/log4j-over-slf4j-2.0.17.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/slf4j/slf4j-api/2.0.17/slf4j-api-2.0.17.jar" path-in-jar="/" />
-            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/rhino/js/1.7R2/js-1.7R2.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/net/jonathangiles/tools/teenyhttpd/1.0.5/teenyhttpd-1.0.5.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/cn/hutool/hutool-log/5.8.37/hutool-log-5.8.37.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/io/github/java-diff-utils/java-diff-utils/4.15/java-diff-utils-4.15.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-fxml/21.0.7/javafx-fxml-21.0.7.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/ch/qos/logback/logback-classic/1.5.18/logback-classic-1.5.18.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-controls/21.0.7/javafx-controls-21.0.7-mac.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/fasterxml/jackson/core/jackson-core/2.19.0/jackson-core-2.19.0.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/freemarker/freemarker/2.3.34/freemarker-2.3.34.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/commons/commons-imaging/1.0.0-alpha6/commons-imaging-1.0.0-alpha6.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/poi/poi-ooxml/5.4.1/poi-ooxml-5.4.1.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-fxml/21.0.7/javafx-fxml-21.0.7-mac.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/commons/commons-text/1.13.1/commons-text-1.13.1.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/commons/commons-collections4/4.5.0/commons-collections4-4.5.0.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/commons/commons-lang3/3.17.0/commons-lang3-3.17.0.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/fxmisc/richtext/richtextfx/0.11.5/richtextfx-0.11.5.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/yahoo/platform/yui/yuicompressor/2.4.8/yuicompressor-2.4.8.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/commons/commons-compress/1.27.1/commons-compress-1.27.1.jar" path-in-jar="/" />
+            <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/github/gino0631/icns-core/1.2/icns-core-1.2.jar" path-in-jar="/" />
         </root>
     </artifact>
 </component>
diff --git a/.idea/artifacts/javafxTool_qe_win_jar.xml b/.idea/artifacts/javafxTool_qe_win_jar.xml
index 69b6f5c3a..c4cb65949 100644
--- a/.idea/artifacts/javafxTool_qe_win_jar.xml
+++ b/.idea/artifacts/javafxTool_qe_win_jar.xml
@@ -6,73 +6,75 @@
       <element id="module-output" name="javafxTool-frame" />
       <element id="module-output" name="javafxTool-core" />
       <element id="module-output" name="javafxTool-common" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/ch/qos/logback/logback-classic/1.5.18/logback-classic-1.5.18.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/ch/qos/logback/logback-core/1.5.18/logback-core-1.5.18.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/cn/hutool/hutool-core/5.8.37/hutool-core-5.8.37.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/cn/hutool/hutool-crypto/5.8.37/hutool-crypto-5.8.37.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/cn/hutool/hutool-log/5.8.37/hutool-log-5.8.37.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/cn/hutool/hutool-poi/5.8.37/hutool-poi-5.8.37.jar" path-in-jar="/" />
       <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/dlsc/formsfx/formsfx-core/11.6.0/formsfx-core-11.6.0.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/dlsc/preferencesfx/preferencesfx-core/11.17.0/preferencesfx-core-11.17.0.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/fasterxml/jackson/core/jackson-annotations/2.19.0/jackson-annotations-2.19.0.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/fasterxml/jackson/core/jackson-core/2.19.0/jackson-core-2.19.0.jar" path-in-jar="/" />
       <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/fasterxml/jackson/core/jackson-databind/2.19.0/jackson-databind-2.19.0.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/github/gino0631/clove-io/0.2/clove-io-0.2.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/github/gino0631/icns-core/1.2/icns-core-1.2.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/github/virtuald/curvesapi/1.08/curvesapi-1.08.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/yahoo/platform/yui/yuicompressor/2.4.8/yuicompressor-2.4.8.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/zaxxer/SparseBitSet/1.3/SparseBitSet-1.3.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/commons-beanutils/commons-beanutils/1.9.4/commons-beanutils-1.9.4.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/commons-codec/commons-codec/1.18.0/commons-codec-1.18.0.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/commons-io/commons-io/2.19.0/commons-io-2.19.0.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/slf4j/slf4j-api/2.0.17/slf4j-api-2.0.17.jar" path-in-jar="/" />
       <element id="extracted-dir" path="$MAVEN_REPOSITORY$/commons-logging/commons-logging/1.3.5/commons-logging-1.3.5.jar" path-in-jar="/" />
       <element id="extracted-dir" path="$MAVEN_REPOSITORY$/fr/brouillard/oss/cssfx/11.5.1/cssfx-11.5.1.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/io/github/java-diff-utils/java-diff-utils/4.15/java-diff-utils-4.15.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/reflections/reflections/0.10.2/reflections-0.10.2.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-base/21.0.7/javafx-base-21.0.7-win.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/kordamp/ikonli/ikonli-javafx/12.4.0/ikonli-javafx-12.4.0.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/controlsfx/controlsfx/11.2.2/controlsfx-11.2.2.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/cn/hutool/hutool-poi/5.8.37/hutool-poi-5.8.37.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/fxmisc/wellbehaved/wellbehavedfx/0.3.3/wellbehavedfx-0.3.3.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/poi/poi/5.4.1/poi-5.4.1.jar" path-in-jar="/" />
       <element id="extracted-dir" path="$MAVEN_REPOSITORY$/jaxen/jaxen/2.0.0/jaxen-2.0.0.jar" path-in-jar="/" />
       <element id="extracted-dir" path="$MAVEN_REPOSITORY$/net/coobird/thumbnailator/0.4.20/thumbnailator-0.4.20.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/net/ifok/image/image4j/0.7.2/image4j-0.7.2.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/net/jonathangiles/tools/teenyhttpd/1.0.5/teenyhttpd-1.0.5.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/commons/commons-collections4/4.4/commons-collections4-4.4.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/commons/commons-compress/1.27.1/commons-compress-1.27.1.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/commons/commons-configuration2/2.12.0/commons-configuration2-2.12.0.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/commons/commons-imaging/1.0.0-alpha6/commons-imaging-1.0.0-alpha6.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/commons/commons-lang3/3.17.0/commons-lang3-3.17.0.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-graphics/21.0.7/javafx-graphics-21.0.7.jar" path-in-jar="/" />
       <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/commons/commons-math3/3.6.1/commons-math3-3.6.1.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/commons/commons-text/1.13.0/commons-text-1.13.0.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/logging/log4j/log4j-api/2.24.3/log4j-api-2.24.3.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/logging/log4j/log4j-core/2.24.3/log4j-core-2.24.3.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/poi/poi-ooxml-lite/5.4.1/poi-ooxml-lite-5.4.1.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/poi/poi-ooxml/5.4.1/poi-ooxml-5.4.1.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/poi/poi/5.4.1/poi-5.4.1.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/github/virtuald/curvesapi/1.08/curvesapi-1.08.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/javassist/javassist/3.30.2-GA/javassist-3.30.2-GA.jar" path-in-jar="/" />
       <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/xmlbeans/xmlbeans/5.3.0/xmlbeans-5.3.0.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/checkerframework/checker-qual/3.49.3/checker-qual-3.49.3.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/controlsfx/controlsfx/11.2.2/controlsfx-11.2.2.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/cn/hutool/hutool-crypto/5.8.37/hutool-crypto-5.8.37.jar" path-in-jar="/" />
       <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/dom4j/dom4j/2.1.4/dom4j-2.1.4.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/freemarker/freemarker/2.3.34/freemarker-2.3.34.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/fxmisc/flowless/flowless/0.7.3/flowless-0.7.3.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/fxmisc/richtext/richtextfx/0.11.5/richtextfx-0.11.5.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/fxmisc/undo/undofx/2.1.1/undofx-2.1.1.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/fxmisc/wellbehaved/wellbehavedfx/0.3.3/wellbehavedfx-0.3.3.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/javassist/javassist/3.30.2-GA/javassist-3.30.2-GA.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/kordamp/ikonli/ikonli-core/12.4.0/ikonli-core-12.4.0.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/kordamp/ikonli/ikonli-javafx/12.4.0/ikonli-javafx-12.4.0.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/kordamp/ikonli/ikonli-material-pack/12.4.0/ikonli-material-pack-12.4.0.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/commons-codec/commons-codec/1.18.0/commons-codec-1.18.0.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/commons-collections/commons-collections/3.2.2/commons-collections-3.2.2.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-swing/21.0.7/javafx-swing-21.0.7.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/commons-io/commons-io/2.19.0/commons-io-2.19.0.jar" path-in-jar="/" />
       <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-base/21.0.7/javafx-base-21.0.7.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-base/21.0.7/javafx-base-21.0.7-win.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-controls/21.0.7/javafx-controls-21.0.7.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-controls/21.0.7/javafx-controls-21.0.7-win.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-fxml/21.0.7/javafx-fxml-21.0.7.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-fxml/21.0.7/javafx-fxml-21.0.7-win.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-graphics/21.0.7/javafx-graphics-21.0.7.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/fasterxml/jackson/core/jackson-annotations/2.19.0/jackson-annotations-2.19.0.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/cn/hutool/hutool-core/5.8.37/hutool-core-5.8.37.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/logging/log4j/log4j-core/2.24.3/log4j-core-2.24.3.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/reactfx/reactfx/2.0-M5/reactfx-2.0-M5.jar" path-in-jar="/" />
       <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-graphics/21.0.7/javafx-graphics-21.0.7-win.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-swing/21.0.7/javafx-swing-21.0.7.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/commons-beanutils/commons-beanutils/1.10.1/commons-beanutils-1.10.1.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/dlsc/preferencesfx/preferencesfx-core/11.17.0/preferencesfx-core-11.17.0.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/ch/qos/logback/logback-core/1.5.18/logback-core-1.5.18.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/kordamp/ikonli/ikonli-core/12.4.0/ikonli-core-12.4.0.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/github/gino0631/clove-io/0.2/clove-io-0.2.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/poi/poi-ooxml-lite/5.4.1/poi-ooxml-lite-5.4.1.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/fxmisc/undo/undofx/2.1.1/undofx-2.1.1.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/checkerframework/checker-qual/3.49.3/checker-qual-3.49.3.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/rhino/js/1.7R2/js-1.7R2.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/net/ifok/image/image4j/0.7.2/image4j-0.7.2.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/fazecast/jSerialComm/2.11.0/jSerialComm-2.11.0.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-controls/21.0.7/javafx-controls-21.0.7.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/commons/commons-configuration2/2.12.0/commons-configuration2-2.12.0.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/logging/log4j/log4j-api/2.24.3/log4j-api-2.24.3.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/kordamp/ikonli/ikonli-material-pack/12.4.0/ikonli-material-pack-12.4.0.jar" path-in-jar="/" />
       <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-swing/21.0.7/javafx-swing-21.0.7-win.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/reactfx/reactfx/2.0-M5/reactfx-2.0-M5.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/reflections/reflections/0.10.2/reflections-0.10.2.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/fxmisc/flowless/flowless/0.7.4/flowless-0.7.4.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/zaxxer/SparseBitSet/1.3/SparseBitSet-1.3.jar" path-in-jar="/" />
       <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/slf4j/log4j-over-slf4j/2.0.17/log4j-over-slf4j-2.0.17.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/slf4j/slf4j-api/2.0.17/slf4j-api-2.0.17.jar" path-in-jar="/" />
-      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/rhino/js/1.7R2/js-1.7R2.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/net/jonathangiles/tools/teenyhttpd/1.0.5/teenyhttpd-1.0.5.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/cn/hutool/hutool-log/5.8.37/hutool-log-5.8.37.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/io/github/java-diff-utils/java-diff-utils/4.15/java-diff-utils-4.15.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-fxml/21.0.7/javafx-fxml-21.0.7.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/ch/qos/logback/logback-classic/1.5.18/logback-classic-1.5.18.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-controls/21.0.7/javafx-controls-21.0.7-win.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/fasterxml/jackson/core/jackson-core/2.19.0/jackson-core-2.19.0.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/freemarker/freemarker/2.3.34/freemarker-2.3.34.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/commons/commons-imaging/1.0.0-alpha6/commons-imaging-1.0.0-alpha6.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/poi/poi-ooxml/5.4.1/poi-ooxml-5.4.1.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-fxml/21.0.7/javafx-fxml-21.0.7-win.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/commons/commons-text/1.13.1/commons-text-1.13.1.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/commons/commons-collections4/4.5.0/commons-collections4-4.5.0.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/commons/commons-lang3/3.17.0/commons-lang3-3.17.0.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/fxmisc/richtext/richtextfx/0.11.5/richtextfx-0.11.5.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/yahoo/platform/yui/yuicompressor/2.4.8/yuicompressor-2.4.8.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/commons/commons-compress/1.27.1/commons-compress-1.27.1.jar" path-in-jar="/" />
+      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/github/gino0631/icns-core/1.2/icns-core-1.2.jar" path-in-jar="/" />
     </root>
   </artifact>
-</component>
+</component>
\ No newline at end of file
diff --git a/core/src/main/java/com/tlcsdm/core/util/DependencyInfo.java b/core/src/main/java/com/tlcsdm/core/util/DependencyInfo.java
index 2750bd365..d709c18fb 100644
--- a/core/src/main/java/com/tlcsdm/core/util/DependencyInfo.java
+++ b/core/src/main/java/com/tlcsdm/core/util/DependencyInfo.java
@@ -232,6 +232,10 @@ private static class SingletonInstance {
                 "https://javaluator.fathzer.com", "Apache License, Version 2.0",
                 "https://www.apache.org/licenses/LICENSE-2.0"),
 
+            new Dependency("com.fazecast", "jSerialComm", "2.11.0", false,
+                "https://fazecast.github.io/jSerialComm", "GNU LGPL",
+                "https://www.gnu.org/licenses/lgpl-3.0.html"),
+
             new Dependency("com.github.gino0631", "icns-core", "1.2", false,
                 "https://github.com/gino0631/icns", "GNU LGPL",
                 "https://opensource.org/license/lgpl-3-0"));
diff --git a/qe/src/main/java/com/tlcsdm/qe/tools/SerialPortTool.java b/qe/src/main/java/com/tlcsdm/qe/tools/SerialPortTool.java
index b02f71879..0a5fd7a0e 100644
--- a/qe/src/main/java/com/tlcsdm/qe/tools/SerialPortTool.java
+++ b/qe/src/main/java/com/tlcsdm/qe/tools/SerialPortTool.java
@@ -27,17 +27,17 @@
 
 package com.tlcsdm.qe.tools;
 
-import cn.hutool.core.util.StrUtil;
 import cn.hutool.log.StaticLog;
 import com.fazecast.jSerialComm.SerialPort;
 import com.fazecast.jSerialComm.SerialPortDataListener;
 import com.fazecast.jSerialComm.SerialPortEvent;
-import com.tlcsdm.core.javafx.control.FxTextInput;
 import com.tlcsdm.core.javafx.helper.LayoutHelper;
 import com.tlcsdm.core.javafx.util.Config;
 import com.tlcsdm.core.javafx.util.FxmlUtil;
+import com.tlcsdm.core.util.CoreConstant;
 import com.tlcsdm.qe.QeSample;
 import com.tlcsdm.qe.util.I18nUtils;
+import javafx.animation.Timeline;
 import javafx.event.ActionEvent;
 import javafx.fxml.FXML;
 import javafx.fxml.FXMLLoader;
@@ -57,11 +57,8 @@
 
 import java.net.URL;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import java.util.ResourceBundle;
-import java.util.Timer;
 import java.util.stream.Collectors;
 
 /**
@@ -72,28 +69,41 @@
  */
 public class SerialPortTool extends QeSample implements Initializable {
 
+    //串口名称选择器
     @FXML
     private ComboBox<SerialPort> serPort;
+    //波特率选择器
     @FXML
     private ComboBox<String> serPortSpeed;
+    //检验位选择器
     @FXML
     private ComboBox<String> serPortCheckBit;
+    //数据位选择器
     @FXML
     private ComboBox<String> serPortDataBit;
+    //停止位选择器
     @FXML
     private ComboBox<String> serPortStopBit;
+    //流控选择器
+    @FXML
+    private ComboBox<String> serFlowControl;
     @FXML
     private Button serPortOpenBtn;
+    //16进制接收显示开关
     @FXML
     private CheckBox recvShowHex;
+    //显示时间
     @FXML
     private CheckBox recvShowTime;
+    //暂停接收
     @FXML
     private CheckBox recvStopShow;
     @FXML
     private Button recvClear;
+    //16进制发送开关
     @FXML
     private CheckBox sendHex;
+    //定时发送开关
     @FXML
     private CheckBox sendCycle;
     @FXML
@@ -113,7 +123,8 @@ public class SerialPortTool extends QeSample implements Initializable {
     @FXML
     private Button sendBtn;
 
-    private Timer t;
+    private final Timeline circularSending = new Timeline();
+    private volatile long waitTime = 1000;
 
     @Override
     public Node getPanel(Stage stage) {
@@ -149,7 +160,18 @@ public String getSampleDescription() {
 
     @Override
     public String getSampleVersion() {
-        return "1.0.1";
+        return "1.0.1-Beta";
+    }
+
+    @Override
+    public boolean hasControlPanel() {
+        return false;
+    }
+
+    @Override
+    public boolean isVisible() {
+        String value = System.getProperty(CoreConstant.JVM_WORKENV);
+        return CoreConstant.JVM_WORKENV_DEV.equals(value) || CoreConstant.JVM_WORKENV_TEST.equals(value);
     }
 
     @Override
@@ -161,33 +183,6 @@ public void initialize(URL location, ResourceBundle resources) {
         initializeUI();
     }
 
-    @Override
-    public Node getControlPanel() {
-        String content = """
-            {note}
-            {enableMunge}: {enableMungeDesc}
-            {enableVerbose}: {enableVerboseDesc}
-            {enableOptimizations}: {enableOptimizationsDesc}
-            {enablePreserveAllSemiColons}: {enablePreserveAllSemiColonsDesc}
-            {enableLinebreakpos}: {enableLinebreakposDesc}
-            """;
-
-        Map<String, String> map = new HashMap<>(32);
-        map.put("note", I18nUtils.get("qe.tool.compress.description.note"));
-        map.put("enableMunge", I18nUtils.get("qe.tool.compress.check.enableMunge"));
-        map.put("enableVerbose", I18nUtils.get("qe.tool.compress.check.enableVerbose"));
-        map.put("enableOptimizations", I18nUtils.get("qe.tool.compress.check.enableOptimizations"));
-        map.put("enablePreserveAllSemiColons", I18nUtils.get("qe.tool.compress.check.enablePreserveAllSemiColons"));
-        map.put("enableLinebreakpos", I18nUtils.get("qe.tool.compress.check.enableLinebreakpos"));
-        map.put("enableMungeDesc", I18nUtils.get("qe.tool.compress.check.enableMunge.description"));
-        map.put("enableVerboseDesc", I18nUtils.get("qe.tool.compress.check.enableVerbose.description"));
-        map.put("enableOptimizationsDesc", I18nUtils.get("qe.tool.compress.check.enableOptimizations.description"));
-        map.put("enablePreserveAllSemiColonsDesc",
-            I18nUtils.get("qe.tool.compress.check.enablePreserveAllSemiColons.description"));
-        map.put("enableLinebreakposDesc", I18nUtils.get("qe.tool.compress.check.enableLinebreakpos.description"));
-        return FxTextInput.textArea(StrUtil.format(content, map));
-    }
-
     /**
      * 设置刷新串口信息按钮被点击时的事件处理器: 重新获取本机当前串口信息
      */
@@ -242,6 +237,12 @@ public ImageView getSampleImageIcon() {
     // https://github.com/yiaoBang/SerialPortToolFX/blob/master/src/main/java/com/yiaoBang/serialPortToolFX/view/SerialPortView.java
 
     public void initializeUI() {
+        //无限循环发送
+        circularSending.setCycleCount(Timeline.INDEFINITE);
+
+        //        recvCount
+        //        sendNumber.textProperty().bind(viewModel.getSEND_LONG_PROPERTY().asString());
+        //        receiveNumber.textProperty().bind(viewModel.getRECEIVE_LONG_PROPERTY().asString());
 
         //        // 初始化常用波特率列表
         //        baudRateComboBox.getItems().addAll("9600", "4800", "2400", "1200");
@@ -308,6 +309,28 @@ public void initializeUI() {
         }
         serPortStopBit.setValue("1");
 
+        //流控
+        //        String[] flowControl = new String[]{
+        //            "100", "300", "600", "1200"
+        //        };
+        //        for (String s : speeds) {
+        //            serPortSpeed.getItems().add(s);
+        //        }
+        //        serPortSpeed.setValue("9600");
+        //serFlowControl.getItems().addAll(SerialPort.FLOW_CONTROL_DISABLED);
+
+        //循环发送的等待时间(ms)
+        sendCycleRap.textProperty().addListener((o, oldValue, newValue) -> {
+            try {
+                waitTime = Integer.parseInt(newValue);
+                if (waitTime < 1) {
+                    waitTime = 1;
+                }
+            } catch (NumberFormatException e) {
+                sendCycleRap.setText(oldValue);
+            }
+        });
+
         serPortOpenBtn.setOnAction((ActionEvent event) -> {
             SerialPort serialPort = serPort.getSelectionModel().getSelectedItem();
             if (serialPort == null) {
@@ -322,6 +345,8 @@ public void initializeUI() {
                 serPortDataBit.setDisable(false);
                 serPortStopBit.setDisable(false);
             } else {
+                serialPortDataListener listener = new serialPortDataListener();
+                serialPort.addDataListener(listener);
                 serialPort.openPort();
                 //SerialPort.ONE_STOP_BIT
                 //SerialPort.NO_PARITY
@@ -333,7 +358,7 @@ public void initializeUI() {
                 serialPort.setFlowControl(SerialPort.FLOW_CONTROL_DISABLED);
                 serialPort.setComPortTimeouts(SerialPort.TIMEOUT_READ_BLOCKING | SerialPort.TIMEOUT_WRITE_BLOCKING,
                     1000, 1000);
-                //UsartRXEven();
+
                 serPortOpenBtn.setText("关闭");
                 serPort.setDisable(true);
                 serPortSpeed.setDisable(true);
@@ -342,48 +367,52 @@ public void initializeUI() {
                 serPortStopBit.setDisable(true);
             }
         });
-        //
-        //        sendBtn.setOnAction(event -> {
-        //            if (null == serialPort || (!serialPort.isOpened())) {
-        //                // new AlertBox().display("错误", "请先打开串口");
-        //                return;
-        //            }
-        //            try {
-        //                if (sendHex.isSelected()) {
-        //                    serialPort.writeBytes(hexStringToBytes(sendTextAear.getText()));
-        //                    sendCount.setText(String.valueOf(
-        //                        (Integer.parseInt(sendCount.getText()) + hexStringToBytes(sendTextAear.getText()).length)));
-        //                } else {
-        //                    serialPort.writeBytes(sendTextAear.getText().getBytes());
-        //                    sendCount.setText(String.valueOf(
-        //                        (Integer.parseInt(sendCount.getText()) + sendTextAear.getText().getBytes().length)));
-        //                }
-        //
-        //            } catch (Exception e) {
-        //                //new AlertBox().display("发送数据错误", e.getMessage());
-        //            }
-        //        });
-        //
-        //        recvClear.setOnAction(event -> {
-        //            recvTextAear.setText("");
-        //        });
-        //        sendHex.setOnAction(event -> {
-        //            if (!sendHex.isSelected())
-        //                try {
-        //                    sendTextAear.setText(new String(hexStringToBytes(sendTextAear.getText())));
-        //                } catch (Exception e) {
-        //                    //new AlertBox().display("非法16进制字符", e.getMessage());
-        //                }
-        //            else
-        //                sendTextAear.setText(bytesToHexString(sendTextAear.getText().getBytes()));
-        //        });
-        //        sendClear.setOnAction(event -> {
-        //            sendTextAear.setText("");
-        //        });
-        //        CountReset.setOnAction(event -> {
-        //            sendCount.setText("0");
-        //            recvCount.setText("0");
-        //        });
+
+        sendBtn.setOnAction(event -> {
+            SerialPort serialPort = serPort.getSelectionModel().getSelectedItem();
+            if (null == serialPort || (!serialPort.isOpen())) {
+                // new AlertBox().display("错误", "请先打开串口");
+                return;
+            }
+            try {
+                if (sendHex.isSelected()) {
+                    byte[] bytes = hexStringToBytes(sendTextAear.getText());
+                    serialPort.writeBytes(bytes, bytes.length);
+                    sendCount.setText(String.valueOf(
+                        (Integer.parseInt(sendCount.getText()) + hexStringToBytes(sendTextAear.getText()).length)));
+                } else {
+                    byte[] bytes = sendTextAear.getText().getBytes();
+                    serialPort.writeBytes(bytes, bytes.length);
+                    sendCount.setText(String.valueOf(
+                        (Integer.parseInt(sendCount.getText()) + sendTextAear.getText().getBytes().length)));
+                }
+
+            } catch (Exception e) {
+                //new AlertBox().display("发送数据错误", e.getMessage());
+            }
+        });
+
+        recvClear.setOnAction(event -> {
+            recvTextAear.setText("");
+        });
+        sendHex.setOnAction(event -> {
+            if (!sendHex.isSelected())
+                try {
+                    sendTextAear.setText(new String(hexStringToBytes(sendTextAear.getText())));
+                } catch (Exception e) {
+                    //new AlertBox().display("非法16进制字符", e.getMessage());
+                }
+            else {
+                sendTextAear.setText(bytesToHexString(sendTextAear.getText().getBytes()));
+            }
+        });
+        sendClear.setOnAction(event -> {
+            sendTextAear.setText("");
+        });
+        CountReset.setOnAction(event -> {
+            sendCount.setText("0");
+            recvCount.setText("0");
+        });
         //        sendCycle.setOnAction(event -> {
         //            if (null == serialPort || (!serialPort.isOpened())) {
         //                //new AlertBox().display("错误", "请先打开串口");
@@ -462,6 +491,17 @@ public void initializeUserDataBindings() {
         //        userData.put("txtCssLinebreakpos", txtCssLinebreakpos);
     }
 
+    @Override
+    public void dispose() {
+        SerialPort serialPort = serPort.getSelectionModel().getSelectedItem();
+        if (serialPort == null) {
+            return;
+        }
+        if (serialPort.isOpen()) {
+            serialPort.closePort();
+        }
+    }
+
     /**
      * 获得当前计算机所有的串口的名称列表
      *
@@ -511,30 +551,6 @@ private SerialPort openPort(String portName, int baudRate) {
         return serialPort;
     }
 
-    /**
-     * 关闭串口
-     *
-     * @param serialPort 待关闭的串口对象
-     */
-    private void closePort(SerialPort serialPort) {
-        if (serialPort != null && serialPort.isOpen()) {
-            serialPort.closePort();
-        }
-    }
-
-    /**
-     * 往串口发送数据
-     *
-     * @param serialPort 串口对象
-     * @param content    待发送数据
-     */
-    private void sendToPort(SerialPort serialPort, byte[] content) {
-        if (!serialPort.isOpen()) {
-            return;
-        }
-        serialPort.writeBytes(content, content.length);
-    }
-
     /**
      * 从串口读取数据
      *
@@ -573,8 +589,9 @@ public int getListeningEvents() {
         public void serialEvent(SerialPortEvent event) {
             byte[] newData = event.getReceivedData();
             System.out.println("Received data of size: " + newData.length);
-            for (int i = 0; i < newData.length; ++i)
+            for (int i = 0; i < newData.length; ++i) {
                 System.out.print((char) newData[i]);
+            }
             System.out.println("\n");
         }
     }
diff --git a/qe/src/main/java/com/tlcsdm/qe/util/QeConstant.java b/qe/src/main/java/com/tlcsdm/qe/util/QeConstant.java
index 873b3849d..a445f76ef 100644
--- a/qe/src/main/java/com/tlcsdm/qe/util/QeConstant.java
+++ b/qe/src/main/java/com/tlcsdm/qe/util/QeConstant.java
@@ -81,7 +81,7 @@ public class QeConstant {
     /**
      * 项目构建日期
      */
-    public static final String PROJECT_BUILD_DAY = "2023-10-02";
+    public static final String PROJECT_BUILD_DAY = "2025-05-11";
     /**
      * 检查更新所用的api
      */
@@ -96,7 +96,7 @@ public class QeConstant {
      */
     public static final List<String> DEPENDENCY_LIST = List.of("poi", "freemarker", "dom4j", "java-diff-utils",
         "richtextfx", "thumbnailator", "jackson", "yuicompressor", "teenyhttpd", "image4j", "commons-imaging",
-        "icns-core", "preferencesfx");
+        "icns-core", "preferencesfx", "jSerialComm");
 
     private QeConstant() {
     }
diff --git a/qe/src/main/resources/META-INF/MANIFEST.MF b/qe/src/main/resources/META-INF/MANIFEST.MF
index 60d88cf47..5fe0714e3 100644
--- a/qe/src/main/resources/META-INF/MANIFEST.MF
+++ b/qe/src/main/resources/META-INF/MANIFEST.MF
@@ -4,6 +4,6 @@ Implementation-Version: 1.0.1
 Built-By: unknowIfGuestInDream
 Build-Os: Windows 11
 Build-Jdk-Spec: 17
-Build-Jdk: Eclipse Temurin 17.0.9
-Created-By: IntelliJ IDEA 2023.3.1
-Build-Day: 2023-10-02
+Build-Jdk: Eclipse Temurin 17.0.15
+Created-By: IntelliJ IDEA 2023.3.2.2
+Build-Day: 2025-05-11
diff --git a/qe/src/main/resources/com/tlcsdm/qe/fxml/serialPortTool.fxml b/qe/src/main/resources/com/tlcsdm/qe/fxml/serialPortTool.fxml
index 7d965351b..980f563d9 100644
--- a/qe/src/main/resources/com/tlcsdm/qe/fxml/serialPortTool.fxml
+++ b/qe/src/main/resources/com/tlcsdm/qe/fxml/serialPortTool.fxml
@@ -62,20 +62,23 @@
                                 <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
                             </rowConstraints>
                             <children>
-                                <Label text="串口号:" GridPane.columnIndex="0"/>
+                                <Label text="串口号" GridPane.columnIndex="0"/>
                                 <ComboBox fx:id="serPort" prefWidth="150.0" GridPane.columnIndex="1"/>
-                                <Label text="波特率:" GridPane.rowIndex="1"/>
+                                <Label text="波特率" GridPane.rowIndex="1"/>
                                 <ComboBox fx:id="serPortSpeed" editable="true" prefWidth="150.0"
                                           GridPane.columnIndex="1" GridPane.rowIndex="1"/>
-                                <Label text="检验位:" GridPane.rowIndex="2"/>
+                                <Label text="检验位" GridPane.rowIndex="2"/>
                                 <ComboBox fx:id="serPortCheckBit" prefWidth="150.0" GridPane.columnIndex="1"
                                           GridPane.rowIndex="2"/>
-                                <Label text="数据位:" GridPane.rowIndex="3"/>
+                                <Label text="数据位" GridPane.rowIndex="3"/>
                                 <ComboBox fx:id="serPortDataBit" prefWidth="150.0" GridPane.columnIndex="1"
                                           GridPane.rowIndex="3"/>
-                                <Label text="停止位:" GridPane.rowIndex="4"/>
+                                <Label text="停止位" GridPane.rowIndex="4"/>
                                 <ComboBox fx:id="serPortStopBit" prefWidth="150.0" GridPane.columnIndex="1"
                                           GridPane.rowIndex="4"/>
+                                <Label text="流控" GridPane.rowIndex="5"/>
+                                <ComboBox fx:id="serFlowControl" prefWidth="150.0" GridPane.columnIndex="1"
+                                          GridPane.rowIndex="5"/>
                             </children>
                         </GridPane>
                         <Button fx:id="serPortOpenBtn" minWidth="130" mnemonicParsing="false"


Reviews:
user: login: sourcery-ai[bot]
body: Hey @DreamAwakenFateBroke - I've reviewed your changes - here's some feedback:

- Consider removing the commented-out code blocks if they are no longer necessary.
- Consider translating the comments for FXML fields to English to maintain consistency with the surrounding code.
- Using a data model for `sendCount` and `recvCount` instead of directly parsing their text values from UI components could improve robustness.

<details>
<summary>Here's what I looked at during the review</summary>

- 🟡 **General issues**: 1 issue found
- 🟢 **Security**: all looks good
- 🟢 **Testing**: all looks good
- 🟢 **Documentation**: all looks good
</details>

***

<details>
<summary>Sourcery is free for open source - if you like our reviews please consider sharing them ✨</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20got%20an%20instant%20code%20review%20from%20%40SourceryAI%2C%20and%20it%20was%20brilliant%21%20It%27s%20free%20for%20open%20source%20and%20has%20a%20free%20trial%20for%20private%20code.%20Check%20it%20out%20https%3A//sourcery.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20got%20an%20instant%20code%20review%20from%20%40SourceryAI%2C%20and%20it%20was%20brilliant%21%20It%27s%20free%20for%20open%20source%20and%20has%20a%20free%20trial%20for%20private%20code.%20Check%20it%20out%20https%3A//sourcery.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https://sourcery.ai)
- [Facebook](https://www.facebook.com/sharer/sharer.php?u=https://sourcery.ai)

</details>

<sub>
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
</sub>
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-10T06:48:42Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 3**

<details>
<summary>🔭 Outside diff range comments (2)</summary><blockquote>

<details>
<summary>qe/src/main/resources/com/tlcsdm/qe/fxml/serialPortTool.fxml (1)</summary><blockquote>

`58-63`: _🛠️ Refactor suggestion_

**增加了一行控件但未同步 `RowConstraints`，可能导致布局异常**

`GridPane` 现在有 6 行（0-5），而 `rowConstraints` 仍只定义了 5 条。如果父容器开启了严格的约束检查，运行时可能报错或无法按预期分配高度。  

```diff
                                 <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
                                 <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
                                 <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
                                 <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
                                 <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
+                                <!-- 新增流控行 -->
+                                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
```

</blockquote></details>
<details>
<summary>qe/src/main/java/com/tlcsdm/qe/tools/SerialPortTool.java (1)</summary><blockquote>

`342-354`: _⚠️ Potential issue_

**每次打开串口都会新增监听器，关闭时未移除**

多次打开/关闭同一端口时可能累积监听器，导致数据重复处理。开口前应检查并移除旧监听器，或在关闭端口前调用 `serialPort.removeDataListener()`.  

```diff
-                serialPortDataListener listener = new serialPortDataListener();
-                serialPort.addDataListener(listener);
+                // 避免重复注册
+                serialPort.removeDataListener();
+                serialPortDataListener listener = new serialPortDataListener();
+                serialPort.addDataListener(listener);
```

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (5)</summary><blockquote>

<details>
<summary>core/src/main/java/com/tlcsdm/core/util/DependencyInfo.java (1)</summary><blockquote>

`235-237`: **依赖列表插入位置可能影响可读性**

`jSerialComm` 插入到 `icns-core` 前面，而文件中其余依赖基本按 `artifact` 名称字母顺序排列。虽然这不会影响程序运行，但长期维护时会降低查找效率，建议保持排序一致性。  

```diff
-            new Dependency("com.fazecast", "jSerialComm", "2.11.0", false,
-                "https://fazecast.github.io/jSerialComm", "GNU LGPL",
-                "https://www.gnu.org/licenses/lgpl-3.0.html"),
+            // …放到按 artifact 排序的正确位置（如 j 开头区段末尾）
```

</blockquote></details>
<details>
<summary>qe/src/main/java/com/tlcsdm/qe/tools/SerialPortTool.java (4)</summary><blockquote>

`316-325`: **等待时间监听逻辑可移入 `IntegerTextFormatter` 简化校验**

目前通过 `ChangeListener` 手动捕获 `NumberFormatException`，可以改为给 `TextField` 设置只允许整数的 `TextFormatter`，避免多处 try-catch。

---

`364-386`: **发送长度统计重复计算，且存在潜在性能问题**

`hexStringToBytes(sendTextAear.getText())` 在十六进制路径下被调用两次，导致重复解析；大文本时性能浪费。  

```diff
-                    byte[] bytes = hexStringToBytes(sendTextAear.getText());
-                    serialPort.writeBytes(bytes, bytes.length);
-                    sendCount.setText(String.valueOf(
-                        (Integer.parseInt(sendCount.getText()) + hexStringToBytes(sendTextAear.getText()).length)));
+                    byte[] bytes = hexStringToBytes(sendTextAear.getText());
+                    serialPort.writeBytes(bytes, bytes.length);
+                    sendCount.setText(String.valueOf(
+                        (Integer.parseInt(sendCount.getText()) + bytes.length)));
```

---

`388-408`: **接收/发送计数清零逻辑正确，建议同步重置界面状态**

若循环发送未来启用，点击“重置统计”时还应停止 `Timeline` 并重置 `sendCycle` 复选框，以保持UI一致。

---

`487-496`: **`dispose` 仅关闭端口，未停止可能存在的 `Timeline`**

如果后续实现循环发送且 `Timeline` 处于运行状态，关闭窗口时需同时调用 `circularSending.stop()`，否则后台线程仍会运行。

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 82c4a115d356730568a61d3ac8ee684910f74a39 and 03a7c94ad94a6ce2d7d566cf7fb7aec1af447d7b.

</details>

<details>
<summary>📒 Files selected for processing (4)</summary>

* `core/src/main/java/com/tlcsdm/core/util/DependencyInfo.java` (1 hunks)
* `qe/src/main/java/com/tlcsdm/qe/tools/SerialPortTool.java` (11 hunks)
* `qe/src/main/java/com/tlcsdm/qe/util/QeConstant.java` (1 hunks)
* `qe/src/main/resources/com/tlcsdm/qe/fxml/serialPortTool.fxml` (1 hunks)

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (9)</summary>

* GitHub Check: build (21, macos-latest, false)
* GitHub Check: build (21, ubuntu-latest, false)
* GitHub Check: build (21, windows-latest, false)
* GitHub Check: build (17, windows-latest, false)
* GitHub Check: build (17, macos-latest, false)
* GitHub Check: build (17, ubuntu-latest, false)
* GitHub Check: qodana
* GitHub Check: StepSecurity Harden-Runner
* GitHub Check: Summary

</details>

<details>
<summary>🔇 Additional comments (1)</summary><blockquote>

<details>
<summary>qe/src/main/java/com/tlcsdm/qe/util/QeConstant.java (1)</summary>

`97-100`: **新增依赖字符串与 DependencyInfo 中的 inUsed 状态不一致**

`DEPENDENCY_LIST` 中加入了 `"jSerialComm"`，表示此模块确实会使用该库。但在 `DependencyInfo` 中同名依赖的 `inUsed` 字段为 `false`。建议二者保持一致，避免后续做依赖过滤或生成清单时出现遗漏。

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-10T06:50:11Z
user: login: unknowIfGuestInDream
state: APPROVED
author_association: OWNER
submitted_at: 2025-05-11T12:37:38Z

Review comments:
diff_hunk: @@ -241,192 +229,226 @@
~    //https://gitee.com/aSingleDragon/rs232-client/blob/main/src/main/java/pers/hll/rs232/rs232client/controller/RS232ManageController.java
     // https://github.com/yiaoBang/SerialPortToolFX/blob/master/src/main/java/com/yiaoBang/serialPortToolFX/view/SerialPortView.java
 
     public void initializeUI() {
+        //无限循环发送
+        circularSending.setCycleCount(Timeline.INDEFINITE);
+
+        //        recvCount
+        //        sendNumber.textProperty().bind(viewModel.getSEND_LONG_PROPERTY().asString());
+        //        receiveNumber.textProperty().bind(viewModel.getRECEIVE_LONG_PROPERTY().asString());
 
         //        // 初始化常用波特率列表
         //        baudRateComboBox.getItems().addAll("9600", "4800", "2400", "1200");
~        //        // 设置波特率默认值
~        //        baudRateComboBox.setValue("9600");
~        //        // 波特率 不接受非数值输入
~        //        baudRateComboBox.getEditor().addEventFilter(KeyEvent.KEY_TYPED, event -> {
~        //            // 获取键入的字符
~        //            String character = event.getCharacter();
~        //            // 如果不是数值或删除 则消耗这个事件
~        //            if (!(character.matches("\\d") || character.isEmpty())) {
~        //                ViewUtil.alertError("只能输入数字(0-9)!");
~        //                event.consume();
~        //            }
~        //        });
~
~        // 初始化当前计算机串口信息
~        //        serialPortNameChoiceBox.getItems().addAll(SerialPortManager.findPorts());
~        //        if (!serialPortNameChoiceBox.getItems().isEmpty()) {
~        //            serialPortNameChoiceBox.setValue(serialPortNameChoiceBox.getItems().get(0));
~        //        }
~        serPort.setCellFactory(cellFactory);
~        serPort.setButtonCell(cellFactory.call(null));
~        SerialPort[] ports = SerialPort.getCommPorts();
~        if (ports.length != 0) {
~            for (SerialPort s : ports) {
~                serPort.getItems().add(s);
~            }
~            serPort.getSelectionModel().select(0);
~        }
~
~        String[] speeds = new String[]{
~            "100", "300", "600", "1200", "2400", "4800", "9600", "14400", "19200", "38400", "56000", "57600", "115200", "128000", "256000"
~        };
~        for (String s : speeds) {
~            serPortSpeed.getItems().add(s);
~        }
~        serPortSpeed.setValue("9600");
~
~        //串口检验位设置
~        String[] checks = new String[]{
~            "NONE", "ODD", "EVEN", "MARK", "SPACE"
~        };
~        for (String s : checks) {
~            serPortCheckBit.getItems().add(s);
~        }
~        serPortCheckBit.setValue("NONE");
~
~        //数据位设置
~        String[] databits = new String[]{
~            "5", "6", "7", "8"
~        };
~        for (String s : databits) {
~            serPortDataBit.getItems().add(s);
~        }
~        serPortDataBit.setValue("8");
~
~        //停止位设置
~        String[] stopbits = new String[]{
~            "1", "2"
~        };
~        for (String s : stopbits) {
~            serPortStopBit.getItems().add(s);
         }
         serPortStopBit.setValue("1");
 
+        //流控
+        //        String[] flowControl = new String[]{
+        //            "100", "300", "600", "1200"
+        //        };
+        //        for (String s : speeds) {
+        //            serPortSpeed.getItems().add(s);
+        //        }
+        //        serPortSpeed.setValue("9600");
+        //serFlowControl.getItems().addAll(SerialPort.FLOW_CONTROL_DISABLED);
+
+        //循环发送的等待时间(ms)
+        sendCycleRap.textProperty().addListener((o, oldValue, newValue) -> {
+            try {
+                waitTime = Integer.parseInt(newValue);
+                if (waitTime < 1) {
+                    waitTime = 1;
+                }
+            } catch (NumberFormatException e) {
+                sendCycleRap.setText(oldValue);
+            }
+        });
+
         serPortOpenBtn.setOnAction((ActionEvent event) -> {
             SerialPort serialPort = serPort.getSelectionModel().getSelectedItem();
             if (serialPort == null) {
~                return;
~            }
~            if (serialPort.isOpen()) {
~                serialPort.closePort();
~                serPortOpenBtn.setText("打开");
~                serPort.setDisable(false);
~                serPortSpeed.setDisable(false);
~                serPortCheckBit.setDisable(false);
                 serPortDataBit.setDisable(false);
                 serPortStopBit.setDisable(false);
             } else {
+                serialPortDataListener listener = new serialPortDataListener();
+                serialPort.addDataListener(listener);
                 serialPort.openPort();
                 //SerialPort.ONE_STOP_BIT
                 //SerialPort.NO_PARITY
~                serialPort.setComPortParameters(Integer.parseInt(serPortSpeed.getValue()),
~                    Integer.parseInt(serPortDataBit.getValue()), Integer.parseInt(serPortStopBit.getValue()),
~                    serPortCheckBit.getValue().equals("NONE") ? 0 : serPortCheckBit.getValue().equals("ODD") ? 1 :
~                        serPortCheckBit.getValue().equals("EVEN") ? 2 : serPortCheckBit.getValue().equals(
~                            "SPACE") ? 3 : 0);
                 serialPort.setFlowControl(SerialPort.FLOW_CONTROL_DISABLED);
                 serialPort.setComPortTimeouts(SerialPort.TIMEOUT_READ_BLOCKING | SerialPort.TIMEOUT_WRITE_BLOCKING,
                     1000, 1000);
-                //UsartRXEven();
+
                 serPortOpenBtn.setText("关闭");
                 serPort.setDisable(true);
                 serPortSpeed.setDisable(true);
~                serPortCheckBit.setDisable(true);
~                serPortDataBit.setDisable(true);
                 serPortStopBit.setDisable(true);
             }
         });
-        //
-        //        sendBtn.setOnAction(event -> {
-        //            if (null == serialPort || (!serialPort.isOpened())) {
-        //                // new AlertBox().display("错误", "请先打开串口");
-        //                return;
-        //            }
-        //            try {
-        //                if (sendHex.isSelected()) {
-        //                    serialPort.writeBytes(hexStringToBytes(sendTextAear.getText()));
-        //                    sendCount.setText(String.valueOf(
-        //                        (Integer.parseInt(sendCount.getText()) + hexStringToBytes(sendTextAear.getText()).length)));
-        //                } else {
-        //                    serialPort.writeBytes(sendTextAear.getText().getBytes());
-        //                    sendCount.setText(String.valueOf(
-        //                        (Integer.parseInt(sendCount.getText()) + sendTextAear.getText().getBytes().length)));
-        //                }
-        //
-        //            } catch (Exception e) {
-        //                //new AlertBox().display("发送数据错误", e.getMessage());
-        //            }
-        //        });
-        //
-        //        recvClear.setOnAction(event -> {
-        //            recvTextAear.setText("");
-        //        });
-        //        sendHex.setOnAction(event -> {
-        //            if (!sendHex.isSelected())
-        //                try {
-        //                    sendTextAear.setText(new String(hexStringToBytes(sendTextAear.getText())));
-        //                } catch (Exception e) {
-        //                    //new AlertBox().display("非法16进制字符", e.getMessage());
-        //                }
-        //            else
-        //                sendTextAear.setText(bytesToHexString(sendTextAear.getText().getBytes()));
-        //        });
-        //        sendClear.setOnAction(event -> {
-        //            sendTextAear.setText("");
-        //        });
-        //        CountReset.setOnAction(event -> {
-        //            sendCount.setText("0");
-        //            recvCount.setText("0");
-        //        });
+
+        sendBtn.setOnAction(event -> {
+            SerialPort serialPort = serPort.getSelectionModel().getSelectedItem();
+            if (null == serialPort || (!serialPort.isOpen())) {
+                // new AlertBox().display("错误", "请先打开串口");
+                return;
+            }
+            try {
+                if (sendHex.isSelected()) {
+                    byte[] bytes = hexStringToBytes(sendTextAear.getText());
+                    serialPort.writeBytes(bytes, bytes.length);
+                    sendCount.setText(String.valueOf(
+                        (Integer.parseInt(sendCount.getText()) + hexStringToBytes(sendTextAear.getText()).length)));
+                } else {
path: qe/src/main/java/com/tlcsdm/qe/tools/SerialPortTool.java
user: login: sourcery-ai[bot]
body: **suggestion (performance):** Optimize repeated hex conversion.

Call hexStringToBytes only once in the sendBtn action when 'sendHex' is selected; reuse the resulting byte array for both writing and any calculations to avoid redundant conversions.

```suggestion
                if (sendHex.isSelected()) {
                    byte[] bytes = hexStringToBytes(sendTextAear.getText());
                    serialPort.writeBytes(bytes, bytes.length);
                    sendCount.setText(String.valueOf(
                        (Integer.parseInt(sendCount.getText()) + bytes.length)));
                } else {
```
created_at: 2025-05-10T06:48:42Z
author_association: NONE
diff_hunk: @@ -62,20 +62,23 @@
                                 <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
                             </rowConstraints>
                             <children>
-                                <Label text="串口号:" GridPane.columnIndex="0"/>
+                                <Label text="串口号" GridPane.columnIndex="0"/>
                                 <ComboBox fx:id="serPort" prefWidth="150.0" GridPane.columnIndex="1"/>
-                                <Label text="波特率:" GridPane.rowIndex="1"/>
+                                <Label text="波特率" GridPane.rowIndex="1"/>
                                 <ComboBox fx:id="serPortSpeed" editable="true" prefWidth="150.0"
                                           GridPane.columnIndex="1" GridPane.rowIndex="1"/>
-                                <Label text="检验位:" GridPane.rowIndex="2"/>
+                                <Label text="检验位" GridPane.rowIndex="2"/>
                                 <ComboBox fx:id="serPortCheckBit" prefWidth="150.0" GridPane.columnIndex="1"
                                           GridPane.rowIndex="2"/>
-                                <Label text="数据位:" GridPane.rowIndex="3"/>
+                                <Label text="数据位" GridPane.rowIndex="3"/>
                                 <ComboBox fx:id="serPortDataBit" prefWidth="150.0" GridPane.columnIndex="1"
                                           GridPane.rowIndex="3"/>
-                                <Label text="停止位:" GridPane.rowIndex="4"/>
+                                <Label text="停止位" GridPane.rowIndex="4"/>
                                 <ComboBox fx:id="serPortStopBit" prefWidth="150.0" GridPane.columnIndex="1"
                                           GridPane.rowIndex="4"/>
+                                <Label text="流控" GridPane.rowIndex="5"/>
+                                <ComboBox fx:id="serFlowControl" prefWidth="150.0" GridPane.columnIndex="1"
+                                          GridPane.rowIndex="5"/>
                             </children>
path: qe/src/main/resources/com/tlcsdm/qe/fxml/serialPortTool.fxml
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**`serFlowControl` 未初始化，界面将出现空下拉框**

虽然新控件已在 FXML 中声明，并在控制器中有字段，但 `initializeUI` 中设置选项的代码仍被注释掉，导致下拉框没有可选项，也没有与串口流控参数联动。  

请在 `initializeUI` 中补充类似代码：
```java
String[] flowControls = {"DISABLED", "RTS/CTS", "XON/XOFF"};
serFlowControl.getItems().addAll(flowControls);
serFlowControl.setValue("DISABLED");
```
并在打开串口时根据选择调用 `serialPort.setFlowControl(...)`。

<details>
<summary>🤖 Prompt for AI Agents (early access)</summary>

```
In qe/src/main/resources/com/tlcsdm/qe/fxml/serialPortTool.fxml around lines 79
to 82, the ComboBox serFlowControl is declared but not initialized with options,
causing it to appear empty. To fix this, in the controller's initializeUI
method, add code to populate serFlowControl with flow control options like
"DISABLED", "RTS/CTS", and "XON/XOFF", set the default value to "DISABLED", and
ensure that when opening the serial port, the selected flow control value is
applied by calling serialPort.setFlowControl(...) accordingly.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-10T06:50:10Z
author_association: NONE
diff_hunk: @@ -573,8 +582,9 @@
         public void serialEvent(SerialPortEvent event) {
             byte[] newData = event.getReceivedData();
             System.out.println("Received data of size: " + newData.length);
-            for (int i = 0; i < newData.length; ++i)
+            for (int i = 0; i < newData.length; ++i) {
                 System.out.print((char) newData[i]);
+            }
             System.out.println("\n");
path: qe/src/main/java/com/tlcsdm/qe/tools/SerialPortTool.java
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**数据接收回调未切到 UI 线程，且没有更新界面**

直接在监听器里 `System.out.print` 会导致 UI 无反馈。建议使用 `Platform.runLater` 将数据追加到 `recvTextAear`，并同步统计量。  

```java
Platform.runLater(() -> {
    recvTextAear.appendText(bytesToHexString(newData) + System.lineSeparator());
    recvCount.setText(String.valueOf(Integer.parseInt(recvCount.getText()) + newData.length));
});
```

<details>
<summary>🤖 Prompt for AI Agents (early access)</summary>

```
In qe/src/main/java/com/tlcsdm/qe/tools/SerialPortTool.java around lines 585 to
588, the data reception callback is printing directly to the console without
switching to the UI thread, causing no UI updates. Replace the System.out.print
loop with a Platform.runLater block that appends the received data as a hex
string to recvTextAear and updates recvCount accordingly, ensuring UI updates
happen on the JavaFX application thread.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-10T06:50:10Z
author_association: NONE
diff_hunk: @@ -113,7 +122,8 @@
     @FXML
     private Button sendBtn;
 
-    private Timer t;
+    private final Timeline circularSending = new Timeline();
+    private volatile long waitTime = 1000;
 
path: qe/src/main/java/com/tlcsdm/qe/tools/SerialPortTool.java
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**`Timeline` 仅声明未使用，循环发送功能仍不可用**

`circularSending` 实例化后没有任何 `KeyFrame`，也未与 `sendCycle` 开关联动，导致循环发送功能实际不可用。  

建议：

1. 使用 `KeyFrame` 定时执行发送逻辑。  
2. 在 `sendCycle` 复选框事件中启动/停止 `Timeline`，并同步禁用相关控件。

<details>
<summary>🤖 Prompt for AI Agents (early access)</summary>

```
In qe/src/main/java/com/tlcsdm/qe/tools/SerialPortTool.java around lines 125 to
127, the Timeline instance circularSending is declared but not used, so the
cyclic sending feature is non-functional. Fix this by adding a KeyFrame to
circularSending that periodically triggers the send logic. Also, modify the
sendCycle checkbox event handler to start or stop the circularSending Timeline
accordingly and disable or enable related controls to reflect the sending state.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-10T06:50:10Z
author_association: NONE

PR comments:
user: login: naming-conventions-bot[bot]
created_at: 2025-05-10T06:47:27Z
body: Thank you for following naming conventions! 😻
author_association: NONE
user: login: sourcery-ai[bot]
created_at: 2025-05-10T06:47:27Z
body: <!-- Generated by sourcery-ai[bot]: start review_guide -->

## Reviewer's Guide

This pull request revamps the `SerialPortTool` by integrating the `jSerialComm` library for robust serial communication, replacing the previous implementation. The UI is enhanced with new controls, such as a flow control selector, and previously dormant functionalities like hex mode toggling and data clearing are now active. Cyclic data sending has been refactored from `java.util.Timer` to `javafx.animation.Timeline` for better JavaFX integration, and resource management is improved with proper port closure on disposal. The separate control panel feature has been removed, streamlining the tool's interface.

### File-Level Changes

| Change | Details | Files |
| ------ | ------- | ----- |
| Integrated `jSerialComm` library for serial port operations and updated project dependencies. | <ul><li>Added `jSerialComm` as a new dependency.</li><li>Updated the `DEPENDENCY_LIST` constant.</li><li>Utilized `jSerialComm` APIs for port detection, opening, writing data, and handling received data events via `SerialPortDataListener`.</li></ul> | `qe/src/main/java/com/tlcsdm/qe/tools/SerialPortTool.java`<br/>`core/src/main/java/com/tlcsdm/core/util/DependencyInfo.java`<br/>`qe/src/main/java/com/tlcsdm/qe/util/QeConstant.java` |
| Enhanced UI with new controls and activated existing interaction logic. | <ul><li>Added an FXML ComboBox `serFlowControl` for selecting serial port flow control.</li><li>Activated event handlers for send button, receive/send area clearing, hex mode toggling for sending, and count reset.</li><li>Added Javadoc-style comments to FXML field declarations for improved clarity.</li></ul> | `qe/src/main/java/com/tlcsdm/qe/tools/SerialPortTool.java`<br/>`qe/src/main/resources/com/tlcsdm/qe/fxml/serialPortTool.fxml` |
| Refactored cyclic sending to use `Timeline` and removed the separate control panel. | <ul><li>Replaced `java.util.Timer` with `javafx.animation.Timeline` for handling cyclic message sending.</li><li>Implemented dynamic configuration of the send interval via the `sendCycleRap` TextField.</li><li>Removed the `getControlPanel()` method and overrode `hasControlPanel()` to return false.</li></ul> | `qe/src/main/java/com/tlcsdm/qe/tools/SerialPortTool.java` |
| Improved resource management and streamlined serial operation methods. | <ul><li>Implemented the `dispose()` method to ensure the serial port is closed when the tool is disposed.</li><li>Removed dedicated `closePort()` and `sendToPort()` helper methods, integrating their logic into event handlers or other methods.</li><li>Modified the serial port opening logic to register a `serialPortDataListener`.</li></ul> | `qe/src/main/java/com/tlcsdm/qe/tools/SerialPortTool.java` |

---

<details>
<summary>Tips and commands</summary>

#### Interacting with Sourcery

- **Trigger a new review:** Comment `@sourcery-ai review` on the pull request.
- **Continue discussions:** Reply directly to Sourcery's review comments.
- **Generate a GitHub issue from a review comment:** Ask Sourcery to create an
  issue from a review comment by replying to it. You can also reply to a
  review comment with `@sourcery-ai issue` to create an issue from it.
- **Generate a pull request title:** Write `@sourcery-ai` anywhere in the pull
  request title to generate a title at any time. You can also comment
  `@sourcery-ai title` on the pull request to (re-)generate the title at any time.
- **Generate a pull request summary:** Write `@sourcery-ai summary` anywhere in
  the pull request body to generate a PR summary at any time exactly where you
  want it. You can also comment `@sourcery-ai summary` on the pull request to
  (re-)generate the summary at any time.
- **Generate reviewer's guide:** Comment `@sourcery-ai guide` on the pull
  request to (re-)generate the reviewer's guide at any time.
- **Resolve all Sourcery comments:** Comment `@sourcery-ai resolve` on the
  pull request to resolve all Sourcery comments. Useful if you've already
  addressed all the comments and don't want to see them anymore.
- **Dismiss all Sourcery reviews:** Comment `@sourcery-ai dismiss` on the pull
  request to dismiss all existing Sourcery reviews. Especially useful if you
  want to start fresh with a new review - don't forget to comment
  `@sourcery-ai review` to trigger a new review!

#### Customizing Your Experience

Access your [dashboard](https://app.sourcery.ai) to:
- Enable or disable review features such as the Sourcery-generated pull request
  summary, the reviewer's guide, and others.
- Change the review language.
- Add, remove or edit custom review instructions.
- Adjust other review settings.

#### Getting Help

- [Contact our support team](mailto:support@sourcery.ai) for questions or feedback.
- Visit our [documentation](https://docs.sourcery.ai) for detailed guides and information.
- Keep in touch with the Sourcery team by following us on [X/Twitter](https://x.com/SourceryAI), [LinkedIn](https://www.linkedin.com/company/sourcery-ai/) or [GitHub](https://github.com/sourcery-ai).

</details>

<!-- Generated by sourcery-ai[bot]: end review_guide -->
author_association: NONE
user: login: vercel[bot]
created_at: 2025-05-10T06:47:27Z
body: [vc]: #FzvxI+m5Fg7EUnID/FgIW9fzgt2pWZKgpGndyDc6Nsg=:eyJpc01vbm9yZXBvIjp0cnVlLCJ0eXBlIjoiZ2l0aHViIiwicHJvamVjdHMiOlt7Im5hbWUiOiJqYXZhZngtdG9vbCIsImxpdmVGZWVkYmFjayI6eyJyZXNvbHZlZCI6MCwidW5yZXNvbHZlZCI6MCwidG90YWwiOjAsImxpbmsiOiJqYXZhZngtdG9vbC1naXQtc2VyLXVua25vd2lmZ3Vlc3RpbmRyZWFtcy1wcm9qZWN0cy52ZXJjZWwuYXBwIn0sImluc3BlY3RvclVybCI6Imh0dHBzOi8vdmVyY2VsLmNvbS91bmtub3dpZmd1ZXN0aW5kcmVhbXMtcHJvamVjdHMvamF2YWZ4LXRvb2wvOWFndDVORHc4UVg2dm9BQ2hkNUczTGpHR1dlSiIsInByZXZpZXdVcmwiOiJqYXZhZngtdG9vbC1naXQtc2VyLXVua25vd2lmZ3Vlc3RpbmRyZWFtcy1wcm9qZWN0cy52ZXJjZWwuYXBwIiwibmV4dENvbW1pdFN0YXR1cyI6IkRFUExPWUVEIiwicm9vdERpcmVjdG9yeSI6ImRvY3MifV19
**The latest updates on your projects**. Learn more about [Vercel for Git ↗︎](https://vercel.link/github-learn-more)

| Name | Status | Preview | Comments | Updated (UTC) |
| :--- | :----- | :------ | :------- | :------ |
| **javafx-tool** | ✅ Ready ([Inspect](https://vercel.com/unknowifguestindreams-projects/javafx-tool/9agt5NDw8QX6voAChd5G3LjGGWeJ)) | [Visit Preview](https://javafx-tool-git-ser-unknowifguestindreams-projects.vercel.app) | 💬 [**Add feedback**](https://vercel.live/open-feedback/javafx-tool-git-ser-unknowifguestindreams-projects.vercel.app?via=pr-comment-feedback-link) | May 11, 2025 0:37am |


author_association: NONE
user: login: quine-bot[bot]
created_at: 2025-05-10T06:47:27Z
body: > 👋 Figuring out if a PR is useful is hard, hopefully this will help.
- @DreamAwakenFateBroke has been on GitHub since **2022** and in that time has had **49 public PRs** merged
- Don't you recognize them? [They've been here before 🎉](https://github.com/unknowIfGuestInDream/javafxTool/issues?q=involves:DreamAwakenFateBroke)
- Here's a good example of their work: [javafxTool](https://github.com/unknowIfGuestInDream/javafxTool) (Javafx scaffolding, built on JDK17 + JavaFX21 + controlsfx 11.x.x + Maven)
- From looking at their profile, they seem to be good with **Java** and **FreeMarker**.

Their most recently public accepted PR is: https://github.com/unknowIfGuestInDream/javafxTool/pull/2133
author_association: NONE
user: login: coderabbitai[bot]
created_at: 2025-05-10T06:47:29Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- This is an auto-generated comment: failure by coderabbit.ai -->

> [!CAUTION]
> ## Review failed
> 
> The pull request is closed.

<!-- end of auto-generated comment: failure by coderabbit.ai -->
<!-- walkthrough_start -->

```markdown
## Walkthrough

本次更改在依赖管理、串口工具类和相关常量、界面布局等方面进行了调整。主要包括在依赖列表中新增 jSerialComm 库、对 SerialPortTool 类进行重构简化、常量列表中增加 jSerialComm、以及 FXML 布局中新增流控参数配置。

## Changes

| 文件/分组                                                         | 变更摘要                                                                                                         |
|-------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------|
| core/src/main/java/com/tlcsdm/core/util/DependencyInfo.java        | 静态依赖列表中新增 jSerialComm 依赖项，包含版本、主页、许可证等信息。                                             |
| qe/src/main/java/com/tlcsdm/qe/tools/SerialPortTool.java           | 重构并简化 SerialPortTool 类，移除无用代码，改用 JavaFX Timeline 实现循环发送，完善事件处理，新增 dispose 方法等。   |
| qe/src/main/java/com/tlcsdm/qe/util/QeConstant.java                | DEPENDENCY_LIST 常量增加 "jSerialComm"。                                                                         |
| qe/src/main/resources/com/tlcsdm/qe/fxml/serialPortTool.fxml       | 串口参数标签去除冒号，新增“流控”配置项及其 ComboBox，扩展串口设置界面。                                           |
| qe/src/main/resources/META-INF/MANIFEST.MF                         | 更新构建环境信息，包括 JDK 版本和 IntelliJ IDEA 版本，构建日期更新。                                               |
| .idea/artifacts/javafxTool_qe_mac_jar.xml 和 javafxTool_qe_win_jar.xml | 调整构建产物配置，切换平台输出路径，更新依赖库版本及新增 jSerialComm 依赖，重组依赖顺序。                          |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant User
    participant SerialPortTool
    participant SerialPort
    participant Timeline

    User->>SerialPortTool: 打开串口
    SerialPortTool->>SerialPort: openPort()
    SerialPortTool->>SerialPort: 添加数据监听器

    User->>SerialPortTool: 设置循环发送
    SerialPortTool->>Timeline: 启动定时器

    Timeline->>SerialPortTool: 定时触发发送事件
    SerialPortTool->>SerialPort: 写入数据

    User->>SerialPortTool: 关闭/释放工具
    SerialPortTool->>SerialPort: closePort()
```

## Assessment against linked issues

| Objective                                    | Addressed | Explanation                         |
|----------------------------------------------|-----------|-----------------------------------|
| 引入串口通信功能，支持基本串口操作 (#1900)   | ✅        |                                   |
| 提供串口参数配置界面，包含流控等参数 (#1900) | ✅        |                                   |
| 实现串口数据发送接收及循环发送功能 (#1900)   | ✅        |                                   |

## Possibly related PRs

- unknowIfGuestInDream/javafxTool#1713：该 PR 也在依赖列表中引入了 jSerialComm，与本次 PR 的依赖集成直接相关。
- unknowIfGuestInDream/javafxTool#2021：该 PR 最初引入了 SerialPortTool 类和 jSerialComm 依赖，本次 PR 对其进行了扩展和重构。
- unknowIfGuestInDream/javafxTool#2140：该 PR 也更新了依赖信息，包含 jSerialComm，和本次 PR 在依赖管理方面相关。

## Suggested reviewers

- DreamAwakenFateBroke

## Poem

> 小兔挥爪点依赖，  
> 串口新控件闪光彩。  
> 流控选项添一排，  
> Timeline 跳跃不懈怠。  
> 代码清爽如春风，  
> 新工具上线乐开怀！  
> 🐇✨
```

<!-- walkthrough_end -->
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->

---

<details>
<summary>📜 Recent review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 700671977dc59c224c7c735c2880442c2053fb03 and 271e3127f67360f6fa6cbfd8c7f3e8edbad90bf6.

</details>

<details>
<summary>📒 Files selected for processing (2)</summary>

* `.idea/artifacts/javafxTool_qe_mac_jar.xml` (1 hunks)
* `.idea/artifacts/javafxTool_qe_win_jar.xml` (1 hunks)

</details>

</details>
<!-- tips_start -->

---

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=unknowIfGuestInDream/javafxTool&utm_content=2138):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: NONE
user: login: mergify[bot]
created_at: 2025-05-10T06:47:59Z
body: Thanks for opening this pull request!
Please check out the [Contributing Guidelines](https://github.com/unknowIfGuestInDream/javafxTool/blob/master/CONTRIBUTING.md).
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-05-10T06:52:21Z
body: # [Qodana](https://qodana.cloud/projects/ARxR6/reports/vE1MK) Community for JVM

**It seems all right 👌**

No new problems were found according to the checks applied

💡 Qodana analysis was run in the pull request mode: only the changed files were checked
☁️ [View the detailed Qodana report](https://qodana.cloud/projects/ARxR6/reports/vE1MK)

<details>
<summary>Contact Qodana team</summary>

Contact us at [qodana-support@jetbrains.com](mailto:qodana-support@jetbrains.com)
  - Or via our issue tracker: https://jb.gg/qodana-issue
  - Or share your feedback: https://jb.gg/qodana-discussions
</details>
<!-- JetBrains/qodana-action@v2025.1.1 : Qodana Community for JVM,  -->
author_association: CONTRIBUTOR
user: login: mergify[bot]
created_at: 2025-05-11T12:30:21Z
body: @unknowIfGuestInDream
Please confirm the modification of MANIFEST.MF.
author_association: CONTRIBUTOR
user: login: sonarqubecloud[bot]
created_at: 2025-05-11T12:38:12Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=unknowIfGuestInDream_javafxTool&pullRequest=2138) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=unknowIfGuestInDream_javafxTool&pullRequest=2138&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=unknowIfGuestInDream_javafxTool&pullRequest=2138&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=unknowIfGuestInDream_javafxTool&pullRequest=2138&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=unknowIfGuestInDream_javafxTool&pullRequest=2138&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [8.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=unknowIfGuestInDream_javafxTool&pullRequest=2138&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=unknowIfGuestInDream_javafxTool&pullRequest=2138)


author_association: NONE