package chuankou;
|
import javax.swing.*;
|
import javax.swing.border.EmptyBorder;
|
import java.awt.*;
|
import com.fazecast.jSerialComm.SerialPort;
|
import chushihua.Chushihua;
|
|
/**
|
* 串口连接对话框
|
* 软件启动时显示,用于选择串口和波特率并连接
|
*/
|
@SuppressWarnings("serial")
|
public class SerialPortConnectionDialog extends JDialog {
|
|
// 颜色常量
|
private static final Color PRIMARY_COLOR = new Color(52, 152, 219);
|
private static final Color SECONDARY_COLOR = new Color(46, 204, 113);
|
private static final Color DANGER_COLOR = new Color(231, 76, 60);
|
private static final Color DARK_COLOR = new Color(255, 69, 0); // 改为橘黄色
|
private static final Color TEXT_COLOR = new Color(0, 0, 0); // 改为黑色以提高可读性
|
|
// UI组件
|
private JComboBox<String> portComboBox;
|
private JComboBox<String> baudRateComboBox;
|
private JButton connectButton;
|
private JButton refreshButton;
|
private JLabel statusLabel;
|
|
// 串口服务
|
private SerialPortService serialService;
|
private boolean isConnected = false;
|
|
// 连接回调接口
|
private ConnectionCallback callback;
|
|
public SerialPortConnectionDialog(JFrame parent, ConnectionCallback callback) {
|
super(parent, "串口连接", true);
|
this.callback = callback;
|
initializeUI();
|
refreshSerialPorts();
|
loadDefaultSettings();
|
}
|
|
private void initializeUI() {
|
setSize(500, 300);
|
setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE); // 防止用户直接关闭
|
setLocationRelativeTo(null);
|
setResizable(false);
|
|
// 设置深色主题
|
try {
|
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
|
// 创建主面板
|
JPanel mainPanel = new JPanel();
|
mainPanel.setLayout(new BorderLayout());
|
mainPanel.setBackground(DARK_COLOR);
|
mainPanel.setBorder(new EmptyBorder(20, 20, 20, 20));
|
|
// 添加各个区域
|
mainPanel.add(createHeaderPanel(), BorderLayout.NORTH);
|
mainPanel.add(createConfigPanel(), BorderLayout.CENTER);
|
mainPanel.add(createButtonPanel(), BorderLayout.SOUTH);
|
|
getContentPane().add(mainPanel);
|
}
|
|
private JPanel createHeaderPanel() {
|
JPanel headerPanel = new JPanel(new BorderLayout());
|
headerPanel.setOpaque(false);
|
|
// 标题
|
JLabel titleLabel = new JLabel("串口连接设置");
|
titleLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 20));
|
titleLabel.setForeground(TEXT_COLOR);
|
|
// 状态标签
|
statusLabel = new JLabel("请选择串口并连接");
|
statusLabel.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14));
|
statusLabel.setForeground(new Color(60, 60, 60)); // 改为深灰色
|
|
JPanel titlePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
titlePanel.setOpaque(false);
|
titlePanel.add(titleLabel);
|
|
JPanel statusPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
statusPanel.setOpaque(false);
|
statusPanel.add(statusLabel);
|
|
headerPanel.add(titlePanel, BorderLayout.NORTH);
|
headerPanel.add(statusPanel, BorderLayout.SOUTH);
|
|
return headerPanel;
|
}
|
|
private JPanel createConfigPanel() {
|
JPanel configPanel = new JPanel(new GridBagLayout());
|
configPanel.setOpaque(false);
|
configPanel.setBorder(new EmptyBorder(20, 0, 20, 0));
|
|
GridBagConstraints gbc = new GridBagConstraints();
|
gbc.fill = GridBagConstraints.HORIZONTAL;
|
gbc.insets = new Insets(10, 10, 10, 10);
|
|
// 串口选择标签
|
JLabel portLabel = new JLabel("串口:");
|
portLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 14));
|
portLabel.setForeground(TEXT_COLOR);
|
gbc.gridx = 0;
|
gbc.gridy = 0;
|
gbc.weightx = 0.2;
|
configPanel.add(portLabel, gbc);
|
|
// 串口选择下拉框
|
portComboBox = new JComboBox<>();
|
portComboBox.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14));
|
portComboBox.setBackground(Color.WHITE);
|
portComboBox.setForeground(Color.BLACK);
|
gbc.gridx = 1;
|
gbc.gridy = 0;
|
gbc.weightx = 0.6;
|
configPanel.add(portComboBox, gbc);
|
|
// 刷新按钮
|
refreshButton = new JButton("刷新");
|
refreshButton.setFont(new Font("Microsoft YaHei", Font.PLAIN, 12));
|
refreshButton.setBackground(PRIMARY_COLOR);
|
refreshButton.setForeground(Color.WHITE);
|
refreshButton.setFocusPainted(false);
|
refreshButton.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));
|
refreshButton.addActionListener(e -> refreshSerialPorts());
|
gbc.gridx = 2;
|
gbc.gridy = 0;
|
gbc.weightx = 0.2;
|
configPanel.add(refreshButton, gbc);
|
|
// 波特率选择标签
|
JLabel baudLabel = new JLabel("波特率:");
|
baudLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 14));
|
baudLabel.setForeground(TEXT_COLOR);
|
gbc.gridx = 0;
|
gbc.gridy = 1;
|
gbc.weightx = 0.2;
|
configPanel.add(baudLabel, gbc);
|
|
// 波特率选择下拉框
|
baudRateComboBox = new JComboBox<>(new String[]{
|
"9600", "19200", "38400", "57600", "115200", "230400", "460800", "921600"
|
});
|
baudRateComboBox.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14));
|
baudRateComboBox.setBackground(Color.WHITE);
|
baudRateComboBox.setForeground(Color.BLACK);
|
gbc.gridx = 1;
|
gbc.gridy = 1;
|
gbc.weightx = 0.6;
|
configPanel.add(baudRateComboBox, gbc);
|
|
return configPanel;
|
}
|
|
private JPanel createButtonPanel() {
|
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 0));
|
buttonPanel.setOpaque(false);
|
buttonPanel.setBorder(new EmptyBorder(10, 0, 0, 0));
|
|
// 连接按钮
|
connectButton = new JButton("连接串口");
|
connectButton.setFont(new Font("Microsoft YaHei", Font.BOLD, 16));
|
connectButton.setBackground(SECONDARY_COLOR);
|
connectButton.setForeground(Color.WHITE);
|
connectButton.setFocusPainted(false);
|
connectButton.setBorder(BorderFactory.createEmptyBorder(10, 30, 10, 30));
|
connectButton.addActionListener(e -> connectSerialPort());
|
|
// 退出按钮
|
JButton exitButton = new JButton("退出程序");
|
exitButton.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14));
|
exitButton.setBackground(DANGER_COLOR);
|
exitButton.setForeground(Color.WHITE);
|
exitButton.setFocusPainted(false);
|
exitButton.setBorder(BorderFactory.createEmptyBorder(8, 20, 8, 20));
|
exitButton.addActionListener(e -> {
|
System.exit(0);
|
});
|
|
buttonPanel.add(connectButton);
|
buttonPanel.add(exitButton);
|
|
return buttonPanel;
|
}
|
|
private void refreshSerialPorts() {
|
String previouslySelected = portComboBox.getSelectedItem() != null ?
|
portComboBox.getSelectedItem().toString() : null;
|
|
portComboBox.removeAllItems();
|
SerialPort[] ports = SerialPort.getCommPorts();
|
|
if (ports.length == 0) {
|
portComboBox.addItem("未检测到串口");
|
connectButton.setEnabled(false);
|
} else {
|
for (SerialPort port : ports) {
|
portComboBox.addItem(port.getSystemPortName() + " - " + port.getDescriptivePortName());
|
}
|
connectButton.setEnabled(true);
|
|
// 尝试恢复之前的选择
|
if (previouslySelected != null) {
|
for (int i = 0; i < portComboBox.getItemCount(); i++) {
|
if (portComboBox.getItemAt(i).equals(previouslySelected)) {
|
portComboBox.setSelectedIndex(i);
|
break;
|
}
|
}
|
}
|
}
|
}
|
|
private void loadDefaultSettings() {
|
try {
|
// 从Chushihua获取默认串口和波特率
|
if (Chushihua.getInstance().isInitialized()) {
|
String defaultPort = Chushihua.getInstance().getSystemProperty(Chushihua.PROP_DEFAULT_SERIAL_PORT);
|
int defaultBaudrate = Chushihua.getInstance().getBaudrate();
|
|
// 设置默认波特率
|
baudRateComboBox.setSelectedItem(String.valueOf(defaultBaudrate));
|
|
// 尝试选择默认串口
|
if (defaultPort != null && !defaultPort.isEmpty()) {
|
for (int i = 0; i < portComboBox.getItemCount(); i++) {
|
String portItem = portComboBox.getItemAt(i);
|
if (portItem.startsWith(defaultPort)) {
|
portComboBox.setSelectedIndex(i);
|
break;
|
}
|
}
|
}
|
}
|
} catch (Exception e) {
|
System.err.println("加载默认设置失败: " + e.getMessage());
|
}
|
}
|
|
private void connectSerialPort() {
|
if (portComboBox.getSelectedIndex() == -1 || portComboBox.getItemAt(0).equals("未检测到串口")) {
|
showMessage("错误", "没有可用的串口", "error");
|
return;
|
}
|
|
String portName = portComboBox.getSelectedItem().toString().split(" - ")[0];
|
int baudRate = Integer.parseInt(baudRateComboBox.getSelectedItem().toString());
|
|
// 禁用按钮,防止重复点击
|
connectButton.setEnabled(false);
|
connectButton.setText("连接中...");
|
statusLabel.setText("正在连接 " + portName + " ...");
|
|
// 在新线程中连接串口,避免阻塞UI
|
new Thread(() -> {
|
try {
|
serialService = new SerialPortService();
|
boolean success = serialService.open(portName, baudRate);
|
|
SwingUtilities.invokeLater(() -> {
|
if (success) {
|
isConnected = true;
|
connectButton.setText("连接成功");
|
connectButton.setBackground(SECONDARY_COLOR);
|
statusLabel.setText("串口连接成功: " + portName + " (" + baudRate + "bps)");
|
|
// 设置Sendmsg的串口服务
|
Sendmsg.setSerialService(serialService, true);
|
|
// 启动协议解析器
|
if (serialService.getProtocolParser() != null) {
|
serialService.getProtocolParser().start();
|
//System.out.println("串口协议解析器已启动");
|
}
|
|
// 启动数据捕获并启用调试输出
|
serialService.enableDebugOutput();
|
serialService.startCapture(data -> {
|
// 这里会触发SerialPortService中的//System.out.println打印
|
});
|
|
// 重要修改:移除自动创建主界面的代码
|
// 只需要通知回调并关闭对话框
|
SwingUtilities.invokeLater(() -> {
|
try {
|
dispose();
|
if (callback != null) {
|
callback.onConnectionSuccess(serialService);
|
}
|
} catch (Exception e) {
|
e.printStackTrace();
|
showMessage("错误", "串口连接回调失败: " + e.getMessage(), "error");
|
}
|
});
|
|
} else {
|
// 连接失败处理保持不变...
|
}
|
});
|
|
} catch (Exception e) {
|
// 异常处理保持不变...
|
}
|
}).start();
|
}
|
|
private void showMessage(String title, String message, String type) {
|
int messageType;
|
switch (type) {
|
case "error":
|
messageType = JOptionPane.ERROR_MESSAGE;
|
break;
|
case "warning":
|
messageType = JOptionPane.WARNING_MESSAGE;
|
break;
|
case "success":
|
messageType = JOptionPane.INFORMATION_MESSAGE;
|
break;
|
default:
|
messageType = JOptionPane.INFORMATION_MESSAGE;
|
}
|
|
JOptionPane.showMessageDialog(this, message, title, messageType);
|
}
|
|
private ImageIcon createIcon(String emoji, int size) {
|
JLabel label = new JLabel(emoji);
|
label.setFont(new Font("Segoe UI Emoji", Font.PLAIN, size));
|
label.setSize(size, size);
|
|
// 创建一个图像
|
java.awt.image.BufferedImage image = new java.awt.image.BufferedImage(
|
size, size, java.awt.image.BufferedImage.TYPE_INT_ARGB);
|
Graphics2D g2 = image.createGraphics();
|
label.print(g2);
|
g2.dispose();
|
|
return new ImageIcon(image);
|
}
|
|
@Override
|
public void dispose() {
|
// 如果连接失败,关闭串口
|
if (!isConnected && serialService != null) {
|
serialService.close();
|
}
|
super.dispose();
|
}
|
|
/**
|
* 连接回调接口
|
*/
|
public interface ConnectionCallback {
|
void onConnectionSuccess(SerialPortService serialService);
|
}
|
|
/**
|
* 静态方法:显示串口连接对话框
|
*/
|
public static boolean showConnectionDialog(JFrame parent) {
|
final boolean[] connectionSuccess = {false};
|
final SerialPortService[] connectedService = {null};
|
|
try {
|
SerialPortConnectionDialog dialog = new SerialPortConnectionDialog(parent,
|
new ConnectionCallback() {
|
@Override
|
public void onConnectionSuccess(SerialPortService serialService) {
|
connectionSuccess[0] = true;
|
connectedService[0] = serialService;
|
|
// 重要修改:移除自动打开主界面的代码
|
// 由Homein统一管理主界面的创建和显示
|
//System.out.println("串口连接成功,准备返回控制权给主程序");
|
|
// 只需要关闭对话框,不创建主界面
|
// 主界面将在Homein.showMainInterface()中创建
|
}
|
});
|
|
dialog.setVisible(true);
|
|
// 等待对话框关闭
|
return connectionSuccess[0];
|
} catch (Exception e) {
|
e.printStackTrace();
|
JOptionPane.showMessageDialog(parent,
|
"创建串口连接对话框失败: " + e.getMessage(),
|
"错误",
|
JOptionPane.ERROR_MESSAGE);
|
return false;
|
}
|
}
|
}
|