Maya Pyside2 UI,无法让 QPushButton 与同一类中的函数连接

Posted

技术标签:

【中文标题】Maya Pyside2 UI,无法让 QPushButton 与同一类中的函数连接【英文标题】:Maya Pyside2 UI, couldn't get QPushButton to connect with function within the same class 【发布时间】:2019-05-11 15:36:14 【问题描述】:

我正在尝试使用 Pyside2 为 Maya 编写 UI,但由于某种原因,我无法将 QPushButton 与同一类中的函数连接起来。

在这种情况下,我编写了一个带有 1 个按钮的简单 UI,以在同一类中触发 template_btnCmd。

谢谢。

import pymel.core as pm ;
import maya.OpenMayaUI as mui ;
from PySide2 import QtCore , QtGui , QtWidgets ;
from shiboken2 import wrapInstance ;

class Gui ( object ) :

    def __init__ ( self ) :
        super ( Gui , self ).__init__() ;

        self.ui = 'template_uiE' ;
        self.w = 500.00 ;
        self.h = 300.00 ;

    def deleteUI ( self , ui ) :
        if pm.window ( ui , ex = True ) :
            pm.deleteUI ( ui ) ;
            self.deleteUI ( ui ) ;

    def show ( self ) :

        self.deleteUI ( self.ui ) ;

        # Pointer
        mayaMainWindow_ptr = mui.MQtUtil.mainWindow();
        mayaMainWindow = wrapInstance(long(mayaMainWindow_ptr), QtWidgets.QWidget);
        self.mayaMainWindow_ptr = mayaMainWindow_ptr;
        self.mayaMainWindow = mayaMainWindow;

        window = QtWidgets.QWidget(parent=mayaMainWindow);
        self.window = window;
        window.setObjectName(self.ui);
        window.resize(self.w, self.h);
        window.setWindowFlags(QtCore.Qt.Window);

        main_QHBoxLayout = QtWidgets.QHBoxLayout(window);
        main_QHBoxLayout.setObjectName('main_QHBoxLayout_uiE');
        self.main_QHBoxLayout = main_QHBoxLayout;

        ### Grid Layout
        button_QPushButton = QtWidgets.QPushButton() ;
        button_QPushButton.setObjectName ( 'button_QPushButton_uiE' ) ;
        button_QPushButton.setText ( 'Template Button' ) ;
        button_QPushButton.clicked.connect ( self.template_btnCmd ) ;
        # --> Insert
        main_QHBoxLayout.addWidget ( button_QPushButton ) ;

        window.show() ;

    def template_btnCmd ( self ) :
        print ( 'This is working...?' ) ;

def run ( *args ) :

    gui = Gui() ;
    gui.show() ;

run() ;

【问题讨论】:

以防万一,python 在行尾不需要分号。 【参考方案1】:

所以我设法运行了该命令。我没有直接将函数连接到 QPushButton,而是使用嵌套函数连接 QPushButton...

        button_QPushButton = QtWidgets.QPushButton() ;
        button_QPushButton.setObjectName ( 'button_QPushButton_uiE' ) ;
        button_QPushButton.setText ( 'Template Button' ) ;

        def template_btnCmd ( *args ) :
            self.template_btnCmd() ;

        button_QPushButton.pressed.connect ( template_btnCmd ) ;
        # --> Insert
        main_QHBoxLayout.addWidget ( button_QPushButton ) ;

我真的不知道这里发生了什么。我不觉得这是要走的路,这更像是一个鸭带解决方案。

如果有人能解释这里发生的事情,那就太好了。

谢谢!

【讨论】:

【参考方案2】:

最简单的解决方案是将您的 gui 变量设为全局变量:

def run ( *args ) :
    global gui
    gui = Gui() ;
    gui.show() ;

Qt 对象通常在没有内存占用时会被删除(例如在类中使用 self),所以我假设它会按照您创建它的方式删除一些连接。

这感觉像是一种创可贴,可能掩盖了一些主要问题,尤其是对于更复杂的界面。

通常,您的主类实际上应该从QObject 继承,主要是以下之一:QDialogQMainWindowQWidget。使用self 声明从QObject 继承的所有对象也很重要,因此它们成为实例变量并且可以在整个类中访问。否则,您可能会在垃圾回收期间删除对象,因为它不属于任何东西,Python 认为您已经完成了它。

最后会是这样的:

import pymel.core as pm
import maya.OpenMayaUI as mui
from PySide2 import QtCore
from PySide2 import QtGui
from PySide2 import QtWidgets
from shiboken2 import wrapInstance


class Gui(QtWidgets.QWidget):

    def __init__(self):
        self.ui = 'template_uiE'
        self.w = 500.00
        self.h = 300.00

        self.deleteGui(self.ui)

        # Pointer
        mayaMainWindow_ptr = mui.MQtUtil.mainWindow()
        mayaMainWindow = wrapInstance(long(mayaMainWindow_ptr), QtWidgets.QWidget)

        super(Gui, self).__init__(mayaMainWindow)

        self.setObjectName(self.ui)
        self.resize(self.w, self.h)
        self.setWindowFlags(QtCore.Qt.Window)

        # Grid Layout
        self.button_QPushButton = QtWidgets.QPushButton()
        self.button_QPushButton.setObjectName('button_QPushButton_uiE')
        self.button_QPushButton.setText('Template Button')
        self.button_QPushButton.clicked.connect(self.template_btnCmd)

        # --> Insert
        self.main_QHBoxLayout = QtWidgets.QVBoxLayout()
        self.main_QHBoxLayout.addWidget(self.button_QPushButton)
        self.setLayout(self.main_QHBoxLayout)

    def deleteGui(self, ui):
        if pm.window(ui, ex=True):
            pm.deleteUI(ui)

    def template_btnCmd(self):
        print 'This is working...?'


def run(*args):
    gui = Gui()
    gui.show()


run()

还有几句话关于编码标准:请坚持使用PEP8 或Google's coding standards。删除所有分号 (;),因为它非常非 Pythonic 并且看起来像冒号 (:),这非常令人困惑。缩小空白空间中的空白,因为它占用了不必要的空间并使其更难以阅读。不要将camelCase 与snake_case 命名混用,选择其中一个。当其他人难以阅读时,发展自己的风格毫无意义:D

【讨论】:

现在开始有意义了!谢谢!哦,哇,我从来不知道这些 PEP8 或 Google 的编码标准!我不是编程背景,对编码礼仪知之甚少。谢谢你的资源!

以上是关于Maya Pyside2 UI,无法让 QPushButton 与同一类中的函数连接的主要内容,如果未能解决你的问题,请参考以下文章

Maya PySide2 UI 获取 QLineEdit 值

使用 PySide2 开发 Maya 插件系列一:QT Designer 设计GUI, pyside-uic 把 .ui 文件转为 .py 文件

使用 PySide2 开发 Maya 插件系列二:继承 uic 转换出来的 py 文件中的类 Ui_Form

maya 独立与 pyside2

使用 PySide2 开发 Maya 插件系列三:qt语言国际化(internationalization)

Maya (PySide2) - 重新打开窗口而不是新窗口