If you were writing your own Qt application from scratch, you would need to create your own QCoreApplication or QApplication instance to handle your application's event loop. When writing a Maya plug-in, you must instead use Maya's own application object which can be retrieved using Qt's qApp macro. The example code below uses the qApp macro to retrieve Maya's application name:
QCoreApplication* app = qApp;
if (app) {
cout << "Application name is '" << app->applicationName().toStdString() << "'" << endl;
}
Creating new windows and dialogs using Qt is done the same way as you would if you were writing a standalone Qt application. The helixQtCmd plug-in in the Developer Kit gives a very simple example of this. The plug-in provides the helixQt command which creates a Qt-based button. Whenever the button is pressed it uses API calls to create a helical curve within Maya.
The button is a regular Qt pushButton with a createHelix() slot added to handle the creation of the curve.
class HelixButton : public QPushButton
{
Q_OBJECT
public:
HelixButton(const QString& text, QWidget* parent = 0);
virtual ~HelixButton();
public slots:
void createHelix(bool checked);
};
Whenever the helixQt command is executed, it first checks to see if the button already exists. If not then it creates the button and connects its clicked signal to its createHelix slot, so that whenever the button is clicked the code to create the helix will be executed:
QPointer HelixQtCmd::button;
MStatus HelixQtCmd::doIt(const MArgList& /* args */)
{
if (button.isNull()) {
button = new HelixButton("Create Helix");
button->connect(button, SIGNAL(clicked(bool)), button, SLOT(createHelix(bool)));
button->show();
}
If the button already exists, then the command simply ensures that it is visible and not hidden beneath other windows:
else {
button->showNormal();
button->raise();
}
return MS::kSuccess;
}
Controls created directly using Qt are not in general recognized by Maya's UI commands. The IsUI
command does not list them and the commands for specific types of controls, such as button
, do not recognize them. The generic control command is an exception, though. So long as the control has been given a unique name, then the control
command can be used to test for its existence and perform basic operations on the control such as setting its visibility.
For example, if the createHelix method of the helixQtCmd plug-in had given the button the unique name of "myButton":
button = new HelixButton("Create Helix");
button->setObjectName("myButton");
then the following MEL script could be used to hide the button:
if (`control -q -exists myButton`) {
control -e -visible false myButton;
}
However, the same code using the button
command would not work because button
only recognizes those buttons which it has created:
if (`button -q -exists myButton`) { // Will always be false.
button -e -visible false myButton; // Will never be executed.
}
It may sometimes be desirable to use Qt to directly access UI elements created using Maya commands. The MQtUtil
API class provides methods for retrieving the Qt object underlying a Maya control, layout, window or menu item. For example, if you have a Maya checkBox control named "myCheckBox" which was created with the following MEL script:
window;
columnLayout;
checkBox myCheckBox;
showWindow;
You can use the MQtUtil
class to retrieve the checkBox's QWidget pointer, and from that determine the current state of the checkBox:
QWidget* control = MQtUtil::findControl("myCheckBox");
if (control) {
QCheckBox* cb = qobject_cast(control);
if (cb) {
if (cb->isChecked()) {
MGlobal::displayInfo("myCheckBox is checked");
} else {
MGlobal::displayInfo("myCheckBox is not checked");
}
}
}
The example above also serves to illustrate why you must always be careful using MQtUtil. The code will only work if Maya's checkbox
command creates a QCheckBox widget or something derived from QCheckBox. While that may be the case in the current version of Maya, it could change in some future version. If you write code which uses Qt to directly access UI elements created using Maya commands, then it is up to you to ensure that your code still behaves as expected in each new release of Maya.
Layouts are an even greater minefield of potential problems:
MQtUtil
provides some methods to make navigating through layouts easier, but keeping track of the proxy versus the actual layout can still be challenging for the plug-in writer and a common source of bugs.MQtUtil
provides methods to help in navigating these complex layouts, but care must be taken.See MQtUtil
for a more in-depth discussion of these and other issues surrounding layouts.