import sys import csv from PyQt5.QtWidgets import QApplication, QDialog, QVBoxLayout, QHBoxLayout, QTableWidget, QTableWidgetItem, \ QPushButton, QCheckBox, QFileDialog, QMessageBox from PyQt5.QtCore import Qt class BatchOperationDialog(QDialog): def __init__(self): super().__init__() self.setWindowTitle("批量操作节点") self.setGeometry(100, 100, 800, 400) # 初始化分页 self.current_page = 0 self.rows_per_page = 20 # 初始化数据 self.data = [] # 初始化UI self.init_ui() def init_ui(self): # 主布局 main_layout = QVBoxLayout() # 创建表格(8列,初始行数可以设置为20) self.table_widget = QTableWidget(self.rows_per_page, 8) # 默认显示20行 self.table_widget.setHorizontalHeaderLabels( ["选择", "IP地址", "MAC地址", "版本号", "通道1名称", "通道1绑定设备", "通道2名称", "通道2绑定设备"] ) # 使通道列可编辑 for row in range(self.table_widget.rowCount()): self.table_widget.setItem(row, 4, QTableWidgetItem()) # 通道1名称 self.table_widget.setItem(row, 5, QTableWidgetItem()) # 通道1绑定设备 self.table_widget.setItem(row, 6, QTableWidgetItem()) # 通道2名称 self.table_widget.setItem(row, 7, QTableWidgetItem()) # 通道2绑定设备 # 添加勾选框到第1列 for row in range(self.table_widget.rowCount()): check_box_item = QTableWidgetItem() check_box_item.setCheckState(0) # 初始状态为未选中 self.table_widget.setItem(row, 0, check_box_item) # 按钮布局 button_layout = QHBoxLayout() # 创建按钮 self.select_all_button = QPushButton("全选") self.select_none_button = QPushButton("全不选") self.get_version_button = QPushButton("获取版本") self.get_mac_button = QPushButton("获取MAC") self.upgrade_button = QPushButton("升级节点") self.load_ips_button = QPushButton("加载IP列表") self.load_all_button = QPushButton("加载完整信息列表") self.save_button = QPushButton("保存表数据") self.prev_page_button = QPushButton("上一页") self.next_page_button = QPushButton("下一页") # 按钮连接 self.select_all_button.clicked.connect(self.select_all) self.select_none_button.clicked.connect(self.select_none) self.get_version_button.clicked.connect(self.get_version) self.get_mac_button.clicked.connect(self.get_mac) self.upgrade_button.clicked.connect(self.upgrade_node) self.save_button.clicked.connect(self.save_data) self.load_ips_button.clicked.connect(self.load_ips) self.load_all_button.clicked.connect(self.load_all_info) self.prev_page_button.clicked.connect(self.prev_page) self.next_page_button.clicked.connect(self.next_page) # 将按钮加入布局 button_layout.addWidget(self.select_all_button) button_layout.addWidget(self.select_none_button) button_layout.addWidget(self.get_version_button) button_layout.addWidget(self.get_mac_button) button_layout.addWidget(self.upgrade_button) button_layout.addWidget(self.load_ips_button) button_layout.addWidget(self.load_all_button) button_layout.addWidget(self.save_button) button_layout.addWidget(self.prev_page_button) button_layout.addWidget(self.next_page_button) # 将表格和按钮布局添加到主布局 main_layout.addWidget(self.table_widget) main_layout.addLayout(button_layout) # 设置对话框的布局 self.setLayout(main_layout) # 允许最大化 # self.setWindowState(Qt.WindowMaximized) def select_all(self): for row in range(self.table_widget.rowCount()): item = self.table_widget.item(row, 0) item.setCheckState(2) # 选中 def select_none(self): for row in range(self.table_widget.rowCount()): item = self.table_widget.item(row, 0) item.setCheckState(0) # 未选中 def get_version(self): print("获取版本按钮被点击") def get_mac(self): print("获取MAC按钮被点击") def upgrade_node(self): print("升级节点按钮被点击") def save_data(self): # 打开文件保存对话框 options = QFileDialog.Options() file_path, _ = QFileDialog.getSaveFileName(self, "保存表数据", "", "CSV Files (*.csv);;All Files (*)", options=options) if file_path: # 保存表格数据到CSV文件 with open(file_path, mode='w', newline='', encoding='utf-8') as file: writer = csv.writer(file) # 写入表头 headers = [self.table_widget.horizontalHeaderItem(i).text() for i in range(self.table_widget.columnCount())] writer.writerow(headers[1:]) # 写入表格内容 for row in range(self.table_widget.rowCount()): row_data = [self.table_widget.item(row, col).text() if self.table_widget.item(row, col) else "" for col in range(1, self.table_widget.columnCount())] # Start from col=1 to skip the first column writer.writerow(row_data) print(f"数据已保存到 {file_path}") def load_ips(self): # 打开文件选择对话框 options = QFileDialog.Options() file_path, _ = QFileDialog.getOpenFileName(self, "选择IP地址文件", "", "Text Files (*.txt);;All Files (*)", options=options) if file_path: # 读取IP地址 with open(file_path, 'r') as file: lines = file.readlines() invalid_ips = [] for i, line in enumerate(lines): ip = line.strip() # 验证IP地址格式 if not self.validate_ip(ip): invalid_ips.append(i + 1) if invalid_ips: # 如果有无效IP,弹出提示框 QMessageBox.warning(self, "错误", f"以下行的IP地址无效:{', '.join(map(str, invalid_ips))}") else: # 将IP地址加载到表格 self.table_widget.setRowCount(len(lines)) for i, line in enumerate(lines): ip = line.strip() if i < self.table_widget.rowCount(): self.table_widget.setItem(i, 1, QTableWidgetItem(ip)) # 设置IP地址列 print(f"加载了{len(lines)}个IP地址") def validate_ip(self, ip): # IP地址验证正则表达式 import re pattern = r"^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$" return bool(re.match(pattern, ip)) def load_all_info(self): # 打开CSV文件选择对话框 options = QFileDialog.Options() file_path, _ = QFileDialog.getOpenFileName(self, "选择CSV文件", "", "CSV Files (*.csv);;All Files (*)", options=options) if file_path: # 读取CSV文件 with open(file_path, mode='r', encoding='utf-8') as file: reader = csv.reader(file) headers = next(reader) # 跳过表头 self.data = [row for row in reader] if len(self.data) <= 20: self.table_widget.setRowCount(len(self.data)) # 确保加载数据后更新分页 self.current_page = 0 # 每次加载新数据,默认回到第一页 self.update_table() def update_table(self): # 获取当前页的数据 start_row = self.current_page * self.rows_per_page end_row = start_row + self.rows_per_page rows_to_display = self.data[start_row:end_row] # 更新表格内容 for row_num, row_data in enumerate(rows_to_display): for col_num, cell_data in enumerate(row_data): self.table_widget.setItem(row_num, col_num + 1, QTableWidgetItem(cell_data)) # +1跳过“选择”列 # 根据数据量调整上一页和下一页按钮的状态 self.prev_page_button.setEnabled(self.current_page > 0) self.next_page_button.setEnabled((self.current_page + 1) * self.rows_per_page < len(self.data)) def prev_page(self): if self.current_page > 0: self.current_page -= 1 self.update_table() def next_page(self): if (self.current_page + 1) * self.rows_per_page < len(self.data): self.current_page += 1 self.update_table() if __name__ == "__main__": app = QApplication(sys.argv) dialog = BatchOperationDialog() dialog.show() sys.exit(app.exec_())