| | |
| | | package home; |
| | | |
| | | import jiexi.*; |
| | | |
| | | import javax.swing.*; |
| | | import java.awt.*; |
| | | import java.net.*; |
| | | import java.io.IOException; |
| | | import java.util.Vector; |
| | | import java.util.Map; |
| | | import java.util.HashMap; |
| | | import java.util.HashSet; |
| | | import java.util.Set; |
| | | |
| | | public class NetworkConfigPanel extends JPanel { |
| | | // 基础设置面板组件 |
| | | private JComboBox<String> ipTypeComboBox; |
| | | private JTextField staticIpField; |
| | | private JTextField subnetMaskField; |
| | | private JTextField gatewayField; |
| | | private JTextField dnsServerField; |
| | | private JTextField macAddressField; |
| | | private JTextField timeoutRestartField; |
| | | private JTextField httpServerPortField; |
| | | private JTextField usernameField; |
| | | private JTextField passwordField; |
| | | private JTextField deviceNameField; |
| | | |
| | | // 选项复选框 |
| | | private JCheckBox indexCheckBox; |
| | | private JCheckBox resetCheckBox; |
| | | private JCheckBox linkCheckBox; |
| | | private JCheckBox rfc2217CheckBox; |
| | | private JCheckBox cacheClearCheckBox; |
| | | private JCheckBox serialSettingsCheckBox; |
| | | |
| | | // 端口设置面板组件 |
| | | private JComboBox<String> workModeComboBox; |
| | | private JTextField targetUrlField; |
| | | private JTextField shortConnectionTimeField; |
| | | private JComboBox<String> baudRateComboBox; |
| | | private JTextField localPortField; |
| | | private JTextField remotePortField; |
| | | private JComboBox<String> tcpClientCountComboBox; |
| | | private JCheckBox enableShortConnectionCheckBox; |
| | | |
| | | // 串口参数组件 |
| | | private JComboBox<String> parityComboBox; |
| | | private JComboBox<String> dataBitsComboBox; |
| | | private JComboBox<String> stopBitsComboBox; |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | private MainFrame mainFrame; |
| | | private JComboBox<String> protocolCombo; |
| | | private JTextField addressField, portField; |
| | | private JButton openBtn, searchBtn; |
| | | private JLabel protocolLabel, addressLabel, portLabel; |
| | | private JButton readBtn, searchBtn, saveBtn; |
| | | private JTable deviceTable; |
| | | private JPanel basicSettingsPanel, portSettingsPanel; |
| | | |
| | | // 新增:标签引用用于语言切换 |
| | | private JLabel deviceListLabel; |
| | | |
| | | // 保存所有参数行的标签引用,用于语言切换 |
| | | private Map<String, JLabel> parameterLabels = new HashMap<>(); |
| | | private JLabel optionsLabel; |
| | | private JLabel parityDataStopLabel; |
| | | |
| | | // 在类变量区域添加 |
| | | private DeviceConfig currentDeviceConfig; |
| | | |
| | | public NetworkConfigPanel(MainFrame mainFrame) { |
| | | this.mainFrame = mainFrame; |
| | | initializeUI(); |
| | | } |
| | | |
| | | |
| | | private void initializeUI() { |
| | | setLayout(new BorderLayout()); |
| | | |
| | | // 控制面板 |
| | | // 控制面板 |
| | | add(createControlPanel(), BorderLayout.NORTH); |
| | | |
| | | // 设备表格和配置面板 |
| | | // 设备表格和配置面板 |
| | | JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); |
| | | splitPane.setLeftComponent(createDeviceTablePanel()); |
| | | splitPane.setRightComponent(createConfigPanel()); |
| | | splitPane.setDividerLocation(400); |
| | | |
| | | add(splitPane, BorderLayout.CENTER); |
| | | } |
| | | |
| | | |
| | | private JPanel createControlPanel() { |
| | | JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 5)); |
| | | |
| | | protocolLabel = new JLabel(getString("protocol.type")); |
| | | panel.add(protocolLabel); |
| | | |
| | | protocolCombo = new JComboBox<>(new String[]{"UDP", "TCP"}); |
| | | protocolCombo.setPreferredSize(new Dimension(150, 25)); |
| | | panel.add(protocolCombo); |
| | | |
| | | addressLabel = new JLabel(getString("local.host.address")); |
| | | panel.add(addressLabel); |
| | | |
| | | addressField = new JTextField(); |
| | | addressField.setPreferredSize(new Dimension(150, 25)); |
| | | panel.add(addressField); |
| | | |
| | | portLabel = new JLabel(getString("local.host.port")); |
| | | panel.add(portLabel); |
| | | |
| | | portField = new JTextField(); |
| | | portField.setPreferredSize(new Dimension(150, 25)); |
| | | panel.add(portField); |
| | | |
| | | // 使用ButtonUtils获取统一样式的按钮 |
| | | openBtn = ButtonUtils.createBlueButton(getString("open")); |
| | | searchBtn = ButtonUtils.createBlueButton(getString("search.devices")); |
| | | |
| | | panel.add(openBtn); |
| | | readBtn = ButtonUtils.createBlueButton(getString("read.parameters")); |
| | | saveBtn = ButtonUtils.createBlueButton(getString("save.parameters")); // 新增保存按钮 |
| | | |
| | | // 添加按钮的点击事件监听器 |
| | | searchBtn.addActionListener(e -> searchDevices()); |
| | | readBtn.addActionListener(e -> readDevices()); |
| | | saveBtn.addActionListener(e -> saveDeviceConfig()); // 新增保存事件 |
| | | |
| | | panel.add(searchBtn); |
| | | |
| | | panel.add(readBtn); |
| | | panel.add(saveBtn); // 添加到面板 |
| | | |
| | | return panel; |
| | | } |
| | | |
| | | |
| | | private void readDevices() { |
| | | // 获取选中的设备 |
| | | int selectedRow = deviceTable.getSelectedRow(); |
| | | if (selectedRow == -1) { |
| | | JOptionPane.showMessageDialog(this, |
| | | getString("please.select.device"), |
| | | getString("prompt"), |
| | | JOptionPane.WARNING_MESSAGE); |
| | | return; |
| | | } |
| | | |
| | | // 检查是否只选中了一个设备 |
| | | int[] selectedRows = deviceTable.getSelectedRows(); |
| | | if (selectedRows.length > 1) { |
| | | JOptionPane.showMessageDialog(this, |
| | | getString("select.one.device"), |
| | | getString("prompt"), |
| | | JOptionPane.WARNING_MESSAGE); |
| | | return; |
| | | } |
| | | |
| | | // 获取选中设备的IP和MAC地址 |
| | | String deviceIp = (String) deviceTable.getValueAt(selectedRow, 1); // 第二列是IP地址 |
| | | String deviceMac = (String) deviceTable.getValueAt(selectedRow, 3); // 第四列是MAC地址 |
| | | |
| | | // 在新线程中执行UDP读取操作 |
| | | new Thread(() -> { |
| | | DatagramSocket socket = null; |
| | | try { |
| | | // 创建UDP Socket |
| | | socket = new DatagramSocket(); |
| | | socket.setSoTimeout(5000); // 设置5秒超时 |
| | | // 准备读取配置的数据 |
| | | byte[] sendData = DellS2.reads2peizhi((byte) 0x03, deviceMac); |
| | | // 创建目标地址:选中设备的IP,端口1500 |
| | | InetAddress deviceAddress = InetAddress.getByName(deviceIp); |
| | | int port = 1500; |
| | | // 创建数据包 |
| | | DatagramPacket packet = new DatagramPacket(sendData, sendData.length, deviceAddress, port); |
| | | // 发送读取请求 |
| | | socket.send(packet); |
| | | // 准备接收响应 |
| | | byte[] receiveData = new byte[1024]; |
| | | DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); |
| | | // 接收响应 |
| | | socket.receive(receivePacket); |
| | | // 处理响应数据 |
| | | processReadResponse(receivePacket, deviceIp, deviceMac); |
| | | } catch (SocketTimeoutException e) { |
| | | SwingUtilities.invokeLater(() -> { |
| | | JOptionPane.showMessageDialog(this, |
| | | getString("read.timeout"), |
| | | getString("error"), |
| | | JOptionPane.ERROR_MESSAGE); |
| | | }); |
| | | } catch (UnknownHostException e) { |
| | | SwingUtilities.invokeLater(() -> { |
| | | JOptionPane.showMessageDialog(this, |
| | | getString("invalid.ip.address") + ": " + deviceIp, |
| | | getString("error"), |
| | | JOptionPane.ERROR_MESSAGE); |
| | | }); |
| | | } catch (IOException e) { |
| | | SwingUtilities.invokeLater(() -> { |
| | | JOptionPane.showMessageDialog(this, |
| | | getString("read.device.error") + ": " + e.getMessage(), |
| | | getString("error"), |
| | | JOptionPane.ERROR_MESSAGE); |
| | | }); |
| | | e.printStackTrace(); |
| | | } finally { |
| | | // 关闭socket |
| | | if (socket != null && !socket.isClosed()) { |
| | | socket.close(); |
| | | } |
| | | } |
| | | }).start(); |
| | | } |
| | | |
| | | /** |
| | | * 处理读取配置的响应数据 |
| | | */ |
| | | private void processReadResponse(DatagramPacket packet, String deviceIp, String deviceMac) { |
| | | // 获取响应数据 |
| | | byte[] responseData = packet.getData(); |
| | | int dataLength = packet.getLength(); |
| | | |
| | | // 将字节数据转换为十六进制字符串 |
| | | String hexData = bytesToHex(responseData, dataLength); |
| | | |
| | | // 打印到控制台 |
| | | System.out.println(hexData); |
| | | DeviceConfig deviceConfig = DeviceConfigParser.parseDeviceConfig(hexData); |
| | | |
| | | // 保存当前设备配置 |
| | | this.currentDeviceConfig = deviceConfig; |
| | | |
| | | // 将解析的配置数据应用到UI组件 |
| | | updateUIWithDeviceConfig(deviceConfig); |
| | | |
| | | // 在UI线程中显示成功消息 |
| | | SwingUtilities.invokeLater(() -> { |
| | | JOptionPane.showMessageDialog(this, |
| | | getString("read.success") + "\nIP: " + deviceIp + "\nMAC: " + deviceMac, |
| | | getString("success"), |
| | | JOptionPane.INFORMATION_MESSAGE); |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * 保存设备配置 - 将UI配置赋值回DeviceConfig对象并通过UDP广播发送 |
| | | */ |
| | | private void saveDeviceConfig() { |
| | | if (currentDeviceConfig == null) { |
| | | JOptionPane.showMessageDialog(this, |
| | | getString("read.parameters.first"), |
| | | getString("prompt"), |
| | | JOptionPane.WARNING_MESSAGE); |
| | | return; |
| | | } |
| | | |
| | | try { |
| | | // 从UI更新基础设置到DeviceConfig |
| | | updateDeviceConfigFromBasicSettings(); |
| | | |
| | | // 从UI更新端口设置到DeviceConfig |
| | | updateDeviceConfigFromPortSettings(); |
| | | |
| | | String mac = currentDeviceConfig.getMacAddress().replaceAll(":", ""); |
| | | byte[] bytes = DellS2.alert_s2(currentDeviceConfig.getStaticIp(), currentDeviceConfig.getGatewayIp(), |
| | | currentDeviceConfig.getSubnetMask(), currentDeviceConfig.getModuleName(), mac); |
| | | byte[] bytes1 = DellS2.alert_s2_chuankou(currentDeviceConfig.getTargetUrl(), mac, |
| | | "0" + currentDeviceConfig.getWorkMode(), currentDeviceConfig.getRemotePort() + "", |
| | | currentDeviceConfig.getBaudRate() + ""); |
| | | byte[] bytes2 = DellS2.reads2peizhi((byte) 0x02, mac); |
| | | // 在新线程中执行UDP发送操作 |
| | | new Thread(() -> { |
| | | DatagramSocket socket = null; |
| | | try { |
| | | // 创建UDP Socket |
| | | socket = new DatagramSocket(); |
| | | socket.setBroadcast(true); |
| | | |
| | | // 创建广播地址:255.255.255.255,端口1500 |
| | | InetAddress broadcastAddress = InetAddress.getByName("255.255.255.255"); |
| | | int port = 1500; |
| | | |
| | | // 发送第一个数据包 (bytes) |
| | | if (bytes != null && bytes.length > 0) { |
| | | DatagramPacket packet1 = new DatagramPacket(bytes, bytes.length, broadcastAddress, port); |
| | | socket.send(packet1); |
| | | } |
| | | |
| | | if (bytes1 != null && bytes1.length > 0) { |
| | | DatagramPacket packet2 = new DatagramPacket(bytes1, bytes1.length, broadcastAddress, port); |
| | | socket.send(packet2); |
| | | } |
| | | |
| | | if (bytes2 != null && bytes2.length > 0) { |
| | | DatagramPacket packet3 = new DatagramPacket(bytes2, bytes2.length, broadcastAddress, port); |
| | | socket.send(packet3); |
| | | } |
| | | |
| | | SwingUtilities.invokeLater(() -> { |
| | | JOptionPane.showMessageDialog(this, |
| | | getString("save.success"), |
| | | getString("success"), |
| | | JOptionPane.INFORMATION_MESSAGE); |
| | | }); |
| | | |
| | | } catch (SocketException e) { |
| | | SwingUtilities.invokeLater(() -> { |
| | | JOptionPane.showMessageDialog(this, |
| | | getString("udp.socket.failed") + ": " + e.getMessage(), |
| | | getString("error"), |
| | | JOptionPane.ERROR_MESSAGE); |
| | | }); |
| | | } catch (UnknownHostException e) { |
| | | SwingUtilities.invokeLater(() -> { |
| | | JOptionPane.showMessageDialog(this, |
| | | getString("invalid.broadcast.address"), |
| | | getString("error"), |
| | | JOptionPane.ERROR_MESSAGE); |
| | | }); |
| | | } catch (IOException e) { |
| | | SwingUtilities.invokeLater(() -> { |
| | | JOptionPane.showMessageDialog(this, |
| | | getString("send.udp.failed") + ": " + e.getMessage(), |
| | | getString("error"), |
| | | JOptionPane.ERROR_MESSAGE); |
| | | }); |
| | | } finally { |
| | | // 关闭socket |
| | | if (socket != null && !socket.isClosed()) { |
| | | socket.close(); |
| | | } |
| | | } |
| | | }).start(); |
| | | |
| | | } catch (Exception e) { |
| | | JOptionPane.showMessageDialog(this, |
| | | getString("save.config.error") + ": " + e.getMessage(), |
| | | getString("error"), |
| | | JOptionPane.ERROR_MESSAGE); |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 从基础设置UI更新DeviceConfig |
| | | */ |
| | | private void updateDeviceConfigFromBasicSettings() { |
| | | // IP地址类型 |
| | | currentDeviceConfig.setIpType(ipTypeComboBox.getSelectedIndex()); |
| | | |
| | | // 网络配置 |
| | | currentDeviceConfig.setStaticIp(staticIpField.getText().trim()); |
| | | currentDeviceConfig.setSubnetMask(subnetMaskField.getText().trim()); |
| | | currentDeviceConfig.setGatewayIp(gatewayField.getText().trim()); |
| | | currentDeviceConfig.setDnsServer(dnsServerField.getText().trim()); |
| | | currentDeviceConfig.setMacAddress(macAddressField.getText().trim()); |
| | | |
| | | // 设备信息 |
| | | currentDeviceConfig.setModuleName(deviceNameField.getText().trim()); |
| | | currentDeviceConfig.setUsername(usernameField.getText().trim()); |
| | | currentDeviceConfig.setPassword(passwordField.getText().trim()); |
| | | |
| | | // 数字字段需要转换 |
| | | try { |
| | | if (!httpServerPortField.getText().trim().isEmpty()) { |
| | | currentDeviceConfig.setHttpServerPort(Integer.parseInt(httpServerPortField.getText().trim())); |
| | | } |
| | | if (!timeoutRestartField.getText().trim().isEmpty()) { |
| | | currentDeviceConfig.setTimeoutRestart(Integer.parseInt(timeoutRestartField.getText().trim())); |
| | | } |
| | | } catch (NumberFormatException e) { |
| | | throw new RuntimeException(getString("port.timeout.format.error"), e); |
| | | } |
| | | |
| | | // 功能选项 |
| | | currentDeviceConfig.setIndex(indexCheckBox.isSelected()); |
| | | currentDeviceConfig.setReset(resetCheckBox.isSelected()); |
| | | currentDeviceConfig.setLink(linkCheckBox.isSelected()); |
| | | currentDeviceConfig.setRfc2217(rfc2217CheckBox.isSelected()); |
| | | currentDeviceConfig.setCacheClear(cacheClearCheckBox.isSelected()); |
| | | } |
| | | |
| | | /** |
| | | * 从端口设置UI更新DeviceConfig |
| | | */ |
| | | private void updateDeviceConfigFromPortSettings() { |
| | | // 串口配置 |
| | | try { |
| | | if (baudRateComboBox.getSelectedItem() != null) { |
| | | currentDeviceConfig.setBaudRate(Integer.parseInt(baudRateComboBox.getSelectedItem().toString())); |
| | | } |
| | | |
| | | // 数据位、校验位、停止位需要根据描述反向映射到数值 |
| | | currentDeviceConfig.setDataBitsDesc(dataBitsComboBox.getSelectedItem().toString()); |
| | | currentDeviceConfig.setParityDesc(parityComboBox.getSelectedItem().toString()); |
| | | currentDeviceConfig.setStopBitsDesc(stopBitsComboBox.getSelectedItem().toString()); |
| | | |
| | | } catch (NumberFormatException e) { |
| | | throw new RuntimeException(getString("baudrate.format.error"), e); |
| | | } |
| | | |
| | | // 通信配置 |
| | | currentDeviceConfig.setWorkModeDesc(workModeComboBox.getSelectedItem().toString()); |
| | | currentDeviceConfig.setTargetUrl(targetUrlField.getText().trim()); |
| | | |
| | | // 数字字段需要转换 |
| | | try { |
| | | if (!shortConnectionTimeField.getText().trim().isEmpty()) { |
| | | currentDeviceConfig.setShortConnectionTime(Integer.parseInt(shortConnectionTimeField.getText().trim())); |
| | | } |
| | | if (!localPortField.getText().trim().isEmpty()) { |
| | | currentDeviceConfig.setLocalPort(Integer.parseInt(localPortField.getText().trim())); |
| | | } |
| | | if (!remotePortField.getText().trim().isEmpty()) { |
| | | currentDeviceConfig.setRemotePort(Integer.parseInt(remotePortField.getText().trim())); |
| | | } |
| | | if (tcpClientCountComboBox.getSelectedItem() != null) { |
| | | currentDeviceConfig.setTcpClientCount(Integer.parseInt(tcpClientCountComboBox.getSelectedItem().toString())); |
| | | } |
| | | } catch (NumberFormatException e) { |
| | | throw new RuntimeException(getString("port.time.format.error"), e); |
| | | } |
| | | |
| | | // 连接类型 |
| | | currentDeviceConfig.setConnectionType(enableShortConnectionCheckBox.isSelected() ? 0 : 1); |
| | | } |
| | | |
| | | /** |
| | | * 将DeviceConfig配置数据应用到UI组件 |
| | | */ |
| | | public void updateUIWithDeviceConfig(DeviceConfig config) { |
| | | if (config == null) return; |
| | | |
| | | // 在EDT线程中更新UI |
| | | SwingUtilities.invokeLater(() -> { |
| | | try { |
| | | // 更新基础设置面板 |
| | | updateBasicSettings(config); |
| | | // 更新端口设置面板 |
| | | updatePortSettings(config); |
| | | } catch (Exception e) { |
| | | System.err.println(getString("update.ui.error") + ": " + e.getMessage()); |
| | | e.printStackTrace(); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | private void updateBasicSettings(DeviceConfig config) { |
| | | // IP地址类型 |
| | | if (ipTypeComboBox != null) { |
| | | ipTypeComboBox.setSelectedIndex(config.getIpType()); |
| | | } |
| | | |
| | | // 网络配置 |
| | | setTextFieldText(staticIpField, config.getStaticIp()); |
| | | setTextFieldText(subnetMaskField, config.getSubnetMask()); |
| | | setTextFieldText(gatewayField, config.getGatewayIp()); |
| | | setTextFieldText(dnsServerField, config.getDnsServer()); |
| | | setTextFieldText(macAddressField, config.getMacAddress()); |
| | | |
| | | // 设备信息 |
| | | setTextFieldText(deviceNameField, config.getModuleName()); |
| | | setTextFieldText(usernameField, config.getUsername()); |
| | | setTextFieldText(passwordField, config.getPassword()); |
| | | setTextFieldText(httpServerPortField, String.valueOf(config.getHttpServerPort())); |
| | | setTextFieldText(timeoutRestartField, String.valueOf(config.getTimeoutRestart())); |
| | | |
| | | // 功能选项 |
| | | setCheckBoxSelected(indexCheckBox, config.isIndex()); |
| | | setCheckBoxSelected(resetCheckBox, config.isReset()); |
| | | setCheckBoxSelected(linkCheckBox, config.isLink()); |
| | | setCheckBoxSelected(rfc2217CheckBox, config.isRfc2217()); |
| | | setCheckBoxSelected(cacheClearCheckBox, config.isCacheClear()); |
| | | } |
| | | |
| | | private void updatePortSettings(DeviceConfig config) { |
| | | // 串口配置 |
| | | setComboBoxSelectedItem(baudRateComboBox, String.valueOf(config.getBaudRate())); |
| | | setComboBoxSelectedItem(dataBitsComboBox, config.getDataBitsDesc()); |
| | | setComboBoxSelectedItem(parityComboBox, config.getParityDesc()); |
| | | setComboBoxSelectedItem(stopBitsComboBox, config.getStopBitsDesc()); |
| | | |
| | | // 通信配置 |
| | | setComboBoxSelectedItem(workModeComboBox, config.getWorkModeDesc()); |
| | | setTextFieldText(targetUrlField, config.getTargetUrl()); |
| | | setTextFieldText(shortConnectionTimeField, String.valueOf(config.getShortConnectionTime())); |
| | | setTextFieldText(localPortField, String.valueOf(config.getLocalPort())); |
| | | setTextFieldText(remotePortField, String.valueOf(config.getRemotePort())); |
| | | setComboBoxSelectedItem(tcpClientCountComboBox, String.valueOf(config.getTcpClientCount())); |
| | | |
| | | // 连接类型 |
| | | setCheckBoxSelected(enableShortConnectionCheckBox, config.getConnectionType() == 0); |
| | | } |
| | | |
| | | // 辅助方法 |
| | | private void setTextFieldText(JTextField field, String text) { |
| | | if (field != null && text != null) { |
| | | field.setText(text); |
| | | } |
| | | } |
| | | |
| | | private void setCheckBoxSelected(JCheckBox checkBox, boolean selected) { |
| | | if (checkBox != null) { |
| | | checkBox.setSelected(selected); |
| | | } |
| | | } |
| | | |
| | | private void setComboBoxSelectedItem(JComboBox<String> comboBox, String item) { |
| | | if (comboBox != null && item != null) { |
| | | comboBox.setSelectedItem(item); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 搜索设备 - 发送UDP广播数据并监听返回 |
| | | */ |
| | | private void searchDevices() { |
| | | new Thread(() -> { |
| | | DatagramSocket socket = null; |
| | | try { |
| | | // 创建UDP Socket |
| | | socket = new DatagramSocket(); |
| | | socket.setBroadcast(true); |
| | | // 设置接收超时时间为5秒 |
| | | socket.setSoTimeout(5000); |
| | | // 准备要发送的数据:FF 01 01 02 (十六进制字节) |
| | | byte[] sendData = DellS2.serch(); |
| | | // 创建广播地址:255.255.255.255,端口1500 |
| | | InetAddress broadcastAddress = InetAddress.getByName("255.255.255.255"); |
| | | int port = 1500; |
| | | DellS2.getRow().removeAllElements(); |
| | | prepareSearch(); |
| | | // 创建数据包 |
| | | DatagramPacket packet = new DatagramPacket(sendData, sendData.length, broadcastAddress, port); |
| | | // 发送数据包 |
| | | socket.send(packet); |
| | | // 监听设备响应 |
| | | listenForDeviceResponses(socket); |
| | | } catch (SocketException e) { |
| | | e.printStackTrace(); |
| | | } catch (UnknownHostException e) { |
| | | e.printStackTrace(); |
| | | } catch (IOException e) { |
| | | // 如果是超时异常,属于正常情况 |
| | | if (e instanceof SocketTimeoutException) { |
| | | System.out.println(getString("listen.timeout")); |
| | | SwingUtilities.invokeLater(() -> { |
| | | JOptionPane.showMessageDialog(this, |
| | | getString("search.complete.timeout"), |
| | | getString("search.complete"), |
| | | JOptionPane.INFORMATION_MESSAGE); |
| | | }); |
| | | } else { |
| | | SwingUtilities.invokeLater(() -> { |
| | | JOptionPane.showMessageDialog(this, |
| | | getString("send.receive.udp.failed") + ": " + e.getMessage(), |
| | | getString("error"), |
| | | JOptionPane.ERROR_MESSAGE); |
| | | }); |
| | | e.printStackTrace(); |
| | | } |
| | | } finally { |
| | | // 关闭socket |
| | | if (socket != null && !socket.isClosed()) { |
| | | socket.close(); |
| | | } |
| | | } |
| | | }).start(); |
| | | } |
| | | |
| | | /** |
| | | * 监听设备响应 |
| | | */ |
| | | private void listenForDeviceResponses(DatagramSocket socket) { |
| | | try { |
| | | int responseCount = 0; |
| | | long startTime = System.currentTimeMillis(); |
| | | long timeout = 5000; // 5秒超时 |
| | | |
| | | // 持续监听直到超时 |
| | | while (System.currentTimeMillis() - startTime < timeout) { |
| | | try { |
| | | // 准备接收缓冲区 |
| | | byte[] receiveData = new byte[1024]; |
| | | DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); |
| | | |
| | | // 设置剩余超时时间 |
| | | long remainingTime = timeout - (System.currentTimeMillis() - startTime); |
| | | if (remainingTime <= 0) break; |
| | | |
| | | socket.setSoTimeout((int) remainingTime); |
| | | |
| | | // 接收数据 |
| | | socket.receive(receivePacket); |
| | | responseCount++; |
| | | |
| | | // 处理接收到的数据 |
| | | processDeviceResponse(receivePacket, responseCount); |
| | | |
| | | } catch (SocketTimeoutException e) { |
| | | // 超时继续循环,检查总超时 |
| | | continue; |
| | | } |
| | | } |
| | | System.out.println(getString("search.complete.responses") + " " + responseCount + " " + getString("devices.found")); |
| | | |
| | | } catch (IOException e) { |
| | | System.err.println(getString("listen.device.error") + ": " + e.getMessage()); |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 处理设备响应数据 |
| | | */ |
| | | private void processDeviceResponse(DatagramPacket packet, int responseNumber) { |
| | | // 获取响应数据 |
| | | byte[] responseData = packet.getData(); |
| | | int dataLength = packet.getLength(); |
| | | |
| | | // 将字节数据转换为十六进制字符串 |
| | | String hexData = bytesToHex(responseData, dataLength); |
| | | DellS2.serch_fanhui(hexData); |
| | | |
| | | // 在UI线程中更新设备表格 |
| | | SwingUtilities.invokeLater(() -> { |
| | | Vector<S2data> row = DellS2.getRow(); |
| | | for (S2data s2data : row) { |
| | | addDeviceToTable(s2data); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * 将字节数组转换为十六进制字符串 |
| | | */ |
| | | private String bytesToHex(byte[] bytes, int length) { |
| | | StringBuilder hexString = new StringBuilder(); |
| | | for (int i = 0; i < length; i++) { |
| | | String hex = Integer.toHexString(bytes[i] & 0xFF); |
| | | if (hex.length() == 1) { |
| | | hexString.append('0'); |
| | | } |
| | | hexString.append(hex.toUpperCase()); |
| | | } |
| | | return hexString.toString(); |
| | | } |
| | | |
| | | private JPanel createDeviceTablePanel() { |
| | | JPanel panel = new JPanel(new BorderLayout()); |
| | | panel.setBorder(BorderFactory.createTitledBorder(getString("device.list"))); |
| | | |
| | | deviceListLabel = new JLabel(getString("device.list")); |
| | | panel.setBorder(BorderFactory.createTitledBorder(deviceListLabel.getText())); |
| | | |
| | | String[] columnNames = { |
| | | getString("select"), |
| | | getString("device.ip"), |
| | | getString("device.name"), |
| | | getString("mac.address"), |
| | | getString("version") |
| | | getString("select"), |
| | | getString("device.ip"), |
| | | getString("device.name"), |
| | | getString("mac.address"), |
| | | getString("version") |
| | | }; |
| | | |
| | | Object[][] data = {}; // 空数据,实际使用时动态填充 |
| | | deviceTable = new JTable(data, columnNames); |
| | | |
| | | // 显式使用 DefaultTableModel |
| | | javax.swing.table.DefaultTableModel model = new javax.swing.table.DefaultTableModel(columnNames, 0) { |
| | | @Override |
| | | public Class<?> getColumnClass(int columnIndex) { |
| | | // 第一列是Boolean类型(选择框) |
| | | if (columnIndex == 0) { |
| | | return Boolean.class; |
| | | } |
| | | return String.class; |
| | | } |
| | | |
| | | @Override |
| | | public boolean isCellEditable(int row, int column) { |
| | | // 只有第一列(选择框)可编辑 |
| | | return column == 0; |
| | | } |
| | | }; |
| | | |
| | | deviceTable = new JTable(model); |
| | | |
| | | // 设置选择模式为单选 |
| | | deviceTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); |
| | | |
| | | // 添加选择监听器,确保只能选择一个设备 |
| | | deviceTable.getSelectionModel().addListSelectionListener(e -> { |
| | | if (!e.getValueIsAdjusting()) { |
| | | int selectedRow = deviceTable.getSelectedRow(); |
| | | if (selectedRow != -1) { |
| | | // 取消其他行的选择框 |
| | | for (int i = 0; i < deviceTable.getRowCount(); i++) { |
| | | if (i != selectedRow) { |
| | | deviceTable.setValueAt(Boolean.FALSE, i, 0); |
| | | } |
| | | } |
| | | // 设置当前行的选择框为选中状态 |
| | | deviceTable.setValueAt(Boolean.TRUE, selectedRow, 0); |
| | | } |
| | | } |
| | | }); |
| | | |
| | | JScrollPane scrollPane = new JScrollPane(deviceTable); |
| | | |
| | | panel.add(scrollPane, BorderLayout.CENTER); |
| | | |
| | | |
| | | return panel; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 清空设备表格 |
| | | */ |
| | | public void clearDeviceTable() { |
| | | // 安全地获取模型 |
| | | if (deviceTable.getModel() instanceof javax.swing.table.DefaultTableModel) { |
| | | javax.swing.table.DefaultTableModel model = (javax.swing.table.DefaultTableModel) deviceTable.getModel(); |
| | | model.setRowCount(0); |
| | | System.out.println(getString("device.table.cleared")); |
| | | } else { |
| | | // 如果不是DefaultTableModel,使用其他方式清空 |
| | | System.err.println(getString("table.model.error")); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 添加设备到表格 |
| | | */ |
| | | private void addDeviceToTable(S2data deviceInfo) { |
| | | // 安全地获取模型 |
| | | if (deviceTable.getModel() instanceof javax.swing.table.DefaultTableModel) { |
| | | javax.swing.table.DefaultTableModel model = (javax.swing.table.DefaultTableModel) deviceTable.getModel(); |
| | | |
| | | // 添加新设备到表格 |
| | | Object[] rowData = { |
| | | Boolean.FALSE, // 选择框 |
| | | deviceInfo.getIp(), // 设备IP |
| | | deviceInfo.getName(), // 设备名称 |
| | | deviceInfo.getMac(), // MAC地址 |
| | | deviceInfo.getVersion() // 版本 |
| | | }; |
| | | model.addRow(rowData); |
| | | } else { |
| | | System.err.println(getString("table.model.error")); |
| | | } |
| | | } |
| | | |
| | | private JPanel createConfigPanel() { |
| | | JPanel panel = new JPanel(); |
| | | panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); |
| | | |
| | | // 创建包含基础设置和端口设置的滚动面板 |
| | | |
| | | // 创建包含基础设置和端口设置的滚动面板 |
| | | JPanel contentPanel = new JPanel(); |
| | | contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.Y_AXIS)); |
| | | |
| | | // 添加顶部间距 |
| | | |
| | | // 添加顶部间距 |
| | | contentPanel.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); |
| | | |
| | | // 基础设置 |
| | | |
| | | // 基础设置 |
| | | basicSettingsPanel = createBasicSettingsPanel(); |
| | | contentPanel.add(basicSettingsPanel); |
| | | contentPanel.add(Box.createVerticalStrut(10)); |
| | | |
| | | // 端口设置 |
| | | |
| | | // 端口设置 |
| | | portSettingsPanel = createPortSettingsPanel(); |
| | | contentPanel.add(portSettingsPanel); |
| | | |
| | | // 将内容面板放入滚动面板 |
| | | |
| | | // 将内容面板放入滚动面板 |
| | | JScrollPane scrollPane = new JScrollPane(contentPanel); |
| | | scrollPane.setBorder(BorderFactory.createEmptyBorder()); |
| | | scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); |
| | | scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); |
| | | |
| | | |
| | | JPanel wrapperPanel = new JPanel(new BorderLayout()); |
| | | wrapperPanel.add(scrollPane, BorderLayout.CENTER); |
| | | |
| | | |
| | | return wrapperPanel; |
| | | } |
| | | |
| | | |
| | | private JPanel createBasicSettingsPanel() { |
| | | JPanel panel = new JPanel(); |
| | | panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); |
| | | panel.setBorder(BorderFactory.createTitledBorder(getString("basic.settings"))); |
| | | |
| | | // 第一行 |
| | | panel.add(createParameterRow("ip.address.type", createComboBox(new String[]{getString("static.ip")}, 150, 25), true)); |
| | | |
| | | // 第二行 |
| | | panel.add(createParameterRow("module.static.ip", createTextField("", 150, 25), true)); |
| | | |
| | | // 第三行 |
| | | panel.add(createParameterRow("subnet.mask", createTextField("", 150, 25), true)); |
| | | |
| | | // 第四行 |
| | | panel.add(createParameterRow("gateway", createTextField("", 150, 25), true)); |
| | | |
| | | // 第五行 |
| | | panel.add(createParameterRow("dns.address", createTextField("", 150, 25), false)); |
| | | |
| | | // 第六行 |
| | | panel.add(createParameterRow("user.mac.address", createTextField("", 150, 25), false)); |
| | | |
| | | // 第七行 |
| | | panel.add(createParameterRow("timeout.restart", createTextField("", 150, 25), false)); |
| | | |
| | | // 第八行 |
| | | panel.add(createParameterRow("http.service.port", createTextField("", 150, 25), false)); |
| | | |
| | | // 第九行 |
| | | panel.add(createParameterRow("username", createTextField("", 150, 25), false)); |
| | | |
| | | // 第十行 |
| | | panel.add(createParameterRow("password", createTextField("", 150, 25), false)); |
| | | |
| | | // 第十一行 |
| | | panel.add(createParameterRow("device.name", createTextField("", 150, 25), false)); |
| | | |
| | | // 第十二行 - 选项复选框(第一行) |
| | | |
| | | // 第一行 - IP地址类型 |
| | | ipTypeComboBox = createComboBox(new String[]{getString("static.ip")}, 150, 25); |
| | | panel.add(createParameterRow("ip.address.type", ipTypeComboBox, true)); |
| | | |
| | | // 第二行 - 模块静态IP |
| | | staticIpField = createTextField("", 150, 25); |
| | | panel.add(createParameterRow("module.static.ip", staticIpField, true)); |
| | | |
| | | // 第三行 - 子网掩码 |
| | | subnetMaskField = createTextField("", 150, 25); |
| | | panel.add(createParameterRow("subnet.mask", subnetMaskField, true)); |
| | | |
| | | // 第四行 - 网关 |
| | | gatewayField = createTextField("", 150, 25); |
| | | panel.add(createParameterRow("gateway", gatewayField, true)); |
| | | |
| | | // 第五行 - DNS地址 |
| | | dnsServerField = createTextField("", 150, 25); |
| | | panel.add(createParameterRow("dns.address", dnsServerField, false)); |
| | | |
| | | // 第六行 - 用户MAC地址 |
| | | macAddressField = createTextField("", 150, 25); |
| | | panel.add(createParameterRow("user.mac.address", macAddressField, false)); |
| | | |
| | | // 第七行 - 超时重启时间 |
| | | timeoutRestartField = createTextField("", 150, 25); |
| | | panel.add(createParameterRow("timeout.restart", timeoutRestartField, false)); |
| | | |
| | | // 第八行 - HTTP服务端口 |
| | | httpServerPortField = createTextField("", 150, 25); |
| | | panel.add(createParameterRow("http.service.port", httpServerPortField, false)); |
| | | |
| | | // 第九行 - 用户名 |
| | | usernameField = createTextField("", 150, 25); |
| | | panel.add(createParameterRow("username", usernameField, false)); |
| | | |
| | | // 第十行 - 密码 |
| | | passwordField = createTextField("", 150, 25); |
| | | panel.add(createParameterRow("password", passwordField, false)); |
| | | |
| | | // 第十一行 - 设备名称 |
| | | deviceNameField = createTextField("", 150, 25); |
| | | panel.add(createParameterRow("device.name", deviceNameField, false)); |
| | | |
| | | // 第十二行 - 选项复选框(第一行) |
| | | JPanel optionPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 0)); |
| | | optionPanel.add(new JLabel(getString("options") + ":")); |
| | | |
| | | optionsLabel = new JLabel(getString("options") + ":"); |
| | | optionPanel.add(optionsLabel); |
| | | |
| | | JPanel checkPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0)); |
| | | checkPanel.add(new JCheckBox("Index")); |
| | | checkPanel.add(new JCheckBox("Reset")); |
| | | checkPanel.add(new JCheckBox("Link")); |
| | | checkPanel.add(new JCheckBox("RFC2217")); |
| | | |
| | | indexCheckBox = new JCheckBox(getString("option.index")); |
| | | resetCheckBox = new JCheckBox(getString("option.reset")); |
| | | linkCheckBox = new JCheckBox(getString("option.link")); |
| | | rfc2217CheckBox = new JCheckBox(getString("option.rfc2217")); |
| | | |
| | | checkPanel.add(indexCheckBox); |
| | | checkPanel.add(resetCheckBox); |
| | | checkPanel.add(linkCheckBox); |
| | | checkPanel.add(rfc2217CheckBox); |
| | | |
| | | optionPanel.add(checkPanel); |
| | | optionPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, 35)); |
| | | panel.add(optionPanel); |
| | | |
| | | // 第十三行 - 选项复选框(第二行) |
| | | |
| | | // 第十三行 - 选项复选框(第二行) |
| | | JPanel optionPanel2 = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 0)); |
| | | // 添加空标签保持对齐 |
| | | optionPanel2.add(new JLabel(" ")); |
| | | |
| | | |
| | | JPanel checkPanel2 = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0)); |
| | | checkPanel2.add(new JCheckBox(getString("clear.cache"))); |
| | | checkPanel2.add(new JCheckBox(getString("serial.settings"))); |
| | | |
| | | cacheClearCheckBox = new JCheckBox(getString("clear.cache")); |
| | | serialSettingsCheckBox = new JCheckBox(getString("serial.settings")); |
| | | |
| | | checkPanel2.add(cacheClearCheckBox); |
| | | checkPanel2.add(serialSettingsCheckBox); |
| | | |
| | | optionPanel2.add(checkPanel2); |
| | | optionPanel2.setMaximumSize(new Dimension(Integer.MAX_VALUE, 35)); |
| | | panel.add(optionPanel2); |
| | | |
| | | |
| | | return panel; |
| | | } |
| | | |
| | | |
| | | private JPanel createPortSettingsPanel() { |
| | | JPanel panel = new JPanel(); |
| | | panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); |
| | | panel.setBorder(BorderFactory.createTitledBorder(getString("port.settings"))); |
| | | |
| | | // 第一行 |
| | | panel.add(createParameterRow("module.work.mode", createComboBox(new String[]{"UDP Client", "TCP Client", "TCP Server"}, 150, 25), false)); |
| | | |
| | | // 第二行 |
| | | panel.add(createParameterRow("target.ip.domain", createTextField("", 150, 25), false)); |
| | | |
| | | // 第三行 |
| | | panel.add(createParameterRow("short.connection.time", createTextField("", 150, 25), false)); |
| | | |
| | | // 第四行 |
| | | panel.add(createParameterRow("serial.baud.rate", createComboBoxWithSelection(new String[]{"9600", "19200", "38400", "115200", "921600"}, "115200", 150, 25), false)); |
| | | |
| | | // 第五行 |
| | | panel.add(createParameterRow("local.port", createTextField("", 150, 25), false)); |
| | | |
| | | // 第六行 |
| | | panel.add(createParameterRow("remote.port", createTextField("", 150, 25), false)); |
| | | |
| | | // 第七行 |
| | | panel.add(createParameterRow("tcp.server.connections", createComboBox(new String[]{"4", "3", "2", "1"}, 150, 25), false)); |
| | | |
| | | // 第八行 - 开启短连接复选框 |
| | | |
| | | // 第一行 - 模块工作模式 |
| | | workModeComboBox = createComboBox(new String[]{ |
| | | getString("work.mode.udp.client"), |
| | | getString("work.mode.tcp.client"), |
| | | getString("work.mode.tcp.server") |
| | | }, 150, 25); |
| | | panel.add(createParameterRow("module.work.mode", workModeComboBox, false)); |
| | | |
| | | // 第二行 - 目标IP/域名 |
| | | targetUrlField = createTextField("", 150, 25); |
| | | panel.add(createParameterRow("target.ip.domain", targetUrlField, false)); |
| | | |
| | | // 第三行 - 短连接时间 |
| | | shortConnectionTimeField = createTextField("", 150, 25); |
| | | panel.add(createParameterRow("short.connection.time", shortConnectionTimeField, false)); |
| | | |
| | | // 第四行 - 串口波特率 |
| | | baudRateComboBox = createComboBoxWithSelection(new String[]{"9600", "19200", "38400", "115200", "921600"}, "115200", 150, 25); |
| | | panel.add(createParameterRow("serial.baud.rate", baudRateComboBox, false)); |
| | | |
| | | // 第五行 - 本地端口 |
| | | localPortField = createTextField("", 150, 25); |
| | | panel.add(createParameterRow("local.port", localPortField, false)); |
| | | |
| | | // 第六行 - 远程端口 |
| | | remotePortField = createTextField("", 150, 25); |
| | | panel.add(createParameterRow("remote.port", remotePortField, false)); |
| | | |
| | | // 第七行 - TCP Server连接数 |
| | | tcpClientCountComboBox = createComboBox(new String[]{"4", "3", "2", "1"}, 150, 25); |
| | | panel.add(createParameterRow("tcp.server.connections", tcpClientCountComboBox, false)); |
| | | |
| | | // 第八行 - 开启短连接复选框 |
| | | JPanel shortConnPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 0)); |
| | | shortConnPanel.add(new JLabel(" ")); // 空标签保持对齐 |
| | | |
| | | shortConnPanel.add(new JLabel(" ")); |
| | | |
| | | JPanel shortConnSubPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0)); |
| | | shortConnSubPanel.add(new JCheckBox(getString("enable.short.connection"))); |
| | | |
| | | enableShortConnectionCheckBox = new JCheckBox(getString("enable.short.connection")); |
| | | shortConnSubPanel.add(enableShortConnectionCheckBox); |
| | | |
| | | shortConnPanel.add(shortConnSubPanel); |
| | | shortConnPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, 35)); |
| | | panel.add(shortConnPanel); |
| | | |
| | | // 第九行 - 校验/数据/停止 |
| | | |
| | | // 第九行 - 校验/数据/停止 |
| | | JPanel parityPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 0)); |
| | | parityPanel.add(new JLabel(getString("parity.data.stop") + ":")); |
| | | |
| | | parityDataStopLabel = new JLabel(getString("parity.data.stop") + ":"); |
| | | parityPanel.add(parityDataStopLabel); |
| | | |
| | | JPanel paritySubPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0)); |
| | | paritySubPanel.add(createComboBox(new String[]{"NONE"}, 80, 25)); |
| | | paritySubPanel.add(createComboBox(new String[]{"8"}, 60, 25)); |
| | | paritySubPanel.add(createComboBox(new String[]{"1"}, 60, 25)); |
| | | |
| | | parityComboBox = createComboBox(new String[]{getString("parity.none")}, 80, 25); |
| | | dataBitsComboBox = createComboBox(new String[]{"8"}, 60, 25); |
| | | stopBitsComboBox = createComboBox(new String[]{"1"}, 60, 25); |
| | | |
| | | paritySubPanel.add(parityComboBox); |
| | | paritySubPanel.add(dataBitsComboBox); |
| | | paritySubPanel.add(stopBitsComboBox); |
| | | |
| | | parityPanel.add(paritySubPanel); |
| | | parityPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, 35)); |
| | | panel.add(parityPanel); |
| | | |
| | | // 第十行 - 保存参数按钮 |
| | | JPanel savePanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); |
| | | savePanel.add(ButtonUtils.createBlueButton(getString("save.parameters"))); |
| | | savePanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, 35)); |
| | | panel.add(savePanel); |
| | | |
| | | |
| | | return panel; |
| | | } |
| | | |
| | | // 创建参数行的辅助方法,参考BaseStationPanel的布局 |
| | | |
| | | // 创建参数行的辅助方法,参考BaseStationPanel的布局 |
| | | private JPanel createParameterRow(String paramKey, JComponent component, boolean withStar) { |
| | | JPanel paramPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 0)); |
| | | |
| | | |
| | | String labelText = getString(paramKey); |
| | | if (withStar) { |
| | | labelText += " ★"; |
| | | labelText += " ★"; |
| | | } |
| | | |
| | | |
| | | JLabel label = new JLabel(labelText); |
| | | label.setPreferredSize(new Dimension(140, 25)); |
| | | |
| | | // 保存标签引用,用于语言切换 |
| | | parameterLabels.put(paramKey, label); |
| | | |
| | | paramPanel.add(label); |
| | | paramPanel.add(component); |
| | | |
| | | // 设置固定高度 |
| | | |
| | | // 设置固定高度 |
| | | paramPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, 35)); |
| | | return paramPanel; |
| | | } |
| | | |
| | | // 创建文本框的辅助方法 |
| | | |
| | | // 创建文本框的辅助方法 |
| | | private JTextField createTextField(String text, int width, int height) { |
| | | JTextField textField = new JTextField(text); |
| | | textField.setPreferredSize(new Dimension(width, height)); |
| | | return textField; |
| | | } |
| | | |
| | | // 创建下拉框的辅助方法 |
| | | |
| | | // 创建下拉框的辅助方法 |
| | | private JComboBox<String> createComboBox(String[] items, int width, int height) { |
| | | JComboBox<String> comboBox = new JComboBox<>(items); |
| | | comboBox.setPreferredSize(new Dimension(width, height)); |
| | | return comboBox; |
| | | } |
| | | |
| | | // 创建带默认选择的下拉框 |
| | | |
| | | // 创建带默认选择的下拉框 |
| | | private JComboBox<String> createComboBoxWithSelection(String[] items, String selected, int width, int height) { |
| | | JComboBox<String> comboBox = createComboBox(items, width, height); |
| | | comboBox.setSelectedItem(selected); |
| | | return comboBox; |
| | | } |
| | | |
| | | |
| | | public void updateLanguage() { |
| | | // 更新控制面板文本 |
| | | protocolLabel.setText(getString("protocol.type")); |
| | | addressLabel.setText(getString("local.host.address")); |
| | | portLabel.setText(getString("local.host.port")); |
| | | openBtn.setText(getString("open")); |
| | | // 更新控制面板按钮文本 |
| | | searchBtn.setText(getString("search.devices")); |
| | | readBtn.setText(getString("read.parameters")); |
| | | saveBtn.setText(getString("save.parameters")); |
| | | |
| | | // 更新设备表格标题 |
| | | if (deviceListLabel != null) { |
| | | deviceListLabel.setText(getString("device.list")); |
| | | // 更新表格边框标题 |
| | | if (deviceTable != null && deviceTable.getParent() != null && |
| | | deviceTable.getParent().getParent() instanceof JPanel) { |
| | | JPanel tablePanel = (JPanel) deviceTable.getParent().getParent(); |
| | | tablePanel.setBorder(BorderFactory.createTitledBorder(getString("device.list"))); |
| | | } |
| | | } |
| | | |
| | | // 更新设置面板边框标题 |
| | | if (basicSettingsPanel != null) { |
| | | basicSettingsPanel.setBorder(BorderFactory.createTitledBorder(getString("basic.settings"))); |
| | | } |
| | | if (portSettingsPanel != null) { |
| | | portSettingsPanel.setBorder(BorderFactory.createTitledBorder(getString("port.settings"))); |
| | | } |
| | | |
| | | // 更新所有参数行的标签文本 |
| | | updateParameterRowLabels(); |
| | | |
| | | // 更新设备表格标题 |
| | | if (deviceTable != null) { |
| | | // 更新表格标题 |
| | | // 更新其他独立标签 |
| | | if (optionsLabel != null) { |
| | | optionsLabel.setText(getString("options") + ":"); |
| | | } |
| | | if (parityDataStopLabel != null) { |
| | | parityDataStopLabel.setText(getString("parity.data.stop") + ":"); |
| | | } |
| | | |
| | | // 更新复选框文本 |
| | | if (indexCheckBox != null) { |
| | | indexCheckBox.setText(getString("option.index")); |
| | | } |
| | | if (resetCheckBox != null) { |
| | | resetCheckBox.setText(getString("option.reset")); |
| | | } |
| | | if (linkCheckBox != null) { |
| | | linkCheckBox.setText(getString("option.link")); |
| | | } |
| | | if (rfc2217CheckBox != null) { |
| | | rfc2217CheckBox.setText(getString("option.rfc2217")); |
| | | } |
| | | if (cacheClearCheckBox != null) { |
| | | cacheClearCheckBox.setText(getString("clear.cache")); |
| | | } |
| | | if (serialSettingsCheckBox != null) { |
| | | serialSettingsCheckBox.setText(getString("serial.settings")); |
| | | } |
| | | if (enableShortConnectionCheckBox != null) { |
| | | enableShortConnectionCheckBox.setText(getString("enable.short.connection")); |
| | | } |
| | | |
| | | // 更新工作模式下拉框选项 |
| | | if (workModeComboBox != null) { |
| | | String currentSelection = (String) workModeComboBox.getSelectedItem(); |
| | | workModeComboBox.removeAllItems(); |
| | | workModeComboBox.addItem(getString("work.mode.udp.client")); |
| | | workModeComboBox.addItem(getString("work.mode.tcp.client")); |
| | | workModeComboBox.addItem(getString("work.mode.tcp.server")); |
| | | // 尝试恢复之前的选择 |
| | | if (currentSelection != null) { |
| | | try { |
| | | // 尝试根据旧值找到对应的新值 |
| | | if (currentSelection.contains("UDP")) { |
| | | workModeComboBox.setSelectedItem(getString("work.mode.udp.client")); |
| | | } else if (currentSelection.contains("TCP Client")) { |
| | | workModeComboBox.setSelectedItem(getString("work.mode.tcp.client")); |
| | | } else if (currentSelection.contains("TCP Server")) { |
| | | workModeComboBox.setSelectedItem(getString("work.mode.tcp.server")); |
| | | } |
| | | } catch (Exception e) { |
| | | // 如果恢复失败,选择第一项 |
| | | if (workModeComboBox.getItemCount() > 0) { |
| | | workModeComboBox.setSelectedIndex(0); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 更新校验位下拉框选项 |
| | | if (parityComboBox != null) { |
| | | String currentSelection = (String) parityComboBox.getSelectedItem(); |
| | | parityComboBox.removeAllItems(); |
| | | parityComboBox.addItem(getString("parity.none")); |
| | | // 恢复之前的选择 |
| | | if (currentSelection != null && currentSelection.equals("NONE")) { |
| | | parityComboBox.setSelectedItem(getString("parity.none")); |
| | | } else if (parityComboBox.getItemCount() > 0) { |
| | | parityComboBox.setSelectedIndex(0); |
| | | } |
| | | } |
| | | |
| | | // 更新表格列名 |
| | | updateTableColumnNames(); |
| | | |
| | | revalidate(); |
| | | repaint(); |
| | | } |
| | | |
| | | /** |
| | | * 更新所有参数行的标签文本 |
| | | */ |
| | | private void updateParameterRowLabels() { |
| | | // 需要带星号的参数键列表(根据 createParameterRow 调用时的 withStar 参数) |
| | | Set<String> keysWithStar = new HashSet<>(); |
| | | keysWithStar.add("ip.address.type"); |
| | | keysWithStar.add("module.static.ip"); |
| | | keysWithStar.add("subnet.mask"); |
| | | keysWithStar.add("gateway"); |
| | | |
| | | // 更新所有保存的标签 |
| | | for (Map.Entry<String, JLabel> entry : parameterLabels.entrySet()) { |
| | | String paramKey = entry.getKey(); |
| | | JLabel label = entry.getValue(); |
| | | if (label != null) { |
| | | String labelText = getString(paramKey); |
| | | // 如果这个参数需要星号,添加星号 |
| | | if (keysWithStar.contains(paramKey)) { |
| | | labelText += " ★"; |
| | | } |
| | | label.setText(labelText); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 更新表格列名 |
| | | */ |
| | | private void updateTableColumnNames() { |
| | | if (deviceTable != null && deviceTable.getModel() instanceof javax.swing.table.DefaultTableModel) { |
| | | javax.swing.table.DefaultTableModel model = (javax.swing.table.DefaultTableModel) deviceTable.getModel(); |
| | | |
| | | String[] columnNames = { |
| | | getString("select"), |
| | | getString("device.ip"), |
| | |
| | | getString("mac.address"), |
| | | getString("version") |
| | | }; |
| | | // 这里需要更新表格列名,为了简单起见,我们只更新边框标题 |
| | | JViewport viewport = (JViewport) deviceTable.getParent(); |
| | | if (viewport != null) { |
| | | JScrollPane scrollPane = (JScrollPane) viewport.getParent(); |
| | | if (scrollPane != null) { |
| | | scrollPane.setBorder(BorderFactory.createTitledBorder(getString("device.list"))); |
| | | |
| | | // 保存当前数据 |
| | | int rowCount = model.getRowCount(); |
| | | Object[][] data = new Object[rowCount][columnNames.length]; |
| | | for (int i = 0; i < rowCount; i++) { |
| | | for (int j = 0; j < columnNames.length; j++) { |
| | | if (j < model.getColumnCount()) { |
| | | data[i][j] = model.getValueAt(i, j); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 更新列名和数据 |
| | | model.setColumnIdentifiers(columnNames); |
| | | } |
| | | |
| | | // 更新设置面板边框标题 |
| | | if (basicSettingsPanel != null) { |
| | | basicSettingsPanel.setBorder(BorderFactory.createTitledBorder(getString("basic.settings"))); |
| | | } |
| | | if (portSettingsPanel != null) { |
| | | portSettingsPanel.setBorder(BorderFactory.createTitledBorder(getString("port.settings"))); |
| | | } |
| | | |
| | | revalidate(); |
| | | repaint(); |
| | | } |
| | | |
| | | |
| | | private String getString(String key) { |
| | | return mainFrame.getString(key); |
| | | } |
| | | |
| | | /** |
| | | * 在搜索开始时调用,清空旧数据并准备新搜索 |
| | | */ |
| | | private void prepareSearch() { |
| | | clearDeviceTable(); |
| | | } |
| | | } |