package chuankou; import javax.swing.*; import javax.swing.border.EmptyBorder; import java.awt.*; import com.fazecast.jSerialComm.SerialPort; import chushihua.Chushihua; import home.CardMachineUI; /** * 串口连接对话框 * 软件启动时显示,用于选择串口和波特率并连接 */ public class SerialPortConnectionDialog extends JDialog { // 颜色常量 private static final Color PRIMARY_COLOR = new Color(52, 152, 219); private static final Color PRIMARY_DARK_COLOR = new Color(41, 128, 185); 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 portComboBox; private JComboBox 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; } } }