# -*- coding: utf-8 -*- """ 栅格处理界面: 提供栅格重分类、栅格转矢量和小面积图斑消除的界面操作 """ import os import json import arcpy from PyQt6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QPushButton, QFileDialog, QGridLayout, QGroupBox, QMessageBox) from tools.ui.runners.script_runner import ScriptRunner class AcidStatsTab(QWidget): """栅格处理窗口部件类""" def __init__(self, parent=None): super(AcidStatsTab, self).__init__(parent) self.main_window = parent # 创建的导出线程 self.script_runner = ScriptRunner() self.connect_signals() self.init_ui() self.setWindowTitle("酸化状况统计") def connect_signals(self): # 连接ScriptRunner的信号 self.script_runner.task_started.connect(self.on_script_started) self.script_runner.task_finished.connect(self.on_script_finished) self.script_runner.task_error.connect(self.on_script_error) self.script_runner.task_log.connect(self.on_script_log) self.script_runner.manager_log.connect(self.log_message) def init_ui(self): """初始化用户界面""" main_layout = QVBoxLayout(self) # 批量处理区域 self.batch_mode_group = QGroupBox("批量处理设置") batch_layout = QGridLayout() # 输入行政区名称 batch_layout.addWidget(QLabel("行政区名称:"), 0, 0) self.input_xzqmc_edit = QLineEdit() batch_layout.addWidget(self.input_xzqmc_edit, 0, 1) # 设置工作空间 batch_layout.addWidget(QLabel("工作空间:"), 1, 0) self.input_workspace_edit = QLineEdit() batch_layout.addWidget(self.input_workspace_edit, 1, 1) self.browse_input_workspace_btn = QPushButton("选择GDB") self.browse_input_workspace_btn.clicked.connect(self.browse_input_workspace) batch_layout.addWidget(self.browse_input_workspace_btn, 1, 2) # 批量输出文件夹 batch_layout.addWidget(QLabel("输出文件夹:"), 2, 0) self.batch_output_folder_edit = QLineEdit() batch_layout.addWidget(self.batch_output_folder_edit, 2, 1) self.browse_batch_output_btn = QPushButton("选择文件夹") self.browse_batch_output_btn.clicked.connect(self.browse_batch_output_folder) batch_layout.addWidget(self.browse_batch_output_btn, 2, 2) # 选择乡镇界线 batch_layout.addWidget(QLabel("乡镇界线:"), 3, 0) self.xzq_features_edit = QLineEdit() batch_layout.addWidget(self.xzq_features_edit, 3, 1) batch_layout.addWidget(QLabel("GDB中的要素类名"), 3, 2) # 选择地类图斑 batch_layout.addWidget(QLabel("地类图斑:"), 4, 0) self.dltb_features_edit = QLineEdit() batch_layout.addWidget(self.dltb_features_edit, 4, 1) batch_layout.addWidget(QLabel("GDB中的要素类名"), 4, 2) # 选择历史PH样点图斑 batch_layout.addWidget(QLabel("历史PH样点:"), 5, 0) self.ph_samples_edit = QLineEdit() batch_layout.addWidget(self.ph_samples_edit, 5, 1) batch_layout.addWidget(QLabel("GDB中的要素类名"), 5, 2) # 选择重分类后的PH面要素 batch_layout.addWidget(QLabel("分类后酸化PH面:"), 6, 0) self.acid_ph_edit = QLineEdit() batch_layout.addWidget(self.acid_ph_edit, 6, 1) batch_layout.addWidget(QLabel("GDB中的要素类名"), 6, 2) # 选择土壤类型图斑 batch_layout.addWidget(QLabel("土壤类型图斑:"), 7, 0) self.soil_type_features_edit = QLineEdit() batch_layout.addWidget(self.soil_type_features_edit, 7, 1) batch_layout.addWidget(QLabel("GDB中的要素类名"), 7, 2) # 选择三普PH赋值栅格 batch_layout.addWidget(QLabel("三普PH栅格:"), 8, 0) self.assign_raster_edit = QLineEdit() batch_layout.addWidget(self.assign_raster_edit, 8, 1) self.assign_raster_btn = QPushButton("选择TIF") self.assign_raster_btn.clicked.connect(self.browse_assign_raster) batch_layout.addWidget(self.assign_raster_btn, 8, 2) # 选择酸化PH赋值栅格 batch_layout.addWidget(QLabel("酸化PH栅格:"), 9, 0) self.acid_raster_edit = QLineEdit() batch_layout.addWidget(self.acid_raster_edit, 9, 1) self.acid_raster_btn = QPushButton("选择TIF") self.acid_raster_btn.clicked.connect(self.browse_acid_raster) batch_layout.addWidget(self.acid_raster_btn, 9, 2) self.batch_mode_group.setLayout(batch_layout) # 操作按钮 btn_layout = QHBoxLayout() # 导出酸化统计表 self.generate_sh_stat_btn = QPushButton("生成酸化统计表") self.generate_sh_stat_btn.clicked.connect(self.on_generate_area_stat) self.cancel_btn = QPushButton("取消") # self.cancel_btn.clicked.connect(self.close) btn_layout.addWidget(self.generate_sh_stat_btn) btn_layout.addWidget(self.cancel_btn) # 添加所有组件到主布局 main_layout.addWidget(self.batch_mode_group) main_layout.addLayout(btn_layout) self.setLayout(main_layout) def browse_input_workspace(self): """浏览选择输入GDB""" folder_path = QFileDialog.getExistingDirectory(self, "选择GDB数据库") if folder_path: self.input_workspace_edit.setText(folder_path) def browse_batch_output_folder(self): """浏览选择表格输出文件夹""" folder_path = QFileDialog.getExistingDirectory(self, "选择表格输出文件夹") if folder_path: self.batch_output_folder_edit.setText(folder_path) def browse_assign_raster(self): """浏览选择赋值栅格 (支持栅格数据)""" file_path, _ = QFileDialog.getOpenFileName( self, "选择赋值栅格", "", "栅格文件 (*.tif *.img *.jpg);;所有文件 (*)" ) if not file_path: return if file_path.lower().endswith(('.tif', '.img', '.jpg')): self.assign_raster_edit.setText(file_path) self.log_message(f"已选择栅格文件: {file_path}") else: QMessageBox.warning(self, "选择错误", "不支持的文件类型。请选择有效的栅格文件。") self.assign_raster_edit.clear() def browse_acid_raster(self): """浏览选择赋值栅格 (支持栅格数据)""" file_path, _ = QFileDialog.getOpenFileName( self, "选择赋值栅格", "", "栅格文件 (*.tif *.img *.jpg);;所有文件 (*)" ) if not file_path: return if file_path.lower().endswith(('.tif', '.img', '.jpg')): self.acid_raster_edit.setText(file_path) self.log_message(f"已选择栅格文件: {file_path}") else: QMessageBox.warning(self, "选择错误", "不支持的文件类型。请选择有效的栅格文件。") self.acid_raster_edit.clear() def validate_inputs(self): """验证输入参数""" # 验证工作空间路径 if not self.input_workspace_edit.text() or not arcpy.Exists(self.input_workspace_edit.text()): QMessageBox.warning(self, "输入错误", "请选择有效的工作空间") return False if not self.batch_output_folder_edit.text(): QMessageBox.warning(self, "输入错误", "请选择批量处理输出文件夹") return False # 行政界线验证 xzq_path = os.path.join(self.input_workspace_edit.text(),self.xzq_features_edit.text()) if not xzq_path or not arcpy.Exists(xzq_path): QMessageBox.warning(self, "输入错误", "行政界线要素路径无效或不存在") return False try: desc = arcpy.Describe(xzq_path) if desc.dataType != 'FeatureClass': QMessageBox.warning(self, "输入错误", f"行政界线不是一个要素类:\n{xzq_path}") return False except Exception as e: QMessageBox.warning(self, "输入错误", f"未知要素,请检查是否为有效要素类:\n{xzq_path}\n错误: {e}") return False # 地类图斑验证 dltb_path = os.path.join(self.input_workspace_edit.text(),self.dltb_features_edit.text()) if not dltb_path or not arcpy.Exists(dltb_path): QMessageBox.warning(self, "输入错误", "地类图斑要素路径无效或不存在") return False try: desc = arcpy.Describe(dltb_path) if desc.dataType != 'FeatureClass': QMessageBox.warning(self, "输入错误", f"地类图斑不是一个要素类:\n{dltb_path}") return False except Exception as e: QMessageBox.warning(self, "输入错误", f"未知要素,请检查是否为有效要素类:\n{dltb_path}\n错误: {e}") return False # 验证PH样点 samples_path = os.path.join(self.input_workspace_edit.text(), self.ph_samples_edit.text()) if not samples_path or not arcpy.Exists(samples_path): QMessageBox.warning(self, "输入错误", "PH样点要素路径无效或不存在") return False try: desc = arcpy.Describe(samples_path) if desc.dataType != 'FeatureClass': QMessageBox.warning(self, "输入错误", f"PH样点不是一个要素类:\n{samples_path}") return False except Exception as e: QMessageBox.warning(self, "输入错误", f"未知要素,请检查是否为有效要素类:\n{samples_path}\n错误: {e}") return False # 重分类后酸化面要素验证 acid_ph_path = os.path.join(self.input_workspace_edit.text(), self.acid_ph_edit.text()) if not acid_ph_path or not arcpy.Exists(acid_ph_path): QMessageBox.warning(self, "输入错误", "酸化PH要素路径无效或不存在") return False try: desc = arcpy.Describe(acid_ph_path) if desc.dataType != 'FeatureClass': QMessageBox.warning(self, "输入错误", f"酸化PH不是一个要素类:\n{acid_ph_path}") return False except Exception as e: QMessageBox.warning(self, "输入错误", f"未知要素,请检查是否为有效要素类:\n{acid_ph_path}\n错误: {e}") return False # 土壤类型验证 trlx_path = os.path.join(self.input_workspace_edit.text(), self.soil_type_features_edit.text()) if not self.soil_type_features_edit.text() or not arcpy.Exists(trlx_path): QMessageBox.warning(self, "输入错误", "土壤类型要素路径无效或不存在") return False try: desc = arcpy.Describe(trlx_path) if desc.dataType != 'FeatureClass': QMessageBox.warning(self, "输入错误", f"土壤类型不是一个要素类:\n{trlx_path}") return False except Exception as e: QMessageBox.warning(self, "输入错误", f"未知要素,请检查是否为有效要素类:\n{trlx_path}\n错误: {e}") return False # 验证输入是否为栅格 if not self.acid_raster_edit.text() or not self.assign_raster_edit.text(): QMessageBox.warning(self, "输入错误", "请选择输入栅格") return False elif not arcpy.Exists(self.acid_raster_edit.text()) or not arcpy.Exists(self.assign_raster_edit.text()): QMessageBox.warning(self, "输入错误", "输入栅格不存在") return False return True # 执行生成酸化统计表 def on_generate_area_stat(self): """执行生成面积统计表""" if not self.validate_inputs(): return try: if self.main_window and hasattr(self.main_window, 'save_settings'): self.main_window.update_settings() self.main_window.save_settings() settings_file = self.main_window.settings_file params = { "settings_path": settings_file, } task_id = self.script_runner.run_suanhua_stat(params) if task_id: self.log_message(f"[GUI] 面积统计任务 {task_id} 已添加到列队") except Exception as e: error_msg = f"处理过程中出错: {str(e)}" QMessageBox.critical(self, "处理错误", error_msg) self.log_message(error_msg) def get_acid_stat_settings(self): """保存当前配置到JSON文件""" config = { "workspace_path": self.input_workspace_edit.text(), "batch_output_folder": self.batch_output_folder_edit.text(), "xzq_features": self.xzq_features_edit.text(), "dltb_features": self.dltb_features_edit.text(), "ph_samples": self.ph_samples_edit.text(), "acid_ph_features": self.acid_ph_edit.text(), "assign_raster": self.assign_raster_edit.text(), "acid_raster": self.acid_raster_edit.text(), "soil_type_features": self.soil_type_features_edit.text(), "xzqmc": self.input_xzqmc_edit.text() } return config def load_settings(self, settings): """从字典加载配置""" try: # 批处理参数 self.input_workspace_edit.setText(settings.get("workspace_path", "")) self.batch_output_folder_edit.setText(settings.get("batch_output_folder", "")) self.xzq_features_edit.setText(settings.get("xzq_features", "")) self.dltb_features_edit.setText(settings.get("dltb_features", "")) self.ph_samples_edit.setText(settings.get("ph_samples", "")) self.acid_ph_edit.setText(settings.get("acid_ph_features", "")) self.assign_raster_edit.setText(settings.get("assign_raster", "")) self.acid_raster_edit.setText(settings.get("acid_raster", "")) self.soil_type_features_edit.setText(settings.get("soil_type_features", "")) return True except Exception as e: QMessageBox.critical(self, "加载配置错误", f"加载配置时出错: {str(e)}") return False def set_buttons_enabled(self, enabled): """设置按钮是否可用""" self.generate_sh_stat_btn.setEnabled(enabled) def on_script_started(self, task_id, task_description): """脚本开始执行""" self.set_buttons_enabled(False) self.log_message(f"{task_id}: 正在运行 - {task_description}") def on_script_finished(self, task_id:str, success:bool, message:str): """脚本执行完成""" self.set_buttons_enabled(True) status = "完成" if success else "失败" self.log_message(f"[{task_id}] 脚本执行{status}: {message}") def on_script_error(self,task_id, error_msg): """脚本执行出错""" self.set_buttons_enabled(True) self.log_message(f"错误:{task_id}-{error_msg}") # QMessageBox.critical(self, "错误", error_msg) def on_script_log(self, task_id, message): """脚本输出日志""" self.log_message(f"{task_id}: {message}") def log_message(self, message): """日志输出""" if self.main_window and hasattr(self.main_window, 'log_signal'): self.main_window.log_signal.emit(message) else: print(message) if __name__ == "__main__": from PyQt6.QtWidgets import QApplication import sys app = QApplication(sys.argv) window = AcidStatsTab() window.show() sys.exit(app.exec())