Python Tools - Session 12A
Qt Template UI with Button Callbacks
2020.03.31 - Session 12A
Session Navigation
Overview
This session introduces a reusable Qt template for building Maya tool UIs. Using PySide2's QUiLoader, we load a .ui file created in Qt Designer and wire up button click callbacks to Python methods. The template demonstrates how to query checkbox, text field, and slider values from the UI, and includes a run() function pattern for managing the UI lifecycle.
Key Concepts
- Loading .ui files with QUiLoader - Load Qt Designer layouts at runtime using PySide2
- Signal-slot connections - Wire button clicks to Python callback methods
- UI value queries - Read checkboxes, text fields, and slider values from widgets
- QDialog lifecycle - Use a
run()function to close existing instances before creating new ones - Maya window parenting - Parent Qt dialogs to the main Maya window via OpenMayaUI
Note
This session uses a companion template_ui.ui file created in Qt Designer. The .ui file defines the visual layout (checkbox, text field, slider, and button).
Source Code - template_ui.py
"""
#############################################################################
filename template_ui.py
author [author]
course [course]
Brief Description:
Qt Template UI
To be used in conjunction with "template_ui.ui" - place them next to each other
Session 12A - Mar 31 2020
#############################################################################
"""
import pymel.core as pm
import os
from PySide2 import QtCore
from PySide2 import QtWidgets
from PySide2 import QtUiTools
from shiboken2 import wrapInstance
import maya.OpenMayaUI as omui
def get_maya_window():
"""Return the main Maya window
"""
main_window_ptr = omui.MQtUtil.mainWindow()
return wrapInstance(long(main_window_ptr), QtWidgets.QWidget)
def get_script_dir():
"""Returns the directory where the current script lives
"""
script_file = os.path.abspath(__file__)
return os.path.dirname(script_file)
class TemplateUI(QtWidgets.QDialog):
def __init__(self, parent=get_maya_window()):
# Run the initialization on the inherited QDialog class
super(TemplateUI, self).__init__(parent)
# Set the window title
self.setWindowTitle('Shape Creator')
# Assemble the file path for the ui file
ui_file_path = os.path.join(get_script_dir(), 'template_ui.ui')
# Creat a QFile object form the file path
qfile_object = QtCore.QFile(ui_file_path)
# Open the QFile object
qfile_object.open(QtCore.QFile.ReadOnly)
# Create a QUI Loader
loader = QtUiTools.QUiLoader()
# Load the file as save it to a property
self.ui = loader.load(qfile_object, parentWidget=self)
self.ui.btnCreateShape.clicked.connect(self.print_values)
# Close the file handle
qfile_object.close()
# Show the UI
self.show()
def print_values(self):
"""Sample method that gets triggered from the button
All we do here is print some of the value from the UI
"""
# Get the values from the UI
checkbox = self.ui.chkTestCheckbox.isChecked()
text = self.ui.txtTestText.text()
number = int(self.ui.sldTestSlider.value())
# Print the values out to the script editor
print ('CheckBox = %s Text = "%s" Number = %i' %(checkbox, text, number))
def run():
"""Checks to see if the UI exists, and closes it
"""
# Run through every qt widget active inside Maya
for ui_item in QtWidgets.qApp.allWidgets():
# If we find a widget whose name matches our class
if type(ui_item).__name__ == 'TemplateUI':
# Close it
ui_item.close()
# Finally, always create an instance of the UI
TemplateUI()