关于QT程序进入到新QWidget无法弹出Toas或Dialog的问题

前言

今天算是碰到个轻量级但却棘手的问题。在一个QT程序中,我要通过一个QWidget A进入到另一个QWidget B,进入的方式如下:在A中先new QWidget B对象,当点击A中的某个按钮的时候,在B.show的同时,要通过槽函数去给B中的变量赋值,同时在槽函数中会弹一个toast或者一个用widget写的类dialog(在构造函数中设置setWindowModality(Qt::ApplicationModal))。代码如下:

A中代码:

B中代码:

然而,奇怪的事情发生了,我的wd不显示,按理说,wd就这么几行代码,没理由进行不下去啊。周周转转了将近一下午的时间,最后找到问题的根源了。就是A代码中的emit和show的顺序颠倒了。因为toast或者dialog显示要依赖于一个QWidget,当QWidget还没有show的时候,toast 弹窗也无法显示出来。即使你通过槽函数调用了 toast 的显示函数,但由于 QWidget 还没有被加入到窗口系统的窗口树中,弹窗也不会被正确渲染出来,还可能会导致程序崩溃

解决办法

先show再emit即可,代码如下:

So easy!!! So hard!!!

#ldtui文件夹中有两个.py 1.__init__.py """ .. module:: ldtui :synopsis: Main tools UI. .. moduleauthor:: Ezequiel Mastrasso """ from Qt import QtGui, QtWidgets, QtCore from Qt.QtWidgets import QApplication, QWidget, QLabel, QMainWindow import sys import imp import os import logging from functools import partial from ldtui import qtutils import ldt logger = logging.getLogger(__name__) class LDTWindow(QMainWindow): '''Main Tools UI Window. Loads the plugInfo.plugin_object.plugin_layout QWidget from all loaded plugins as tabs''' def __init__(self, plugins): super(LDTWindow, self).__init__() self.setWindowTitle("Look Dev Tool Set") self.setGeometry(0, 0, 650, 600) layout = QtWidgets.QGridLayout() self.setLayout(layout) tabwidget = QtWidgets.QTabWidget() tabwidget.setTabBar(qtutils.HTabWidget(width=150, height=50)) tabwidget.setTabPosition(QtWidgets.QTabWidget.West) # Stylesheet fix for Katana # With default colors, the tab text is almost the # same as the tab background stylesheet = """ QTabBar::tab:unselected {background: #222222;} QTabWidget>QWidget>QWidget{background: #222222;} QTabBar::tab:selected {background: #303030;} QTabWidget>QWidget>QWidget{background: #303030;} """ tabwidget.setStyleSheet(stylesheet) layout.addWidget(tabwidget, 0, 0) plugins_ui = {} plugins_buttons = {} for pluginInfo in plugins.getAllPlugins(): tabwidget.addTab( pluginInfo.plugin_object.plugin_layout, pluginInfo.name) self.setCentralWidget(tabwidget) 2.qtutils.py """ .. module:: qtutils :synopsis: small qt utilies and custom widgets. .. moduleauthor:: Ezequiel Mastrasso """ from Qt import QtGui, QtWidgets, QtCore from Qt.QtWidgets import QApplication, QWidget, QLabel, QMainWindow import logging logger = logging.getLogger(__name__) def get_folder_path(): """Gets a folder path from the user""" file_dialog = QtWidgets.QFileDialog() file_dialog.setFileMode(QtWidgets.QFileDialog.Directory) if file_dialog.exec_(): path = str(file_dialog.selectedFiles()[0]) return path else: return None class HTabWidget(QtWidgets.QTabBar): ''' QPaint event to draw the QTabWidget titles horizontally ''' def __init__(self, *args, **kwargs): self.tabSize = QtCore.QSize(kwargs.pop('width'), kwargs.pop('height')) super(HTabWidget, self).__init__(*args, **kwargs) def paintEvent(self, event): painter = QtWidgets.QStylePainter(self) option = QtWidgets.QStyleOptionTab() for index in range(self.count()): self.initStyleOption(option, index) tabRect = self.tabRect(index) tabRect.moveLeft(10) painter.drawControl(QtWidgets.QStyle.CE_TabBarTabShape, option) painter.drawText(tabRect, QtCore.Qt.AlignVCenter | QtCore.Qt.TextDontClip, self.tabText(index)) def tabSizeHint(self, index): return self.tabSize #ldtutils文件夹中有一个文件 1.__init__.py """ .. module:: ldtutils :synopsis: general non dcc specific utils. .. moduleauthor:: Ezequiel Mastrasso """ from ldtcommon import CONFIG_MATERIALS_JSON from ldtcommon import TEXTURE_CHANNEL_MATCHING_RATIO from ldtcommon import TEXTURE_MATCHING_RATIO from fuzzywuzzy import fuzz import subprocess import multiprocessing import sys import json import logging import os import random import lucidity logger = logging.getLogger(__name__) def create_commands(texture_mapping): default_command = "maya -batch -file someMayaFile.mb -command " commands = [] for key, value in texture_mapping: dir, filename = os.path.split(key) filename, ext = os.path.splitext(filename) filename = os.path.join(dir, filename + "WithTexture." + ext) commands.append("".format(default_command, "abc_file", key, "texture", value, "file -save ", filename)) return commands def launch_function(func, args): commands = create_commands(args) launch_multiprocess(launch_subprocess, commands) def launch_subprocess(command): try: subprocess_output = subprocess.check_output(command) logger.info("Subprocess launched\t{out}\nrunning the command\t{command}", out=subprocess_output, command=command) except subprocess.CalledProcessError as e: logger.exception( "Error while trying to launch subprocess: {}".format(e.output)) raise return command def launch_multiprocess(function, args): """ :param function: Function to be called inside the multiprocess -- Takes only 1 arg :param args: list/tuple of arguments for above function :return: """ multiprocessing.freeze_support() pool = multiprocessing.Pool(processes=int(multiprocessing.cpu_count()/2)) logger.debug("Pool created") try: pool_process = pool.map_async(function, (args)) except Exception as e: msg = "Error while trying to launch process in pool: {}".format(e) logger.exception(msg) raise finally: pool.close() pool.join() try: logger.info("output from the process: {pool_out}", out=pool_process.successful()) return 0 except AssertionError: logger.exception("Couldn't communicate with the process poll created; \ No output from processes fetched") return 1 def map_textures_to_alembic(texture_mapping): launch_subprocess(command) def load_json(file_path): """ Load a json an returns a dict. Args: file_path (str): Json file path to open. """ with open(file_path) as handle: dictdump = json.loads(handle.read()) return dictdump def save_json(file_path, data): """ Dump a dict into a json file. Args: file_path (str): Json file path to save. data (dict): Data to save into the json file. """ # TODO (eze) pass def get_random_color(seed): """ Return a random color using a seed. Used by all material creating, and viewport color functions that do not use textures, to have a common color accross dccs Args: seed (str): Returns: tuple, R,G,B colors. """ random.seed(seed + "_r") color_red = random.uniform(0, 1) random.seed(seed + "_g") color_green = random.uniform(0, 1) random.seed(seed + "_b") color_blue = random.uniform(0, 1) return color_red, color_green, color_blue def create_directoy(path): """ Create a folder. Args: path (str): Directory path to create. """ os.mkdir(path) logger.info("Directory created: %s" % path) def is_directory(path): """ Check if the given path exists, and is a directory. Args: path (str): Directory to check. """ if os.path.exists(path) and os.path.isdir(path): return True else: return False def get_files_in_folder(path, recursive=False, pattern=None): """ Search files in a folder. Args: path (str): Path to search. Kwards: recursive (bool): Search files recursively in folder. pattern (str): pattern to match, for ie '.exr'. Returns: array. File list """ logger.info("Searching for files in: %s" % path) logger.info("Searching options: Recursive %s, pattern: %s" % (recursive, pattern)) file_list = [] for path, subdirs, files in os.walk(path): for file in files: # skip .mayaswatchs stuff if ".maya" not in file: if pattern: if pattern in file: file_list.append(os.path.join(path, file)) logger.debug( "File with pattern found, added to the list: %s" % file) else: file_list.append(os.path.join(path, file)) logger.debug("File added to the list: %s" % file) if not recursive: break return file_list def string_matching_ratio(stringA, stringB): """ Compare two strings and returns a fuzzy string matching ratio. In general ratio, partial_ratio, token_sort_ratio and token_set_ratio did not give different results given that we are comparin a single. TODO: Try bitap algorithm for fuzzy matching, partial substring matching might be better for our cases. Different channels fuzzy ratio comparission ('baseColor','diffusecolor') = 67 ('base','diffusecolor') = 25 ('specular','specularColor') = 76 ('specular','specularcolor') = 76 ('specular_color', 'specular_bump') = 67 ('coat_color', 'coat_ior') = 78 ('secondary_specular_color', 'secondary_specular_ior') = 91 ('subsurface_weight', 'subsurface_Color') = 67 ('emission', 'emission_weight') = 70 Same channel diferent naming ratio comparission ('diffuse_weight','diffuseGain') = 64 Args: stringA (str): string to compare against. stringB (str): string to compare. Returns: int. Ratio, from 0 to 100 according to fuzzy matching. """ return fuzz.token_set_ratio(stringA, stringB) def get_config_materials(): """ Gets the CONFIG_MATERIALS_JSON as a dict Returns: dict. CONFIG_MATERIALS_JSON """ return load_json(CONFIG_MATERIALS_JSON) 你看看
最新发布
08-22
根据你提供的 `ldtui` 文件夹中的 `__init__.py` 和 `qtutils.py`,以及 `ldtutils` 中的 `__init__.py`,我可以看出这是一个 Maya 插件项目,主要功能是创建一个 UI 窗口,加载插件的 Tab 界面,并提供一些 Qt 工具和通用工具函数。 --- ## ❗当前你遇到的错误: ``` # Error: AttributeError: file <maya console> line 6: module 'ldt.ldtui' has no attribute 'show_gui' ``` 这个错误表明你在调用: ```python ldt.ldtui.show_gui() ``` 但模块中并没有定义 `show_gui()` 函数。 --- ## ✅ 解决方案 你需要在 `ldt/ldtui/__init__.py` 中添加 `show_gui()` 函数。当前的代码中只定义了 `LDTWindow` 类,但没有提供一个函数来创建并显示这个窗口。 ### ✅ 修改 `ldt/ldtui/__init__.py`,添加如下函数: ```python def show_gui(): from ldt import plugins # 确保你有 plugins 模块 from maya import OpenMayaUI as omui from shiboken2 import wrapInstance # 获取 Maya 主窗口作为父窗口 maya_main = wrapInstance(int(omui.MQtUtil.mainWindow()), QtWidgets.QWidget) # 加载插件 plugin_manager = plugins.PluginManager() plugin_manager.load_plugins() # 创建窗口并显示 window = LDTWindow(plugin_manager) window.setParent(maya_main) window.show() ``` > 注意:你必须确保你有 `ldt/plugins.py` `ldt.plugins.PluginManager` 这个模块,否则会报错。 --- ## 🧪 示例:如何调用这个函数 在 Maya 的 Script Editor 中运行: ```python import sys # 可选:添加路径 # sys.path.append(r'C:\Users\Long\Documents\maya\scripts') import importlib import ldt.ldtui importlib.reload(ldt.ldtui) ldt.ldtui.show_gui() ``` --- ## 🧩 补充说明 ### 1. `LDTWindow` 类说明 - 这是一个继承自 `QMainWindow` 的主窗口类 - 从插件系统中获取所有插件的 UI 界面(`plugin_layout`) - 使用 `QTabWidget` 展示为多个 Tab 页 - 使用了自定义的 `HTabWidget`(在 `qtutils.py` 中) ### 2. `HTabWidget` 类说明 - 继承自 `QTabBar`,用于自定义 Tab 的绘制样式 - `paintEvent()` 方法自定义了 Tab 的外观 - `tabSizeHint()` 设置了每个 Tab 的大小 --- ## 📁 项目结构建议 确保你的项目结构如下: ``` C:\Users\Long\Documents\maya\scripts\ └── ldt/ ├── __init__.py ├── plugins.py # 你需要这个文件来实现插件系统 └── ldtui/ ├── __init__.py └── qtutils.py ``` --- ## 🔧 附加建议 ### 如果你没有 `plugins.py`,可以创建一个简单的插件系统示例: #### `ldt/plugins.py` ```python class PluginInfo: def __init__(self, name, plugin_object): self.name = name self.plugin_object = plugin_object class PluginManager: def __init__(self): self.plugins = [] def load_plugins(self): # 示例插件 from Qt import QtWidgets widget = QtWidgets.QWidget() layout = QtWidgets.QVBoxLayout() label = QtWidgets.QLabel("This is a plugin tab") layout.addWidget(label) widget.setLayout(layout) self.plugins.append(PluginInfo("Example Plugin", type('PluginObject', (), {'plugin_layout': widget}))) def getAllPlugins(self): return self.plugins ``` --- ## ✅ 总结 | 问题 | 解决方法 | |------|----------| | 没有 `show_gui()` 函数 | 在 `ldt/ldtui/__init__.py` 中添加该函数 | | 插件系统实现 | 实现 `plugins.py` 插件管理器 | | Maya 无法找到模块 | 使用 `sys.path.append()` 添加路径 | | 模块加载 | 使用 `importlib.reload()` | | 插件界面无法显示 | 确保 `plugin_layout` 是有效的 `QWidget` | --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值