pyside6 打开.c文件过滤注释等,保留需要的字符

文章介绍了如何利用Python的正则表达式库`re`和Qt库中的`QFileDialog`及`QTextEdit`组件,从C源代码中提取特定的配置数据,如`SPICMD`和`SPIDAT`,并去除注释和空白符,以便进一步处理或应用。
部署运行你感兴趣的模型镜像

需要提取.c中的配置数据,用以他用,c文件的内容简单举例如下:

#define hello 0
/////

SPICMD(0xFB);
SPIDAT(0x00);
SPIDAT(0x01);

//SPICMD(0xFB);
//SPIDAT(0x02);
//SPIDAT(0x03);

SPICMD(0xFB);    //SPIDAT(0x04);    SPIDAT(0x05);

SPIDAT(0x08);    SPIDAT(0x09);/*
SPICMD(0xFB);
SPIDAT(0x06);
SPIDAT(0x07);
*/

目的是删掉红色部分内容,保留黑色部分数据,并格式化去空格、Tab以及分行。

中间有用好多方法,最后询问了优快云的Gpt给的建议,灵光一闪,用re简单处理好了。

openfile.py

import sys
import re
from PySide6.QtWidgets import QApplication, QMainWindow, QFileDialog, QTextEdit
from PySide6.QtGui import QAction
from openfile_ui import Ui_Form


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.ui = Ui_Form()
        self.ui.setupUi(self)
        self.ui.pushButton.released.connect(self.file_open)

    def file_open(self):
        file_name, _ = QFileDialog.getOpenFileName(self, '打开文件', '', 'C files (*.c)')
        if file_name:
            # with open(file_name, 'r', encoding='utf-8') as file:
            file = open(file_name,'r', encoding='utf-8')
            content = file.read()           #as string

            regex_case = re.compile('.*SPICMD.*')
            regex_case1 = re.compile('.*SPIDAT.*')
            regex_case2 = re.compile('//.*')        #找//
            regex_case3 = re.compile(r'/\*.*?\*/', re.DOTALL)  #找/*  */

            text_no_comment1 = re.sub(regex_case2, '', content)# del //后面内容
            content = re.sub(regex_case3, '', text_no_comment1)# del /* */之间内容
            content = content.replace(' ','').replace('    ','').replace(';',';\n')
            # print(content)
            
            tmp_list = content.split('\n')
            content_list = [i for i in tmp_list if i != ""]
            # print(content_list)
            str1 = ''
            for line in content_list:

                regex_case = re.compile('.*SPICMD.*')
                regex_case1 = re.compile('.*SPIDAT.*')

                found_case = regex_case.search(line)
                found_case1 = regex_case1.search(line)

                if found_case or found_case1:
                    # print(line)
                    str1 = str1 + line + '\n'

            self.ui.textEdit.setPlainText(str1)        
            file.close()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())

openfile_ui.py

# -*- coding: utf-8 -*-

################################################################################
## Form generated from reading UI file 'openfile_ui.ui'
##
## Created by: Qt User Interface Compiler version 6.4.1
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################

from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
    QMetaObject, QObject, QPoint, QRect,
    QSize, QTime, QUrl, Qt)
from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
    QFont, QFontDatabase, QGradient, QIcon,
    QImage, QKeySequence, QLinearGradient, QPainter,
    QPalette, QPixmap, QRadialGradient, QTransform)
from PySide6.QtWidgets import (QApplication, QPushButton, QSizePolicy, QTextEdit,
    QVBoxLayout, QWidget)

class Ui_Form(object):
    def setupUi(self, Form):
        if not Form.objectName():
            Form.setObjectName(u"Form")
        Form.resize(404, 271)
        self.verticalLayoutWidget = QWidget(Form)
        self.verticalLayoutWidget.setObjectName(u"verticalLayoutWidget")
        self.verticalLayoutWidget.setGeometry(QRect(0, 0, 401, 271))
        self.verticalLayout = QVBoxLayout(self.verticalLayoutWidget)
        self.verticalLayout.setObjectName(u"verticalLayout")
        self.verticalLayout.setContentsMargins(0, 0, 0, 0)
        self.textEdit = QTextEdit(self.verticalLayoutWidget)
        self.textEdit.setObjectName(u"textEdit")

        self.verticalLayout.addWidget(self.textEdit)

        self.pushButton = QPushButton(self.verticalLayoutWidget)
        self.pushButton.setObjectName(u"pushButton")

        self.verticalLayout.addWidget(self.pushButton)


        self.retranslateUi(Form)

        QMetaObject.connectSlotsByName(Form)
    # setupUi

    def retranslateUi(self, Form):
        Form.setWindowTitle(QCoreApplication.translate("Form", u"Form", None))
        self.pushButton.setText(QCoreApplication.translate("Form", u"&Open", None))
    # retranslateUi

运行结果如下:

如此获得的数据,再进行二次提炼发送串口或者其他用途。

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

Python3.9

Python3.9

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

