|
There are some more interesting possibilities along these lines that people may be interested in trying out.
Interesting functions to explore
QtGui.qApp.allWidgets()
Returns all qt widgets of the motionbuilder interface, bit messy to work with thought so better to use.
QtGui.qApp.topLevelWidgets()
This returns all windows...like viewer window for example, the menu bar or more interestingly any FBTool window that has been shown.
So its possible to get a pointer to the qt widget representing the window of a FBTool and since any QWidget that you create can be parented into any other widget you can now after you have found your tool window parent in your qt gui into the FBTool that you created.
Seems that the pointers to the widgets are destroyed once the parent is hidden so unlike normal tools it becomes necessary to recreate the gui each time you show the window however that is easy enough to do with a callback to the tools OnShow event.
So i make this subclass of FBTool that i use for my qt based tools
from pyfbsdk import FBTool
from pyfbsdk_additions import AddTool
from PyQt4 import QtGui,QtCore
class QTool(FBTool):
def __init__(self, name, ui_class, register=True):
FBTool.__init__(self,name)
self.widget=None
self.__ui_=ui_class
if register:
AddTool(self)
self.OnShow.Add(self.build)
def build(self,inst,evt):
self.widget=None
for widget in QtGui.qApp.topLevelWidgets():
if widget.windowTitle()==self.Name:
self.widget=widget
break
if not self.widget:
raise RuntimeError('Unable to locate the QWidget representing this FBTool')
self.__ui_( self.widget )
Then i use designer to make my interfaces, signals etc and use the uic module to source the .ui files into python classes and then i create a interface class for that which will take care of running any pyfbsdk code based on existing or custom signals ive setup..could look something like this:
from YOUR_PACKAGE_HERE import QTool
from PyQt4 import uic, QtGui, QtCore
#-------------------------------------------------------------------------------
# Locate the .ui file to load as the qt interface
#------------------------------------------------------------------------------- ui_filename=setYourUiFilename() #-------------------------------------------------------------------------------
# Use the uic module to compile it and generate the ui class and its baseclass
#------------------------------------------------------------------------------- UI_CLASS, QT_BASE=uic.loadUiType(ui_filename)
class InterfaceClass(QT_BASE):
def __init__(self,parent):
QT_BASE.__init__(self,parent)
#-----------------------------------------------------------------------
# Create the controls
#-----------------------------------------------------------------------
self.ui = UI_CLASS( )
self.ui.setupUi( self )
#-----------------------------------------------------------------------
# The parent of this widget will be a widget representing a FBTool window
# and for this widget to resize into that window we need to add a new
# layout owned by the parent.
#-----------------------------------------------------------------------
layout=QtGui.QBoxLayout(0,parent)
layout.addWidget(self)
# your own initializer here, probably hooking up your custom signals
# self.emit(QtCore.SIGNAL("myCustomSignal(QString)"),self.returnAString)
So that creates a interface class that takes care of initializing the qt and running the actual mobu code. The constructor takes a parent argument and that is where the QTool comes in. The QTool will take this interface class, create it and pass its own qt widget representation to the interface class initializer which is then used as its parent. The interface class adds a layout to the QTool which sizes itself to fit within the tool window so then the interface is drawn on top of the FBTool window. Code to create the tool could look something like this:
DestroyToolByName("MyToolName") t = QTool("MyToolName",InterfaceClass)
And thats all there is to it. The new qt interface is not really part of the FBTool, rather its just drawn on top of it so potentially if one finds a way to access widget representations to FBLayouts it would be possible to mix pyfbsdk controls with pyqt controls
...lots of interesting things are accessible now. Its possible to add your own menu bars and menu items and so on.
So far my own tools created this way seem pretty stable
Oh and the above works only if the base of your qt interface is QWidget. If you are trying to integrate a qt tool based on QMainWindow and not FBTool a slightly different approach is needed since the QMainWindow will not parent itself happily into another window. In this case you need to find the qApp.topLevelWidgets() with the .name ‘Viewer’ which is the viewer window and then pass that QWidget to as the parent to your main window. Then if you want it to look like other FBTools you can set the window decorators on it with window.setWindowFlags(Qt.Tool)
|