package home; import javax.swing.*; import javax.swing.border.TitledBorder; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.*; import java.text.SimpleDateFormat; import java.util.Date; public class ExtensionPanel extends JDialog { private static final long serialVersionUID = 1L; private MainFrame mainFrame; private JPanel commandPanel; private JScrollPane scrollPane; private JButton saveButton; private File commandFile; public ExtensionPanel(MainFrame parent) { super(parent, getString(parent, "extension"), false); // 设置为非模态对话框 this.mainFrame = parent; initializeUI(); loadCommands(); } private void initializeUI() { setSize(800, 500); // 修改默认打开窗口为800*500 setLocationRelativeTo(mainFrame); setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); setLayout(new BorderLayout()); // 创建命令面板 commandPanel = new JPanel(); commandPanel.setLayout(new BoxLayout(commandPanel, BoxLayout.Y_AXIS)); scrollPane = new JScrollPane(commandPanel); scrollPane.setBorder(BorderFactory.createTitledBorder( BorderFactory.createEtchedBorder(), getString(mainFrame, "common.commands"), TitledBorder.LEFT, TitledBorder.TOP )); // 创建按钮面板 JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); // 使用ButtonUtils创建样式按钮 saveButton = ButtonUtils.createBlueButton(getString(mainFrame, "save.common.commands"), 25); saveButton.setPreferredSize(new Dimension(120, 25)); saveButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { saveCommands(); } }); buttonPanel.add(saveButton); add(scrollPane, BorderLayout.CENTER); add(buttonPanel, BorderLayout.SOUTH); // 初始化指令文件 String rootPath = System.getProperty("user.dir"); File systemFileDir = new File(rootPath + File.separator + "systemfile"); if (!systemFileDir.exists()) { systemFileDir.mkdirs(); } commandFile = new File(systemFileDir, "zhiling.txt"); } private void loadCommands() { commandPanel.removeAll(); // 清空面板 if (commandFile.exists()) { try (BufferedReader reader = new BufferedReader(new FileReader(commandFile))) { String line; while ((line = reader.readLine()) != null) { if (!line.trim().isEmpty()) { // 每行格式:是否HEX:指令内容 String[] parts = line.split(":", 2); boolean isHex = false; String command = ""; if (parts.length == 2) { isHex = Boolean.parseBoolean(parts[0]); command = parts[1]; } else { command = line; } addCommandRow(isHex, command); } } } catch (IOException e) { JOptionPane.showMessageDialog(this, getString(mainFrame, "load.commands.failed") + e.getMessage(), getString(mainFrame, "error"), JOptionPane.ERROR_MESSAGE); } } // 添加一个空行用于新增命令 addCommandRow(false, ""); commandPanel.revalidate(); commandPanel.repaint(); } private void addCommandRow(boolean isHex, String command) { JPanel rowPanel = new JPanel(); rowPanel.setLayout(new BoxLayout(rowPanel, BoxLayout.X_AXIS)); rowPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); // 设置行间距 // HEX复选框 JCheckBox hexCheckBox = new JCheckBox(getString(mainFrame, "hex.send")); hexCheckBox.setSelected(isHex); hexCheckBox.setAlignmentY(Component.CENTER_ALIGNMENT); // 命令文本框 JTextField commandField = new JTextField(command); commandField.setMaximumSize(new Dimension(Integer.MAX_VALUE, 30)); // 限制高度,宽度自适应 // 发送按钮 JButton sendButton = createSendButton(); sendButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { sendCommand(hexCheckBox.isSelected(), commandField.getText()); } }); // 添加组件到行面板 rowPanel.add(hexCheckBox); rowPanel.add(Box.createHorizontalStrut(5)); // HEX复选框与文本框间隔5像素 rowPanel.add(commandField); rowPanel.add(Box.createHorizontalStrut(10)); // 文本框与按钮间隔10像素 rowPanel.add(sendButton); commandPanel.add(rowPanel); } private JButton createSendButton() { JButton button = new JButton(getString(mainFrame, "send")); // 设置按钮大小为60×20(宽×高) button.setPreferredSize(new Dimension(80, 20)); button.setMinimumSize(new Dimension(80, 20)); button.setMaximumSize(new Dimension(80, 20)); // 设置按钮样式 button.setBackground(new Color(0, 120, 215)); button.setForeground(Color.WHITE); button.setFocusPainted(false); button.setBorderPainted(false); button.setFont(button.getFont().deriveFont(Font.BOLD, 12f)); // 添加鼠标交互效果 button.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseEntered(java.awt.event.MouseEvent evt) { button.setBackground(new Color(0, 150, 255)); // 悬停时变亮 button.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); } public void mouseExited(java.awt.event.MouseEvent evt) { button.setBackground(new Color(0, 120, 215)); // 恢复正常颜色 button.setCursor(Cursor.getDefaultCursor()); } public void mousePressed(java.awt.event.MouseEvent evt) { // 点击效果 - 颜色变深并有轻微缩小效果 button.setBackground(new Color(0, 80, 160)); button.setBounds(button.getX() + 1, button.getY() + 1, 58, 18); } public void mouseReleased(java.awt.event.MouseEvent evt) { // 恢复原状 button.setBackground(new Color(0, 150, 255)); button.setBounds(button.getX() - 1, button.getY() - 1, 60, 20); } }); return button; } private void saveCommands() { try (BufferedWriter writer = new BufferedWriter(new FileWriter(commandFile))) { Component[] components = commandPanel.getComponents(); for (Component comp : components) { if (comp instanceof JPanel) { JPanel rowPanel = (JPanel) comp; Component[] rowComponents = rowPanel.getComponents(); boolean isHex = false; String command = ""; for (Component rowComp : rowComponents) { if (rowComp instanceof JCheckBox) { isHex = ((JCheckBox) rowComp).isSelected(); } else if (rowComp instanceof JTextField) { command = ((JTextField) rowComp).getText().trim(); } } if (!command.isEmpty()) { writer.write(isHex + ":" + command); writer.newLine(); } } } JOptionPane.showMessageDialog(this, getString(mainFrame, "save.commands.success"), getString(mainFrame, "prompt"), JOptionPane.INFORMATION_MESSAGE); } catch (IOException e) { JOptionPane.showMessageDialog(this, getString(mainFrame, "save.commands.failed") + e.getMessage(), getString(mainFrame, "error"), JOptionPane.ERROR_MESSAGE); } } private void sendCommand(boolean isHex, String command) { if (command == null || command.trim().isEmpty()) { JOptionPane.showMessageDialog(this, getString(mainFrame, "command.cannot.empty"), getString(mainFrame, "error"), JOptionPane.ERROR_MESSAGE); return; } // 获取当前时间 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String currentTime = dateFormat.format(new Date()); // 构建日志信息 StringBuilder logMessage = new StringBuilder(); logMessage.append("[").append(currentTime).append("] "); logMessage.append(getString(mainFrame, "send")).append(": "); // 根据HEX发送选项格式化内容 if (isHex) { logMessage.append("HEX "); logMessage.append(command); } else { logMessage.append("ASCII "); logMessage.append(command); } logMessage.append(" [").append(getString(mainFrame, "extension.command")).append("]"); logMessage.append("\n"); // 将发送信息添加到数据日志面板 addLogToDataLogPanel(logMessage.toString()); // 调用主框架的发送方法 if (mainFrame != null) { mainFrame.sendDataFromExtension(command, isHex); } } /** * 将日志信息添加到数据日志面板 * @param logMessage 日志信息 */ private void addLogToDataLogPanel(String logMessage) { try { // 通过主框架获取DataLogPanel实例 if (mainFrame != null) { // 直接调用MainFrame的日志添加方法,避免使用反射 mainFrame.addToDataLog(logMessage); } } catch (Exception ex) { // 备用方案:尝试使用反射 try { DataLogPanel dataLogPanel = mainFrame.getDataLogPanel(); if (dataLogPanel != null) { java.lang.reflect.Field logAreaField = DataLogPanel.class.getDeclaredField("logArea"); logAreaField.setAccessible(true); JTextArea logArea = (JTextArea) logAreaField.get(dataLogPanel); if (logArea != null) { logArea.append(logMessage); // 自动滚动到最后 logArea.setCaretPosition(logArea.getDocument().getLength()); } } } catch (Exception e) { System.err.println("无法访问数据日志区域: " + e.getMessage()); // 显示错误信息 JOptionPane.showMessageDialog(this, getString(mainFrame, "cannot.display.in.data.log") + ": " + e.getMessage(), getString(mainFrame, "error"), JOptionPane.ERROR_MESSAGE); } } } private static String getString(MainFrame mainFrame, String key) { return mainFrame != null ? mainFrame.getString(key) : key; } }