TensorFlow问题:FLAGS._parse_flags()报错AttributeError:_parse_flags

本文解决了一个TensorFlow中关于属性错误的问题。由于TensorFlow版本更新,原用法FLAGS._parse_flags()被废弃,改用FLAGS.flag_values_dict()。文章提供了解决方案。
部署运行你感兴趣的模型镜像

1,前言

俗话说,难者不会,会者不难。当时解决这个“AttributeError:_parse_flags”时,真真是耗费我一些时间,所以在我解决后,我的第一个想法就是赶紧把TensorFlow这个坑给添上,话不多说了,直接写原因和解决方案

2,原因

哎呀、、、、还是TensorFlow的版本问题了,TensorFlow版本升级后,它就无情的抛弃了FLAGS._parse_flags()这种用法,改成了用FLAGS.flag_values_dict()

3,解决办法

聪明如你,应该知道咋解决了吧,就是用FLAGS.flag_values_dict()替换FLAGS._parse_flags(),问题完美解决,不再出现报错

您可能感兴趣的与本文相关的镜像

TensorFlow-v2.9

TensorFlow-v2.9

TensorFlow

TensorFlow 是由Google Brain 团队开发的开源机器学习框架,广泛应用于深度学习研究和生产环境。 它提供了一个灵活的平台,用于构建和训练各种机器学习模型