麻烦帮我优化这段代码,需要保留完整功能和逻辑from PySide2 import QtGui from PySide2 import QtWidgets, QtCore from shiboken2 import wrapInstance from maya.app.general.mayaMixin import MayaQWidgetDockableMixin from maya import OpenMayaUI as omui import maya.OpenMaya as om import maya.cmds as cmds import maya.mel as mel import os, platform, subprocess, sys import xml.dom.minidom as xml # 用于XML设置 DEBUG = False PRNT_STRING = "<RizomUV桥接工具>" # 日志前缀汉化 try: # Python 3 from . import scriptlist except ImportError: import scriptlist class Settings(): def __init__(self): config_path = os.path.join('%s/RizomBridge' % os.getenv('APPDATA')) config_file = 'uisettings.xml' # 脚本路径设置 rizom_script_path = os.path.join(config_path, "MayaRizomBridgeScript.lua") self.rizom_script_path = rizom_script_path.replace('\\', '/') self.apppath = None self.config_file_path = os.path.join(config_path, config_file) self.check_config_exists(config_path) try: self.read_settings() except: print("<RizomUV桥接工具> 读设置失败,正在创建新的xml文件。") # 日志汉化 self.set_defaults() self.save_xml() self.read_settings() self.exportFile = os.path.join(config_path, self.objname) self.exportFile = self.exportFile.replace('\\', '/') def read_settings(self): doc = xml.parse(self.config_file_path) ui_app = doc.getElementsByTagName("Application")[0] self.apppath = ui_app.getAttribute("apppath") self.objname = ui_app.getAttribute("objname") self.upaxis = ui_app.getAttribute("upaxis") self.loaduvs = self.str_to_bool(ui_app.getAttribute("loaduvs")) self.useuvlink = self.str_to_bool(ui_app.getAttribute("useuvlink")) self.fixuvnames = self.str_to_bool(ui_app.getAttribute("fixuvnames")) ui_packer = doc.getElementsByTagName("Packer")[0] self.quality = int(ui_packer.getAttribute("quality")) self.mutations = int(ui_packer.getAttribute("mutations")) self.margin = int(ui_packer.getAttribute("margin")) self.spacing = int(ui_packer.getAttribute("spacing")) self.resolution = int(ui_packer.getAttribute("resolution")) self.initscaleavg = self.str_to_bool(ui_packer.getAttribute("initscaleavg")) self.autofit = self.str_to_bool(ui_packer.getAttribute("autofit")) def set_defaults(self): self.objname = "MayaRizomExport.fbx" self.upaxis = "Y" self.loaduvs = True self.useuvlink = True self.fixuvnames = False self.quality = 2 self.mutations = 256 self.margin = 2 self.spacing = 2 self.resolution = 1024 self.initscaleavg = True self.autofit = True self.apppath = self.findall_rizom_installs()[-1] def save_xml(self): print(PRNT_STRING, f"将设置保存到磁盘: {self.config_file_path}") # 日志汉化 doc = xml.Document() root_element = doc.createElement("RizomBridge") element_application = doc.createElement("Application") element_application.setAttribute("apppath", str(self.apppath)) element_application.setAttribute("objname", str(self.objname)) element_application.setAttribute("upaxis", str(self.upaxis)) element_application.setAttribute("loaduvs", str(self.loaduvs)) element_application.setAttribute("useuvlink", str(self.useuvlink)) element_application.setAttribute("fixuvnames", str(self.fixuvnames)) element_packer = doc.createElement("Packer") element_packer.setAttribute("quality", str(self.quality)) element_packer.setAttribute("mutations", str(self.mutations)) element_packer.setAttribute("margin", str(self.margin)) element_packer.setAttribute("spacing", str(self.spacing)) element_packer.setAttribute("resolution", str(self.resolution)) element_packer.setAttribute("initscaleavg", str(self.initscaleavg)) element_packer.setAttribute("autofit", str(self.autofit)) doc.appendChild(root_element) root_element.appendChild(element_application) root_element.appendChild(element_packer) doc.writexml(open(self.config_file_path, 'w'), indent=" ", addindent=" ", newl='\n') def check_config_exists(self, config_path): print(PRNT_STRING, f"检查配置文件: {self.config_file_path}") # 日志汉化 if not os.path.exists(config_path): os.makedirs(config_path) if not os.path.exists(self.config_file_path): print(PRNT_STRING, "未找到配置文件。") # 日志汉化 self.set_defaults() self.save_xml() else: print(PRNT_STRING, "找到配置文件。") # 日志汉化 def findall_rizom_installs(self): """ 返回注册表中所有存在的rizom.exe路径 """ try: import winreg except: self.manual_locate_rizom() return [self.apppath] key_path = "SOFTWARE\\Rizom Lab\\" parent_key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, key_path) installs = [] i = 0 while i < 1000: try: key = winreg.EnumKey(parent_key, i) try: exe_path = winreg.QueryValue(winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, key_path + key), "rizomuv.exe") + ".exe" except FileNotFoundError: exe_path = "" if os.path.exists(exe_path): installs.append(exe_path.replace("\\", "/")) except WindowsError: break i += 1 print(PRNT_STRING, "在Windows注册表中找到RizomUV安装路径:") # 日志汉化 for inst in sorted(installs): print(" ..", inst) return sorted(installs) def manual_locate_rizom(self): om.MGlobal.displayWarning(f"无法定位rizomuv.exe: {self.apppath}") # 提示汉化 fname = QtWidgets.QFileDialog.getOpenFileName(None, '定位rizomuv.exe', 'C:/Program Files/Rizom Lab/', "可执行文件 (*.exe)") # 对话框标题及过滤器汉化 self.apppath = fname[0] self.appver = self.get_version() self.save_xml() def get_version(self): """ 从文件夹名称读版本号,返回列表形式,例如 [2022, 2] """ # 注释汉化 return os.path.dirname(self.apppath).split()[-1].split('.') def check_lua_path(self): if not os.path.exists(self.rizom_script_path): with open(self.rizom_script_path, 'w') as f: if DEBUG: print(PRNT_STRING, f"在{self.rizom_script_path}创建空白lua文件") # 日志汉化 f.write('') def str_to_bool(self, s): if s == 'True': return True else: # 其他情况均返回False,否则可能返回None导致崩溃 return False class RizomUVBridgeWindow(MayaQWidgetDockableMixin, QtWidgets.QDialog): def __init__(self, rootWidget=None, *args, **kwargs): super(RizomUVBridgeWindow, self).__init__() self.conf = Settings() self.conf.check_lua_path() print("Rizom路径:", self.conf.apppath) # 日志汉化 self.setWindowTitle("桥接工具") # 窗口标题汉化 self.sj_num_selchange = cmds.scriptJob(parent=self.objectName(), event=['SelectionChanged', self.ui_update_uvchannels]) self.resize(250, 300) self.create_widgets() self.create_layouts() self.create_connections() self.exported_objects = [] self.ui_update_uvchannels() self.cleanse_namespaces() self.config_updated = False if not os.path.exists(self.conf.apppath): self.conf.manual_locate_rizom() v = self.conf.get_version() self.btn_run.setText(f'运行RizomUV {v[0]}.{v[1]}') # 按钮文本汉化 rizom_link_path = os.path.dirname(self.conf.apppath) + '/RizomUVLink' self.port = None if rizom_link_path not in sys.path: sys.path.append(os.path.dirname(self.conf.apppath) + '/RizomUVLink') try: from RizomUVLink import CRizomUVLink self.link = CRizomUVLink() except: self.link = None def create_widgets(self): v = ".".join(self.conf.get_version()) self.btn_run = QtWidgets.QPushButton(f'运行RizomUV {v}', self) # 按钮文本汉化 self.btn_export = QtWidgets.QPushButton('导出', self) # 按钮文本汉化 self.btn_import = QtWidgets.QPushButton('导入', self) # 按钮文本汉化 self.cbx_use_link = QtWidgets.QCheckBox('尝试使用CRizomUVLink连接', self) # 复选框文本汉化 self.cbx_use_link.setChecked(self.conf.useuvlink) self.cbx_fix_set_names = QtWidgets.QCheckBox('导入时修复UV集名称', self) # 复选框文本汉化 self.cbx_fix_set_names.setChecked(self.conf.fixuvnames) if not os.path.exists(self.conf.exportFile): self.btn_import.setEnabled(False) # 导出设置组件 self.radioAxisY = QtWidgets.QRadioButton('Y轴') # 单选按钮文本汉化 self.radioAxisZ = QtWidgets.QRadioButton('Z轴') # 单选按钮文本汉化 if self.conf.upaxis == 'Y': self.radioAxisY.setChecked(True) else: self.radioAxisZ.setChecked(True) self.cbx_keepuv = QtWidgets.QCheckBox('加载现有UV', self) # 复选框文本汉化 self.cbx_keepuv.setChecked(self.conf.loaduvs) self.combo_scripts = QtWidgets.QComboBox(self) self.combo_scripts.addItem("无脚本") # 下拉框文本汉化 for s in scriptlist.scripts: self.combo_scripts.addItem(s[1]) # 工具组件 self.btn_fix_shell_normals = QtWidgets.QPushButton('将UV边界边设为硬边') # 按钮文本汉化 self.btn_edit_settings = QtWidgets.QPushButton('打开设置文件夹') # 按钮文本汉化 self.combo_pack_uvset = QtWidgets.QComboBox(self) self.btn_pack = QtWidgets.QPushButton('导出并打包UV', self) # 按钮文本汉化 self.combo_pack_quality = QtWidgets.QComboBox(self) self.combo_pack_quality.addItems(['低', '普通', '高', '较高', '极高']) # 下拉框文本汉化 self.combo_pack_quality.setCurrentIndex(self.conf.quality) self.slider_pack_uvmap = QtWidgets.QSlider(QtCore.Qt.Orientation(1)) self.slider_pack_uvmap.setMinimum(0) self.slider_pack_uvmap.setMaximum(5) self.slider_pack_uvmap.setValue(1) self.label_uvmap = QtWidgets.QLabel("1") self.dspin_pack_mutations = QtWidgets.QSpinBox() self.dspin_pack_mutations.setSingleStep(1) self.dspin_pack_mutations.setRange(1, 1000) self.dspin_pack_mutations.setWrapping(False) self.dspin_pack_mutations.setValue(self.conf.mutations) self.dspin_pack_resolution = QtWidgets.QSpinBox() self.dspin_pack_resolution.setSingleStep(8) self.dspin_pack_resolution.setRange(8, 8192) self.dspin_pack_resolution.setWrapping(False) self.dspin_pack_resolution.setValue(self.conf.resolution) self.dspin_pack_margin = QtWidgets.QSpinBox() self.dspin_pack_margin.setSingleStep(1) self.dspin_pack_margin.setWrapping(False) self.dspin_pack_margin.setValue(self.conf.margin) self.dspin_pack_spacing = QtWidgets.QSpinBox() self.dspin_pack_spacing.setSingleStep(1) self.dspin_pack_spacing.setWrapping(False) self.dspin_pack_spacing.setValue(self.conf.spacing) self.cbx_initial_scale_avg = QtWidgets.QCheckBox("使用'平均'初始缩放", self) # 复选框文本汉化 self.cbx_initial_scale_avg.setChecked(self.conf.initscaleavg) self.cbx_layout_scaling = QtWidgets.QCheckBox("布局:自动适配", self) # 复选框文本汉化 self.cbx_layout_scaling.setChecked(self.conf.autofit) def create_layouts(self): main_layout = QtWidgets.QVBoxLayout(self) grp_layout = QtWidgets.QVBoxLayout() grp_layout.addWidget(self.btn_run) grp_layout.addWidget(self.btn_export) grp_layout.addWidget(self.btn_import) grp_layout.addWidget(self.cbx_use_link) grp_layout.addWidget(self.cbx_fix_set_names) grp = QtWidgets.QGroupBox("UV操作") # 组框标题汉化 grp.setLayout(grp_layout) main_layout.addWidget(grp) # 导出设置 grp_layout = QtWidgets.QVBoxLayout() grp_layout.addWidget(self.cbx_keepuv) hor_layout = QtWidgets.QHBoxLayout() hor_layout.addWidget(QtWidgets.QLabel("脚本")) # 标签文本汉化 hor_layout.addWidget(self.combo_scripts) grp_layout.addLayout(hor_layout) hor_layout = QtWidgets.QHBoxLayout() hor_layout.addWidget(QtWidgets.QLabel("上方向轴")) # 标签文本汉化 hor_layout.addWidget(self.radioAxisY) hor_layout.addWidget(self.radioAxisZ) grp_layout.addLayout(hor_layout) grp = QtWidgets.QGroupBox("导出设置") # 组框标题汉化 grp.setLayout(grp_layout) main_layout.addWidget(grp) # 工具 grp_layout = QtWidgets.QVBoxLayout() grp_layout.addWidget(self.btn_fix_shell_normals) grp_layout.addWidget(self.btn_edit_settings) grp = QtWidgets.QGroupBox("工具") # 组框标题汉化 grp.setLayout(grp_layout) main_layout.addWidget(grp) # UV打包 grp_layout = QtWidgets.QVBoxLayout() grp = QtWidgets.QGroupBox("UV打包") # 组框标题汉化 hor_layout = QtWidgets.QHBoxLayout() hor_layout.addWidget(self.btn_pack) grp_layout.addLayout(hor_layout) hor_layout = QtWidgets.QHBoxLayout() hor_layout.addWidget(QtWidgets.QLabel("要打包的UV集")) # 标签文本汉化 hor_layout.addWidget(self.combo_pack_uvset) grp_layout.addLayout(hor_layout) hor_layout = QtWidgets.QHBoxLayout() hor_layout.addWidget(QtWidgets.QLabel("打包质量")) # 标签文本汉化 hor_layout.addWidget(self.combo_pack_quality) grp_layout.addLayout(hor_layout) hor_layout = QtWidgets.QHBoxLayout() hor_layout.addWidget(QtWidgets.QLabel("迭代次数")) # 标签文本汉化 hor_layout.addWidget(self.dspin_pack_mutations) hor_layout.addWidget(QtWidgets.QLabel("分辨率")) # 标签文本汉化 hor_layout.addWidget(self.dspin_pack_resolution) grp_layout.addLayout(hor_layout) hor_layout = QtWidgets.QHBoxLayout() hor_layout.addWidget(QtWidgets.QLabel("边距")) # 标签文本汉化 hor_layout.addWidget(self.dspin_pack_margin) hor_layout.addWidget(QtWidgets.QLabel("间距")) # 标签文本汉化 hor_layout.addWidget(self.dspin_pack_spacing) grp_layout.addLayout(hor_layout) hor_layout = QtWidgets.QHBoxLayout() hor_layout.addWidget(self.cbx_initial_scale_avg) grp_layout.addLayout(hor_layout) hor_layout = QtWidgets.QHBoxLayout() hor_layout.addWidget(self.cbx_layout_scaling) grp_layout.addLayout(hor_layout) grp_layout.addStretch() grp.setLayout(grp_layout) main_layout.addWidget(grp) def create_connections(self): self.btn_run.clicked.connect(self.riz_run) self.btn_export.clicked.connect(self.riz_export) self.btn_import.clicked.connect(self.riz_import) self.btn_fix_shell_normals.clicked.connect(fix_shell_border_normals) self.btn_edit_settings.clicked.connect(self.browse_settings_location) self.cbx_keepuv.stateChanged.connect(self.set_config) self.slider_pack_uvmap.valueChanged.connect(self.ui_pack_update_labels) self.radioAxisY.clicked.connect(self.set_config) self.radioAxisZ.clicked.connect(self.set_config) self.dspin_pack_mutations.valueChanged.connect(self.set_config) self.dspin_pack_resolution.valueChanged.connect(self.set_config) self.dspin_pack_margin.valueChanged.connect(self.set_config) self.dspin_pack_spacing.valueChanged.connect(self.set_config) self.cbx_layout_scaling.stateChanged.connect(self.set_config) self.cbx_use_link.stateChanged.connect(self.set_config) self.cbx_fix_set_names.stateChanged.connect(self.set_config) self.btn_pack.clicked.connect(self.riz_pack) return def riz_run(self): # 确认应用程序路径 if not os.path.exists(self.conf.apppath): self.manual_locate_rizom() if self.link and self.cbx_use_link.isChecked(): self.port = self.link.RunRizomUV() print(PRNT_STRING, f"RizomUV {self.link.RizomUVVersion()}链接已建立。正在TCP端口{self.port}监听命令") # 日志汉化 else: # 链接不可用时使用原始方法 print(PRNT_STRING, "RizomUV链接不可用。将使用LUA脚本文件通信。") # 日志汉化 cmd = '"' + self.conf.apppath + '" -cf "' + self.conf.rizom_script_path + '"' print(cmd) if platform.system() == "Windows": self.sp = subprocess.Popen(cmd, shell=True) else: self.sp = subprocess.Popen(["open", "-a", self.conf.apppath, "-cf", self.conf.rizom_script_path]) self.btn_export.setEnabled(True) return def riz_pack(self): # 导出模型不加载脚本 current_uv = self.combo_pack_uvset.currentText() exported = self.riz_export(False, False) if not exported: return # 根据GUI选项构建LUA代码 cmd = '' # 重复使用的文本块 cmd_properties_prefix = 'ZomIslandGroups({Mode="SetGroupsProperties", WorkingSet="Visible", MergingPolicyString="A_ADD|AIB_ADD_A_VALUE_B|B_CLONE", GroupPaths={ "RootGroup" }, ' # 加载模型 cmd += 'ZomLoad({File={Path="'+self.conf.exportFile+'", ImportGroups=true, XYZUVW=true, UVWProps=true}})\n' cmd += 'ZomUvset({Mode="SetCurrent", Name="%s"})\n' % current_uv cmd += cmd_properties_prefix + 'Properties={Pack={Rotate={Step=90}}}})\n' cmd += cmd_properties_prefix + 'Properties={Pack={Rotate={Mode=0}}}})\n' margin = float(self.dspin_pack_margin.value()) / self.dspin_pack_resolution.value() spacing = float(self.dspin_pack_spacing.value()) / self.dspin_pack_resolution.value() cmd += cmd_properties_prefix + 'Properties={Pack={SpacingSize=%f}}})\n' % spacing cmd += cmd_properties_prefix + 'Properties={Pack={MarginSize=%f}}})\n' % margin quality = [128, 256, 512, 1024, 2048] cmd += cmd_properties_prefix + 'Properties={Pack={Resolution=%i}}})\n' % quality[self.combo_pack_quality.currentIndex()] cmd += cmd_properties_prefix + 'Properties={Pack={MaxMutations=%i}}})\n' % self.dspin_pack_mutations.value() init_scale = 0 if self.cbx_initial_scale_avg.isChecked(): init_scale = 2 layout_scale = 0 if self.cbx_layout_scaling.isChecked(): layout_scale = 2 cmd += 'ZomSet({Path="Prefs.PackOptions.__ScalingMode", Value=%i})\n' % init_scale cmd += 'ZomSave({File={Path="c:/users/root/appdata/local/temp/MayaRizomExport.fbx", UVWProps=true}, __UpdateUIObjFileName=true})\n' cmd += 'ZomIslandGroups({Mode="DistributeInTilesEvenly", WorkingSet="Visible&Flat", MergingPolicyString="A_ADD|AIB_ADD_A_VALUE_B|B_CLONE", UseTileLocks=true, UseIslandLocks=true})\n' cmd += 'ZomPack({RootGroup="RootGroup", WorkingSet="Visible&Flat", ProcessTileSelection=false, RecursionDepth=1, Translate=true, LayoutScalingMode=%i, Scaling={Mode=%i}})\n' % (layout_scale, init_scale) if DEBUG: print(cmd) self.write_to_lua_file(cmd) return def fbx_export(self): # FBX导出 if not cmds.pluginInfo("fbxmaya", loaded=True, query=True): cmds.loadPlugin("fbxmaya") cmds.undoInfo(openChunk=True) mel.eval('ConvertInstanceToObject;') # 这是唯一需要撤销的命令 mel.eval('FBXExportSmoothingGroups -v true;') mel.eval('FBXExportTriangulate -v false;') mel.eval('FBXExportSmoothMesh -v false;') mel.eval('FBXExportUpAxis {};'.format(self.conf.upaxis)) print(f'FBXExport -s -f "{self.conf.exportFile}";') mel.eval(f'FBXExport -s -f "{self.conf.exportFile}";') try: cmds.undo() except RuntimeError as RE: # 没有更多可撤销的命令 pass # 结束FBX导出 return def riz_export(self, use_script=True, load_model=True): if self.link and self.cbx_use_link.isChecked(): print("Rizom链接版本", self.link.Version()) self.exported_objects = cmds.ls(selection=True, tr=True) # FBX导出 self.fbx_export() if not self.port: self.riz_run() params = { "File.Path": self.conf.exportFile, "File.XYZUVW": True, # 加载3D+UV数据(使用File.XYZ仅加载3D数据) "File.UVWProps": True, # 加载UV属性(如固定、纹理密度设置等) "File.ImportGroups": True, # 加载岛组层级 "__Focus": True, # 在视口中聚焦加载的网格 } self.link.Load(params) if DEBUG: print("<RIZOM> 导出至:", self.conf.exportFile) # 日志汉化 cmds.select(self.exported_objects) # 启用导入按钮(如果之前禁用) self.btn_import.setEnabled(True) else: # 传统方法 # print("<RIZOM> 正在导出模型") # 日志汉化 self.cleanse_namespaces() # 强制清理 self.exported_objects = cmds.ls(selection=True, tr=True) if not self.exported_objects: return False # 删除历史记录(防止存在空组被此操作移除) # 否则导入时会被清除,导致对象计数不匹配 cmds.bakePartialHistory() cmd = '' # 导出选项 if load_model: if self.cbx_keepuv.isChecked(): cmd += 'ZomLoad({File={Path="'+self.conf.exportFile+'", ImportGroups=true, XYZUVW=true, UVWProps=true}})\n' else: cmd += 'ZomLoad({File={Path="'+self.conf.exportFile+'", ImportGroups=true, XYZ=true}, NormalizeUVW=true})\n' # 添加脚本 if self.combo_scripts.currentIndex() and use_script is True: script_name = scriptlist.scripts[self.combo_scripts.currentIndex()-1][0] script_path = os.path.join(os.path.dirname(__file__), 'lua_scripts/%s' % script_name) with open(script_path, 'r') as lua_script: cmd += lua_script.read() if DEBUG: print("<RizomUV桥接工具>", cmd) # 日志汉化 # FBX导出 self.fbx_export() if DEBUG: print("<RIZOM> 导出至:", self.conf.exportFile) # 日志汉化 cmds.select(self.exported_objects) self.write_to_lua_file(cmd) self.btn_import.setEnabled(True) # 如果有显著更改,将配置写入磁盘 if self.config_updated == True: self.conf.save_xml() return True def riz_import(self): if not os.path.exists(self.conf.exportFile): om.MGlobal.displayError(f"无法找到导出文件: {self.conf.exportFile}") # 错误提示汉化 self.btn_import.setEnabled(False) if self.cbx_use_link.isChecked(): if self.link: try: self.link.Save({"File.Path": self.conf.exportFile}) except RuntimeError as RE: cmds.error('无法通过Python链接向Rizom发送保存命令。导出时是否启用了链接?') # 错误提示汉化 # FBX导入 namespace = ':RIZOMUV' if not cmds.namespace(ex=namespace): cmds.namespace(add=namespace) cmds.namespace(set=namespace) mel.eval('FBXImportMode -v add;') mel.eval(f'FBXImport -f "{self.conf.exportFile}";') # 结束FBX导入 imported_objects = cmds.ls('RIZOMUV:*', long=True, type="transform") original_matches = [] for riz_obj in imported_objects: print("导入的对象名称", riz_obj) # 日志汉化 original = riz_obj.replace('RIZOMUV:', '') original_matches.append(original) # 列出每个项目的UV集,无UV集则跳过(排除组节点等对象) original_uvsets = cmds.polyUVSet(original, allUVSets=True, q=True) imported_uvsets = cmds.polyUVSet(riz_obj, allUVSets=True, q=True) if original_uvsets: # 检查名称 # if self.cbx_fix_set_names.isChecked(): for i in range(len(original_uvsets)): try: if not original_uvsets[i] == imported_uvsets[i]: cmds.polyUVSet(riz_obj, rename=True, uvSet=imported_uvsets[i], newUVSet=original_uvsets[i]) except IndexError: # 可能因Maya奇怪的bug导致(polyUVSet命令列出的UV集数量与UV集编辑器中不同) print("UV集索引错误。对象的UV集数量似乎不匹配") # 日志汉化 print("原始UV集:", original_uvsets, original) print("导入的UV集:", imported_uvsets, riz_obj) pass try: cmds.polyTransfer(original, ao=riz_obj, ch=False, uv=True) except RuntimeError as rt: print(f"<RizomUV桥接工具> 无法从{riz_obj}向{original}传输UV") # 日志汉化 if DEBUG: print(f"<RizomUV桥接工具> 从{riz_obj}向{original}传输UV") # 日志汉化 cmds.select(original_matches) cmds.bakePartialHistory() cmds.delete(':RIZOMUV:*') cmds.namespace(rm=':RIZOMUV') return def browse_settings_location(self): os.startfile(os.path.dirname(self.conf.config_file_path)) def ui_pack_update_labels(self): print("值已更改") # 日志汉化 self.label_uvmap.setText(str(self.slider_pack_uvmap.value())) def ui_update_uvchannels(self): sel_obj = cmds.ls(sl=True, tr=True) if not sel_obj: self.combo_pack_uvset.clear() return uvsets = cmds.polyUVSet(sel_obj[0], allUVSets=True, q=True) current_set = cmds.polyUVSet(sel_obj[0], cuv=True, q=True) if uvsets: print(uvsets) self.combo_pack_uvset.clear() self.combo_pack_uvset.addItems(uvsets) self.combo_pack_uvset.setCurrentIndex(uvsets.index(current_set[0])) def cleanse_namespaces(self): """ 第一步 -- 尝试删除所有现有RIZOMUV命名空间直到失败,这应该能清除像 RIZOMUV:RIZOMUV:RIZOMUV这样的嵌套实例 """ fail = False while(not fail): try: cmds.namespace(rm=':RIZOMUV', mnr=True) except: fail = True """ 第二步 -- 在某些场景中,命名空间可能被重命名为RIZOMUV1、RIZOMUV2、RIZOMUV3等 因此需要查找并删除这些残留 """ """ 第二步(更新)-- 尝试删除除RIZOM之外的其他命名空间,因为存在其他命名空间可能导致导入失败 """ c = cmds.listRelatives(ad=True) if not c: return for obj in c: ns_split = obj.split(':') if len(ns_split)>1: result = cmds.confirmDialog( m="选中的对象已分配命名空间。\n" # 对话框文本汉化 "使用工具前必须移除这些命名空间\n" "是否为您删除?(包括未选中的对象)\n\n" "对象上的命名空间:\n%s" % ns_split[0], button=['移除', '消'] # 按钮文本汉化 ) if result == '移除': cmds.namespace(rm=ns_split[0], mnr=True) else: return return def write_to_lua_file(self, command): with open(self.conf.rizom_script_path, 'w') as f: f.write(command) print("<RIZOM> 已将命令写入lua文件:", self.conf.rizom_script_path) # 日志汉化 for line in command.split("\n"): print("\t", line) return def set_config(self): self.conf.loaduvs = self.cbx_keepuv.isChecked() if self.radioAxisY.isChecked(): self.conf.upaxis = "Y" else: self.conf.upaxis = "Z" self.conf.mutations = self.dspin_pack_mutations.value() self.conf.resolution = self.dspin_pack_resolution.value() self.conf.margin = self.dspin_pack_margin.value() self.conf.spacing = self.dspin_pack_spacing.value() self.conf.autofit = self.cbx_layout_scaling.isChecked() self.conf.fixuvnames = self.cbx_fix_set_names.isChecked() self.conf.useuvlink = self.cbx_use_link.isChecked() self.config_updated = True self.conf.save_xml() def closeEvent(self, event): self.conf.save_xml() def GetMayaWidget(): """ 返回Maya主窗口部件的Python对象 """ # 注释汉化 main_window_ptr = omui.MQtUtil.mainWindow() if sys.version_info.major >= 3: return wrapInstance(int(main_window_ptr), QtWidgets.QWidget) else: return wrapInstance(long(main_window_ptr), QtWidgets.QWidget) def fix_shell_border_normals(): obj_list = cmds.ls(sl=True, o=True) all_final_borders = [] for sub_obj in obj_list: cmds.select(sub_obj, r=True) cmds.polyNormalPerVertex(ufn=True) cmds.polySoftEdge(sub_obj, a=180, ch=1) print("全部软化") # 日志汉化 # 选择对象UV cmds.select(sub_obj + '.map[*]') mel.eval('polySelectBorderShell 1;') uv_border = cmds.polyListComponentConversion(te=True, internal=True) uv_border = cmds.ls(uv_border, fl=True) final_border = [] # 特殊过滤 for curEdge in uv_border: edge_uvs = cmds.polyListComponentConversion(curEdge, tuv=True) edge_uvs = cmds.ls(edge_uvs, fl=True) if len(edge_uvs) > 2: final_border.append(curEdge) cmds.polySoftEdge(final_border, a=0, ch=1) all_final_borders.append(final_border) cmds.select(cl=True) for sel_l in all_final_borders: cmds.select(sel_l, add=True) cmds.hilite(obj_list) def run(): scriptJobs = cmds.scriptJob(listJobs=True) for sj in scriptJobs: if "RizomBridge" in sj: print(PRNT_STRING, f"终止已存在的scriptJob: {sj}") # 日志汉化 cmds.scriptJob(kill=int(sj.split(':')[0])) d = RizomUVBridgeWindow() d.show(dockable=True) if __name__ == "__main__": run()
最新发布
11-02
<think>我们正在处理一个关于PySide6中将.ui文件转换为.py文件的问题。根据用户提供的引用,我们可以总结出以下关键点: 1. 引用[1]提到一个脚本,它使用任意找到的uic命令转换ui文件,并将导入模块改为qtpy(一个通用库)。但用户使用的是PySide6,所以我们不需要改为qtpy,除非有跨Qt绑定的需求。 2. 引用[2]提到在PyCharm中配置PySide6的快捷方式,其中有一个是PySide6_Designer(用于设计UI),但没有直接提到转换命令。 3. 引用[3]介绍了PySide6的背景。 4. 引用[4]提到安装PySide6和PyQt5,但用户可能只需要PySide6。 5. 引用[5]提到转换后的.py文件中文乱码问题,说明转换过程中可能会遇到编码问题。 在PySide6中,将.ui文件转换为.py文件通常使用`pyside6-uic`命令行工具。具体步骤如下: ### 步骤: 1. **确保已安装PySide6**:在终端中运行`pip install PySide6`(如果已经安装,则跳过)。 2. **使用`pyside6-uic`命令转换**: - 打开终端(或命令提示符/PowerShell)。 - 使用以下命令格式: ``` pyside6-uic input.ui -o output.py ``` 其中`input.ui`是输入的UI文件路径,`output.py`是输出的Python文件路径。 ### 示例: 假设我们有一个名为`mainwindow.ui`的文件,想要转换为`ui_mainwindow.py`,则命令为: ```bash pyside6-uic mainwindow.ui -o ui_mainwindow.py ``` ### 注意: - 转换后的文件通常会包含一个用于设置UI的类(如`Ui_MainWindow`),你可以在自己的代码中继承并初始化这个类。 - 关于引用[5]中提到的中文乱码问题:在转换后的文件中,字符串可能会以Unicode转义序列的形式出现(如`u"\u767b\u5f55\u6846"`)。这是正常的,因为Qt使用Unicode字符串。这些字符串在运行时会被正确显示为中文。如果你希望转换后的文件中直接显示中文,可以尝试以下方法: - 在转换命令中加入`--from-imports`选项(PySide6uic工具可能没有这个选项,但PyQt的有,PySide6uic命令参数可能与PyQt的uic不完全相同,需验证)。 - 或者,在转换后手动修改文件,将Unicode转义序列改为中文字符(注意文件编码需为UTF-8)。 - 另外,可以尝试在转换命令中指定编码(如`--encoding utf-8`),但PySide6uic工具可能默认就是UTF-8。 ### 在Python代码中动态加载.ui文件(无需转换): 除了转换为.py文件,PySide6也支持在运行时直接加载.ui文件,使用`QUiLoader`类。示例代码如下: ```python from PySide6.QtWidgets import QApplication from PySide6.QtUiTools import QUiLoader import sys app = QApplication(sys.argv) loader = QUiLoader() window = loader.load("mainwindow.ui") # 加载UI文件 window.show() sys.exit(app.exec()) ``` 这种方法不需要转换步骤,但可能会稍微增加运行时开销。 ### 总结: 用户的主要需求是将.ui文件转换为.py文件,使用`pyside6-uic`命令是最直接的方法。如果遇到中文乱码问题,可以按照上述建议处理。 §§相关问题§§ 1. 如何解决PySide6转换后的.py文件中中文显示为Unicode转义序列的问题? 2. 除了使用命令行工具,还有其他方法将.ui文件转换为.py文件吗? 3.PySide6中,动态加载.ui文件和转换为.py文件各有什么优缺点? 4. 如何配置PyCharm以方便地使用PySide6uic工具?</think>在PySide6中将`.ui`文件转换为`.py`文件,可以通过以下步骤实现: ### 方法1:使用命令行工具 1. **安装PySide6**(如未安装): ```bash pip install PySide6 ``` 2. **执行转换命令**: ```bash pyside6-uic input.ui -o output.py ``` - `input.ui`: 输入的Qt Designer文件 - `output.py`: 生成的Python文件 - 示例:`pyside6-uic mainwindow.ui -o ui_mainwindow.py` ### 方法2:在Python代码中动态转换 ```python from PySide6.QUiTools import QUiLoader loader = QUiLoader() window = loader.load("your_ui_file.ui") # 加载UI文件 window.show() ``` ### 中文乱码解决方案 如果转换后出现中文Unicode转义(如`u"\u767b\u5f55"`),可通过以下方式修复: ```python # 在生成的.py文件中修改 QCoreApplication.translate("Form", "登录", None) # 直接使用中文字符 ``` > 确保文件保存为**UTF-8编码**[^5] ### 配置PyCharm快捷方式(可选) 1. 添加外部工具: - **名称**: PySide6-UIC - **程序**: `pyside6-uic` - **参数**: `$FileName$ -o ui_$FileNameWithoutExtension$.py` - **工作目录**: `$ProjectFileDir$` 2. 右键点击`.ui`文件 → `External Tools` → 选择配置好的工具 ### 注意事项 1. 转换后的文件会生成`Ui_ClassName`类,需在代码中继承使用: ```python class MainWindow(QMainWindow, Ui_MainWindow): def __init__(self): super().__init__() self.setupUi(self) # 初始化UI ``` 2. PySide6uic工具与PyQt5的`pyuic5`不兼容,需使用`pyside6-uic`[^3]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值