import sys import xml.etree.ElementTree as ET from PyQt5.QtWidgets import (QApplication, QMainWindow, QTableWidget, QTableWidgetItem, QPushButton, QFileDialog, QLineEdit, QLabel, QMessageBox, QHBoxLayout, QVBoxLayout, QWidget, QHeaderView, QAbstractItemView, QComboBox, QSizePolicy, QStyledItemDelegate) from PyQt5.QtCore import Qt, QSize from PyQt5.QtGui import QBrush, QColor, QFont import os class ComboBoxDelegate(QStyledItemDelegate): def __init__(self, parent=None, options=None): super().__init__(parent) self.options = options or [] def createEditor(self, parent, option, index): editor = QComboBox(parent) editor.setEditable(True) editor.addItems(self.options) return editor def setEditorData(self, editor, index): value = index.data(Qt.DisplayRole) if value: editor.setCurrentText(value) def setModelData(self, editor, model, index): model.setData(index, editor.currentText(), Qt.EditRole) class XMLDataManager(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("RawDataConfig编辑器") self.setGeometry(100, 100, 1400, 800) self.current_file = None self.original_data = [] # 原始数据,保持不变 self.display_data = [] # 当前显示的数据 self.temp_data = [] # 临时数据(用于保存修改) self.row_counter = 1 self.type_options = set() self.data_type_id_options = set() self.is_searching = False self.search_results_indices = [] # 保存搜索结果的原始索引 self.search_text = "" # 保存当前搜索文本 # 定义字体 self.normal_font = QFont() self.bold_font = QFont() self.bold_font.setBold(True) self.column_names = [ "path", "type", "variable", "id", "data_type_id", "subsystem_id", "parts", "parts_id", "attribute", "attribute_id", "mapping" ] self.required_columns = [col for col in self.column_names if col != "mapping"] self.init_ui() def init_ui(self): central_widget = QWidget() self.setCentralWidget(central_widget) self.load_btn = QPushButton("加载文件") self.add_btn = QPushButton("添加记录") self.delete_btn = QPushButton("删除记录") self.save_btn = QPushButton("保存修改") self.export_btn = QPushButton("导出文件") self.search_btn = QPushButton("搜索") self.clear_btn = QPushButton("清空搜索") button_style = """ QPushButton { background-color: rgb(65, 105, 225); color: white; border: none; padding: 8px 16px; text-align: center; font-size: 14px; margin: 4px 2px; border-radius: 4px; } QPushButton:hover { background-color: rgb(55, 95, 215); } QPushButton:pressed { background-color: rgb(45, 85, 205); } """ for btn in [self.load_btn, self.export_btn, self.add_btn, self.delete_btn, self.save_btn, self.search_btn, self.clear_btn]: btn.setStyleSheet(button_style) self.search_box = QLineEdit() self.search_box.setPlaceholderText("输入搜索内容...") self.search_box.setMinimumWidth(300) self.search_box.setStyleSheet(""" QLineEdit { padding: 8px; border: 1px solid #ccc; border-radius: 4px; font-size: 14px; } """) self.column_combo = QComboBox() self.column_combo.setMinimumWidth(120) self.column_combo.addItem("所有列") self.column_combo.addItems(self.column_names) self.column_combo.setCurrentIndex(0) self.column_combo.setStyleSheet(""" QComboBox { padding: 6px; border: 1px solid #ccc; border-radius: 4px; font-size: 14px; } """) self.table = QTableWidget() self.table.setColumnCount(len(self.column_names) + 1) headers = ["序号"] + self.column_names self.table.setHorizontalHeaderLabels(headers) self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Interactive) self.table.horizontalHeader().setStretchLastSection(True) self.table.setSelectionBehavior(QTableWidget.SelectRows) self.table.setSelectionMode(QAbstractItemView.ExtendedSelection) self.table.itemChanged.connect(self.update_cell_style) self.table.setStyleSheet(""" QTableWidget { gridline-color: #ddd; font-size: 12px; } QHeaderView::section { background-color: #f2f2f2; padding: 4px; border: 1px solid #ddd; font-weight: bold; } QTableCornerButton::section { background-color: #f2f2f2; border: 1px solid #ddd; } """) self.table.setColumnWidth(0, 60) self.table.verticalHeader().setVisible(False) self.table.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) top_layout = QHBoxLayout() top_layout.addWidget(self.load_btn) top_layout.addWidget(self.add_btn) top_layout.addWidget(self.delete_btn) top_layout.addWidget(self.save_btn) top_layout.addWidget(self.export_btn) top_layout.addStretch() search_col_label = QLabel("搜索列:") search_col_label.setStyleSheet("font-size: 14px;") top_layout.addWidget(search_col_label) top_layout.addWidget(self.column_combo) search_col_label1 = QLabel("搜索内容:") search_col_label1.setStyleSheet("font-size: 14px;") top_layout.addWidget(search_col_label1) top_layout.addWidget(self.search_box) top_layout.addWidget(self.search_btn) top_layout.addWidget(self.clear_btn) main_layout = QVBoxLayout() main_layout.addLayout(top_layout) main_layout.addWidget(self.table) central_widget.setLayout(main_layout) self.load_btn.clicked.connect(self.load_xml) self.export_btn.clicked.connect(self.export_xml) self.add_btn.clicked.connect(self.add_record) self.delete_btn.clicked.connect(self.delete_record) self.save_btn.clicked.connect(self.save_changes) self.search_btn.clicked.connect(self.search_records) self.clear_btn.clicked.connect(self.clear_search) self.statusBar = self.statusBar() self.statusBar.setStyleSheet("background-color: #f0f0f0; padding: 4px;") def update_cell_style(self, item): col_idx = item.column() - 1 if col_idx < 0 or col_idx >= len(self.column_names): return col_name = self.column_names[col_idx] cell_text = item.text().lower() # 重置字体 item.setFont(self.normal_font) # 检查必填项 if col_name in self.required_columns: if not item.text().strip(): item.setBackground(QColor(255, 200, 200)) else: item.setBackground(QColor(255, 255, 255)) # 高亮显示搜索匹配的内容 if self.is_searching and self.search_text: if self.search_text in cell_text: item.setFont(self.bold_font) # 匹配项加粗 if col_name in self.required_columns and not item.text().strip(): item.setBackground(QColor(255, 200, 200)) else: item.setBackground(QColor(255, 255, 0)) # 黄色高亮 elif col_name in self.required_columns and not item.text().strip(): item.setBackground(QColor(255, 200, 200)) else: item.setBackground(QColor(255, 255, 255)) def load_xml(self): file_path, _ = QFileDialog.getOpenFileName( self, "选择XML文件", "", "XML文件 (*.xml)" ) if not file_path: return try: tree = ET.parse(file_path) root = tree.getroot() self.current_file = file_path file_name = os.path.basename(file_path) self.setWindowTitle(f"RawDataConfig编辑器 - {file_name}") self.table.setRowCount(0) self.original_data = [] self.display_data = [] self.temp_data = [] self.row_counter = 1 self.type_options = set() self.data_type_id_options = set() self.is_searching = False self.search_results_indices = [] self.search_text = "" for record in root.findall('Record'): row_data = {} for col_name in self.column_names: value = record.get(col_name, '') row_data[col_name] = value if col_name == 'type' and value: self.type_options.add(value) elif col_name == 'data_type_id' and value: self.data_type_id_options.add(value) self.original_data.append(row_data) self.temp_data = [row.copy() for row in self.original_data] self.display_data = self.temp_data.copy() self.populate_table() self.adjust_column_widths() self.statusBar.showMessage(f"成功加载文件: {file_path}", 3000) except Exception as e: QMessageBox.critical(self, "错误", f"加载XML文件失败:\n{str(e)}") def populate_table(self, data=None, indices=None): if data is None: data = self.display_data try: self.table.itemChanged.disconnect(self.update_cell_style) except: pass self.table.setRowCount(len(data)) type_col_index = self.column_names.index('type') + 1 data_type_id_col_index = self.column_names.index('data_type_id') + 1 type_delegate = ComboBoxDelegate(self.table, sorted(self.type_options)) data_type_id_delegate = ComboBoxDelegate(self.table, sorted(self.data_type_id_options)) self.table.setItemDelegateForColumn(type_col_index, type_delegate) self.table.setItemDelegateForColumn(data_type_id_col_index, data_type_id_delegate) for row_idx, record in enumerate(data): # 保留原始序号 if indices and row_idx < len(indices): original_idx = indices[row_idx] seq_item = QTableWidgetItem(str(original_idx + 1)) else: seq_item = QTableWidgetItem(str(self.row_counter + row_idx)) seq_item.setTextAlignment(Qt.AlignCenter) seq_item.setFlags(seq_item.flags() & ~Qt.ItemIsEditable) seq_item.setFont(self.normal_font) self.table.setItem(row_idx, 0, seq_item) for col_idx, col_name in enumerate(self.column_names): value = record.get(col_name, '') item = QTableWidgetItem(value) if self.is_searching and self.search_text and self.search_text in value.lower(): item.setFont(self.bold_font) else: item.setFont(self.normal_font) # item.setFont(self.normal_font) if col_name in ['type', 'data_type_id']: item.setFlags(item.flags() | Qt.ItemIsEditable) if col_name in self.required_columns and not value.strip(): item.setBackground(QColor(255, 200, 200)) self.table.setItem(row_idx, col_idx + 1, item) self.table.itemChanged.connect(self.update_cell_style) def adjust_column_widths(self): self.table.setColumnWidth(0, 60) for col in range(1, self.table.columnCount()): self.table.resizeColumnToContents(col) if self.table.columnWidth(col) < 100: self.table.setColumnWidth(col, 100) def export_xml(self): if not self.temp_data: QMessageBox.warning(self, "警告", "没有数据可导出") return file_path, _ = QFileDialog.getSaveFileName( self, "导出XML文件", "", "XML文件 (*.xml)" ) if not file_path: return try: with open(file_path, 'wb') as f: f.write(b'<?xml version="1.0" ?>\n') f.write(b'<DataRecords>\n') for record in self.temp_data: attrs = ' '.join([f'{k}="{v}"' for k, v in record.items()]) f.write(f' <Record {attrs}/>\n'.encode('utf-8')) f.write(b'</DataRecords>') self.statusBar.showMessage(f"成功导出到: {file_path}", 3000) except Exception as e: QMessageBox.critical(self, "错误", f"导出XML文件失败:\n{str(e)}") def add_record(self): selected_rows = set(index.row() for index in self.table.selectedIndexes()) insert_row = self.table.rowCount() if selected_rows: insert_row = min(selected_rows) + 1 self.table.insertRow(insert_row) new_record = {col_name: "" for col_name in self.column_names} # 根据当前状态添加到不同的数据列表 if self.is_searching: # 在搜索状态下添加记录到临时数据和显示数据 self.display_data.insert(insert_row, new_record) # 找到合适的原始索引位置插入 insert_original_pos = self.search_results_indices[insert_row] if insert_row < len( self.search_results_indices) else len(self.temp_data) self.temp_data.insert(insert_original_pos, new_record) # 更新后续的搜索结果索引 self.search_results_indices = [x if x < insert_original_pos else x + 1 for x in self.search_results_indices] else: self.display_data.insert(insert_row, new_record) self.temp_data.insert(insert_row, new_record) seq_item = QTableWidgetItem(str(self.row_counter + insert_row)) seq_item.setTextAlignment(Qt.AlignCenter) seq_item.setFlags(seq_item.flags() & ~Qt.ItemIsEditable) seq_item.setFont(self.normal_font) self.table.setItem(insert_row, 0, seq_item) for col_idx, col_name in enumerate(self.column_names): item = QTableWidgetItem("") item.setFont(self.normal_font) if col_name in ['type', 'data_type_id']: item.setFlags(item.flags() | Qt.ItemIsEditable) if col_name in self.required_columns: item.setBackground(QColor(255, 200, 200)) self.table.setItem(insert_row, col_idx + 1, item) self.update_sequence_numbers() self.table.scrollToItem(self.table.item(insert_row, 0)) self.table.selectRow(insert_row) self.statusBar.showMessage("已添加新记录", 2000) def delete_record(self): selected_rows = set(index.row() for index in self.table.selectedIndexes()) if not selected_rows: QMessageBox.warning(self, "警告", "请先选择要删除的记录") return reply = QMessageBox.question(self, "确认删除", f"确定要删除选中的 {len(selected_rows)} 条记录吗?", QMessageBox.Yes | QMessageBox.No) if reply != QMessageBox.Yes: return # 按降序删除以避免索引问题 for row in sorted(selected_rows, reverse=True): self.table.removeRow(row) if row < len(self.display_data): del self.display_data[row] if self.is_searching and row < len(self.search_results_indices): # 如果是搜索状态,需要从原始数据中删除 original_idx = self.search_results_indices[row] if original_idx < len(self.temp_data): del self.temp_data[original_idx] # 更新搜索结果索引 self.search_results_indices = [x if x < original_idx else x - 1 for x in self.search_results_indices] self.search_results_indices.pop(row) elif not self.is_searching and row < len(self.temp_data): del self.temp_data[row] self.update_sequence_numbers() self.statusBar.showMessage(f"已删除 {len(selected_rows)} 条记录", 3000) def update_sequence_numbers(self): for row_idx in range(self.table.rowCount()): if self.is_searching and row_idx < len(self.search_results_indices): original_idx = self.search_results_indices[row_idx] seq_item = QTableWidgetItem(str(original_idx + 1)) else: seq_item = QTableWidgetItem(str(self.row_counter + row_idx)) seq_item.setTextAlignment(Qt.AlignCenter) seq_item.setFlags(seq_item.flags() & ~Qt.ItemIsEditable) seq_item.setFont(self.normal_font) self.table.setItem(row_idx, 0, seq_item) def save_changes(self): if not self.display_data: QMessageBox.warning(self, "警告", "没有数据可保存") return empty_fields = [] for row_idx in range(self.table.rowCount()): for col_idx, col_name in enumerate(self.column_names): if col_name in self.required_columns: item = self.table.item(row_idx, col_idx + 1) if item is None or not item.text().strip(): seq_item = self.table.item(row_idx, 0) row_num = seq_item.text() if seq_item else str(row_idx + 1) empty_fields.append(f"行 {row_num} 的 '{col_name}' 列") if empty_fields: error_msg = "以下必填项为空,请填写完整后保存:\n" error_msg += "\n".join(empty_fields[:10]) if len(empty_fields) > 10: error_msg += f"\n...(共{len(empty_fields)}个错误)" QMessageBox.warning(self, "保存失败", error_msg) return try: # 更新显示数据 for row_idx in range(self.table.rowCount()): while row_idx >= len(self.display_data): self.display_data.append({col_name: "" for col_name in self.column_names}) for col_idx, col_name in enumerate(self.column_names): item = self.table.item(row_idx, col_idx + 1) if item: self.display_data[row_idx][col_name] = item.text() if col_name == 'type' and item.text(): self.type_options.add(item.text()) elif col_name == 'data_type_id' and item.text(): self.data_type_id_options.add(item.text()) else: self.display_data[row_idx][col_name] = "" # 更新临时数据 if self.is_searching: # 在搜索状态下,需要特殊处理以保持数据一致性 for display_idx, original_idx in enumerate(self.search_results_indices): if display_idx < len(self.display_data) and original_idx < len(self.temp_data): for col_name in self.column_names: self.temp_data[original_idx][col_name] = self.display_data[display_idx][col_name] else: # 非搜索状态下,直接更新临时数据 self.temp_data = [row.copy() for row in self.display_data] self.statusBar.showMessage("修改已保存到内存", 2000) except Exception as e: QMessageBox.critical(self, "错误", f"保存失败: {str(e)}") def search_records(self): search_text = self.search_box.text().strip() selected_column = self.column_combo.currentText() if not search_text: QMessageBox.warning(self, "警告", "请输入搜索内容") return self.is_searching = True self.search_text = search_text.lower() # 保存搜索文本用于高亮 self.search_results_indices = [] matched_rows = [] # 搜索基于临时数据(包含所有修改) for original_idx, record in enumerate(self.temp_data): match_found = False if selected_column == "所有列": for col_name in self.column_names: value = record.get(col_name, '').lower() if self.search_text in value: match_found = True break else: value = record.get(selected_column, '').lower() if self.search_text in value: match_found = True if match_found: self.search_results_indices.append(original_idx) matched_rows.append(record) if matched_rows: self.display_data = matched_rows # 传递原始索引用于显示正确的序号 self.populate_table(self.display_data, self.search_results_indices) self.adjust_column_widths() self.statusBar.showMessage(f"找到 {len(matched_rows)} 条匹配记录", 3000) else: QMessageBox.information(self, "搜索结果", "未找到匹配记录") self.statusBar.showMessage("未找到匹配记录", 2000) def clear_search(self): # 恢复显示所有数据,保留所有修改 self.display_data = [row.copy() for row in self.temp_data] self.is_searching = False self.search_text = "" # 清空搜索文本 self.search_box.clear() # 清空搜索框内容 self.search_results_indices = [] self.populate_table() self.adjust_column_widths() self.statusBar.showMessage("已显示所有记录", 2000) if __name__ == "__main__": app = QApplication(sys.argv) window = XMLDataManager() window.show() sys.exit(app.exec_()) 去除搜索结果黄色高亮显示,其余部分程序不变
08-21
import sys import xml.etree.ElementTree as ET from PyQt5.QtWidgets import (QApplication, QMainWindow, QTableWidget, QTableWidgetItem, QPushButton, QFileDialog, QLineEdit, QLabel, QMessageBox, QHBoxLayout, QVBoxLayout, QWidget, QHeaderView, QAbstractItemView, QComboBox, QSizePolicy, QStyledItemDelegate) from PyQt5.QtCore import Qt, QSize from PyQt5.QtGui import QBrush, QColor, QFont import os class ComboBoxDelegate(QStyledItemDelegate): def __init__(self, parent=None, options=None): super().__init__(parent) self.options = options or [] def createEditor(self, parent, option, index): editor = QComboBox(parent) editor.setEditable(True) editor.addItems(self.options) return editor def setEditorData(self, editor, index): value = index.data(Qt.DisplayRole) if value: editor.setCurrentText(value) def setModelData(self, editor, model, index): model.setData(index, editor.currentText(), Qt.EditRole) class XMLDataManager(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("RawDataConfig编辑器") self.setGeometry(100, 100, 1400, 800) self.current_file = None self.original_data = [] # 原始数据,保持不变 self.display_data = [] # 当前显示的数据 self.temp_data = [] # 临时数据(用于保存修改) self.row_counter = 1 self.type_options = set() self.data_type_id_options = set() self.is_searching = False self.search_results_indices = [] # 保存搜索结果的原始索引 self.column_names = [ "path", "type", "variable", "id", "data_type_id", "subsystem_id", "parts", "parts_id", "attribute", "attribute_id", "mapping" ] self.required_columns = [col for col in self.column_names if col != "mapping"] self.init_ui() def init_ui(self): central_widget = QWidget() self.setCentralWidget(central_widget) self.load_btn = QPushButton("加载文件") self.add_btn = QPushButton("添加记录") self.delete_btn = QPushButton("删除记录") self.save_btn = QPushButton("保存修改") self.export_btn = QPushButton("导出文件") self.search_btn = QPushButton("搜索") self.clear_btn = QPushButton("清空搜索") button_style = """ QPushButton { background-color: rgb(65, 105, 225); color: white; border: none; padding: 8px 16px; text-align: center; font-size: 14px; margin: 4px 2px; border-radius: 4px; } QPushButton:hover { background-color: rgb(55, 95, 215); } QPushButton:pressed { background-color: rgb(45, 85, 205); } """ for btn in [self.load_btn, self.export_btn, self.add_btn, self.delete_btn, self.save_btn, self.search_btn, self.clear_btn]: btn.setStyleSheet(button_style) self.search_box = QLineEdit() self.search_box.setPlaceholderText("输入搜索内容...") self.search_box.setMinimumWidth(300) self.search_box.setStyleSheet(""" QLineEdit { padding: 8px; border: 1px solid #ccc; border-radius: 4px; font-size: 14px; } """) self.column_combo = QComboBox() self.column_combo.setMinimumWidth(120) self.column_combo.addItem("所有列") self.column_combo.addItems(self.column_names) self.column_combo.setCurrentIndex(0) self.column_combo.setStyleSheet(""" QComboBox { padding: 6px; border: 1px solid #ccc; border-radius: 4px; font-size: 14px; } """) self.table = QTableWidget() self.table.setColumnCount(len(self.column_names) + 1) headers = ["序号"] + self.column_names self.table.setHorizontalHeaderLabels(headers) self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Interactive) self.table.horizontalHeader().setStretchLastSection(True) self.table.setSelectionBehavior(QTableWidget.SelectRows) self.table.setSelectionMode(QAbstractItemView.ExtendedSelection) self.table.itemChanged.connect(self.update_cell_background) self.table.setStyleSheet(""" QTableWidget { gridline-color: #ddd; font-size: 12px; } QHeaderView::section { background-color: #f2f2f2; padding: 4px; border: 1px solid #ddd; font-weight: bold; } QTableCornerButton::section { background-color: #f2f2f2; border: 1px solid #ddd; } """) self.table.setColumnWidth(0, 60) self.table.verticalHeader().setVisible(False) self.table.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) top_layout = QHBoxLayout() top_layout.addWidget(self.load_btn) top_layout.addWidget(self.add_btn) top_layout.addWidget(self.delete_btn) top_layout.addWidget(self.save_btn) top_layout.addWidget(self.export_btn) top_layout.addStretch() search_col_label = QLabel("搜索列:") search_col_label.setStyleSheet("font-size: 14px;") top_layout.addWidget(search_col_label) top_layout.addWidget(self.column_combo) search_col_label1 = QLabel("搜索内容:") search_col_label1.setStyleSheet("font-size: 14px;") top_layout.addWidget(search_col_label1) top_layout.addWidget(self.search_box) top_layout.addWidget(self.search_btn) top_layout.addWidget(self.clear_btn) main_layout = QVBoxLayout() main_layout.addLayout(top_layout) main_layout.addWidget(self.table) central_widget.setLayout(main_layout) self.load_btn.clicked.connect(self.load_xml) self.export_btn.clicked.connect(self.export_xml) self.add_btn.clicked.connect(self.add_record) self.delete_btn.clicked.connect(self.delete_record) self.save_btn.clicked.connect(self.save_changes) self.search_btn.clicked.connect(self.search_records) self.clear_btn.clicked.connect(self.clear_search) self.statusBar = self.statusBar() self.statusBar.setStyleSheet("background-color: #f0f0f0; padding: 4px;") def update_cell_background(self, item): col_idx = item.column() - 1 if col_idx < 0 or col_idx >= len(self.column_names): return col_name = self.column_names[col_idx] if col_name in self.required_columns: if not item.text().strip(): item.setBackground(QColor(255, 200, 200)) else: item.setBackground(QColor(255, 255, 255)) def load_xml(self): file_path, _ = QFileDialog.getOpenFileName( self, "选择XML文件", "", "XML文件 (*.xml)" ) if not file_path: return try: tree = ET.parse(file_path) root = tree.getroot() self.current_file = file_path file_name = os.path.basename(file_path) self.setWindowTitle(f"RawDataConfig编辑器 - {file_name}") self.table.setRowCount(0) self.original_data = [] self.display_data = [] self.temp_data = [] self.row_counter = 1 self.type_options = set() self.data_type_id_options = set() self.is_searching = False self.search_results_indices = [] for record in root.findall('Record'): row_data = {} for col_name in self.column_names: value = record.get(col_name, '') row_data[col_name] = value if col_name == 'type' and value: self.type_options.add(value) elif col_name == 'data_type_id' and value: self.data_type_id_options.add(value) self.original_data.append(row_data) self.temp_data = [row.copy() for row in self.original_data] self.display_data = self.temp_data.copy() self.populate_table() self.adjust_column_widths() self.statusBar.showMessage(f"成功加载文件: {file_path}", 3000) except Exception as e: QMessageBox.critical(self, "错误", f"加载XML文件失败:\n{str(e)}") def populate_table(self, data=None, indices=None): if data is None: data = self.display_data try: self.table.itemChanged.disconnect(self.update_cell_background) except: pass self.table.setRowCount(len(data)) type_col_index = self.column_names.index('type') + 1 data_type_id_col_index = self.column_names.index('data_type_id') + 1 type_delegate = ComboBoxDelegate(self.table, sorted(self.type_options)) data_type_id_delegate = ComboBoxDelegate(self.table, sorted(self.data_type_id_options)) self.table.setItemDelegateForColumn(type_col_index, type_delegate) self.table.setItemDelegateForColumn(data_type_id_col_index, data_type_id_delegate) for row_idx, record in enumerate(data): # 保留原始序号 if indices and row_idx < len(indices): original_idx = indices[row_idx] seq_item = QTableWidgetItem(str(original_idx + 1)) else: seq_item = QTableWidgetItem(str(self.row_counter + row_idx)) seq_item.setTextAlignment(Qt.AlignCenter) seq_item.setFlags(seq_item.flags() & ~Qt.ItemIsEditable) self.table.setItem(row_idx, 0, seq_item) for col_idx, col_name in enumerate(self.column_names): value = record.get(col_name, '') item = QTableWidgetItem(value) if col_name in ['type', 'data_type_id']: item.setFlags(item.flags() | Qt.ItemIsEditable) if col_name in self.required_columns and not value.strip(): item.setBackground(QColor(255, 200, 200)) self.table.setItem(row_idx, col_idx + 1, item) self.table.itemChanged.connect(self.update_cell_background) def adjust_column_widths(self): self.table.setColumnWidth(0, 60) for col in range(1, self.table.columnCount()): self.table.resizeColumnToContents(col) if self.table.columnWidth(col) < 100: self.table.setColumnWidth(col, 100) def export_xml(self): if not self.temp_data: QMessageBox.warning(self, "警告", "没有数据可导出") return file_path, _ = QFileDialog.getSaveFileName( self, "导出XML文件", "", "XML文件 (*.xml)" ) if not file_path: return try: with open(file_path, 'wb') as f: f.write(b'<?xml version="1.0" ?>\n') f.write(b'<DataRecords>\n') for record in self.temp_data: attrs = ' '.join([f'{k}="{v}"' for k, v in record.items()]) f.write(f' <Record {attrs}/>\n'.encode('utf-8')) f.write(b'</DataRecords>') self.statusBar.showMessage(f"成功导出到: {file_path}", 3000) except Exception as e: QMessageBox.critical(self, "错误", f"导出XML文件失败:\n{str(e)}") def add_record(self): selected_rows = set(index.row() for index in self.table.selectedIndexes()) insert_row = self.table.rowCount() if selected_rows: insert_row = min(selected_rows) + 1 self.table.insertRow(insert_row) new_record = {col_name: "" for col_name in self.column_names} # 根据当前状态添加到不同的数据列表 if self.is_searching: # 在搜索状态下添加记录到临时数据和显示数据 self.display_data.insert(insert_row, new_record) # 找到合适的原始索引位置插入 insert_original_pos = self.search_results_indices[insert_row] if insert_row < len( self.search_results_indices) else len(self.temp_data) self.temp_data.insert(insert_original_pos, new_record) # 更新后续的搜索结果索引 self.search_results_indices = [x if x < insert_original_pos else x + 1 for x in self.search_results_indices] else: self.display_data.insert(insert_row, new_record) self.temp_data.insert(insert_row, new_record) seq_item = QTableWidgetItem(str(self.row_counter + insert_row)) seq_item.setTextAlignment(Qt.AlignCenter) seq_item.setFlags(seq_item.flags() & ~Qt.ItemIsEditable) self.table.setItem(insert_row, 0, seq_item) for col_idx, col_name in enumerate(self.column_names): item = QTableWidgetItem("") if col_name in ['type', 'data_type_id']: item.setFlags(item.flags() | Qt.ItemIsEditable) if col_name in self.required_columns: item.setBackground(QColor(255, 200, 200)) self.table.setItem(insert_row, col_idx + 1, item) self.update_sequence_numbers() self.table.scrollToItem(self.table.item(insert_row, 0)) self.table.selectRow(insert_row) self.statusBar.showMessage("已添加新记录", 2000) def delete_record(self): selected_rows = set(index.row() for index in self.table.selectedIndexes()) if not selected_rows: QMessageBox.warning(self, "警告", "请先选择要删除的记录") return reply = QMessageBox.question(self, "确认删除", f"确定要删除选中的 {len(selected_rows)} 条记录吗?", QMessageBox.Yes | QMessageBox.No) if reply != QMessageBox.Yes: return # 按降序删除以避免索引问题 for row in sorted(selected_rows, reverse=True): self.table.removeRow(row) if row < len(self.display_data): del self.display_data[row] if self.is_searching and row < len(self.search_results_indices): # 如果是搜索状态,需要从原始数据中删除 original_idx = self.search_results_indices[row] if original_idx < len(self.temp_data): del self.temp_data[original_idx] # 更新搜索结果索引 self.search_results_indices = [x if x < original_idx else x - 1 for x in self.search_results_indices] self.search_results_indices.pop(row) elif not self.is_searching and row < len(self.temp_data): del self.temp_data[row] self.update_sequence_numbers() self.statusBar.showMessage(f"已删除 {len(selected_rows)} 条记录", 3000) def update_sequence_numbers(self): for row_idx in range(self.table.rowCount()): if self.is_searching and row_idx < len(self.search_results_indices): original_idx = self.search_results_indices[row_idx] seq_item = QTableWidgetItem(str(original_idx + 1)) else: seq_item = QTableWidgetItem(str(self.row_counter + row_idx)) seq_item.setTextAlignment(Qt.AlignCenter) seq_item.setFlags(seq_item.flags() & ~Qt.ItemIsEditable) self.table.setItem(row_idx, 0, seq_item) def save_changes(self): if not self.display_data: QMessageBox.warning(self, "警告", "没有数据可保存") return empty_fields = [] for row_idx in range(self.table.rowCount()): for col_idx, col_name in enumerate(self.column_names): if col_name in self.required_columns: item = self.table.item(row_idx, col_idx + 1) if item is None or not item.text().strip(): seq_item = self.table.item(row_idx, 0) row_num = seq_item.text() if seq_item else str(row_idx + 1) empty_fields.append(f"行 {row_num} 的 '{col_name}' 列") if empty_fields: error_msg = "以下必填项为空,请填写完整后保存:\n" error_msg += "\n".join(empty_fields[:10]) if len(empty_fields) > 10: error_msg += f"\n...(共{len(empty_fields)}个错误)" QMessageBox.warning(self, "保存失败", error_msg) return try: # 更新显示数据 for row_idx in range(self.table.rowCount()): while row_idx >= len(self.display_data): self.display_data.append({col_name: "" for col_name in self.column_names}) for col_idx, col_name in enumerate(self.column_names): item = self.table.item(row_idx, col_idx + 1) if item: self.display_data[row_idx][col_name] = item.text() if col_name == 'type' and item.text(): self.type_options.add(item.text()) elif col_name == 'data_type_id' and item.text(): self.data_type_id_options.add(item.text()) else: self.display_data[row_idx][col_name] = "" # 更新临时数据 if self.is_searching: # 在搜索状态下,需要特殊处理以保持数据一致性 for display_idx, original_idx in enumerate(self.search_results_indices): if display_idx < len(self.display_data) and original_idx < len(self.temp_data): for col_name in self.column_names: self.temp_data[original_idx][col_name] = self.display_data[display_idx][col_name] else: # 非搜索状态下,直接更新临时数据 self.temp_data = [row.copy() for row in self.display_data] self.statusBar.showMessage("修改已保存到内存", 2000) except Exception as e: QMessageBox.critical(self, "错误", f"保存失败: {str(e)}") def search_records(self): search_text = self.search_box.text().strip().lower() selected_column = self.column_combo.currentText() if not search_text: self.clear_search() return self.is_searching = True self.search_results_indices = [] matched_rows = [] # 搜索基于临时数据(包含所有修改) for original_idx, record in enumerate(self.temp_data): match_found = False if selected_column == "所有列": for col_name in self.column_names: value = record.get(col_name, '').lower() if search_text in value: match_found = True break else: value = record.get(selected_column, '').lower() if search_text in value: match_found = True if match_found: self.search_results_indices.append(original_idx) matched_rows.append(record) if matched_rows: self.display_data = matched_rows # 传递原始索引用于显示正确的序号 self.populate_table(self.display_data, self.search_results_indices) self.adjust_column_widths() self.statusBar.showMessage(f"找到 {len(matched_rows)} 条匹配记录", 3000) else: QMessageBox.information(self, "搜索结果", "未找到匹配记录") self.statusBar.showMessage("未找到匹配记录", 2000) def clear_search(self): # 恢复显示所有数据,保留所有修改 self.display_data = [row.copy() for row in self.temp_data] self.is_searching = False self.search_results_indices = [] self.populate_table() self.adjust_column_widths() self.statusBar.showMessage("已显示所有记录", 2000) if __name__ == "__main__": app = QApplication(sys.argv) window = XMLDataManager() window.show() sys.exit(app.exec_()) 修改上面的程序,对搜索结果高亮显示,清空搜索后,搜索内容框里面的内容为空。显示修改后的完整程序
08-21
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值