Embedding FreeCADGui
You already know that you can import the FreeCAD module into a python application, and use all its tools from the host application. But the FreeCAD User Interface (GUI) can also be imported as a python module. Normally you can only import the complete interface as a whole, not pieces of it. That is because the FreeCAD interface system is not only made of independent widgets and toolbars, but is a complex construction where several invisible components (such as the selection system, etc) are needed for the main 3D view to be able to function.
But, with a bit of hacking, it is possible to import the whole FreeCAD interface, then move the 3D view from it to your own Qt application.
But be aware that there are still a lot of problems with this approach. The Qt event handling doesn't seem to work (no idea why) and if you use the 3d view's context-menu the application crashes. A better way could be to create your own 3d view SoQtExaminerViewer or SoQtViewer and "push" the content of FreeCAD's 3d view to your view, as shown below.
First, get the main window via PyQt:
from PyQt4 import QtGui from PyQt4 import QtCore def getMainWindow(): toplevel = QtGui.qApp.topLevelWidgets() for i in toplevel: if i.metaObject().className() == "Gui::MainWindow": return i raise Exception("No main window found") mw=getMainWindow()
Then get the View3DInventor view the same way:
def get3dview(mw): childs=mw.findChildren(QtGui.QMainWindow) for i in childs: if i.metaObject().className()=="Gui::View3DInventor": return i return None v=get3dview(mw)
The following code is generated automatically, by creating a Ui-file with QtDesigner, and converting it to python code with the pyuic tool:
# -*- coding: utf-8 -*- # Form implementation generated from reading ui file 'mainwindow.ui' # # Created: Sun Dec 27 11:18:56 2009 # by: PyQt4 UI code generator 4.6 # # WARNING! All changes made in this file will be lost! from PyQt4 import QtCore, QtGui class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(508, 436) self.centralwidget = QtGui.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.gridLayout = QtGui.QGridLayout(self.centralwidget) self.gridLayout.setObjectName("gridLayout") self.mdiArea = QtGui.QMdiArea(self.centralwidget) self.mdiArea.setViewMode(QtGui.QMdiArea.TabbedView) self.mdiArea.setTabPosition(QtGui.QTabWidget.South) self.mdiArea.setObjectName("mdiArea") self.gridLayout.addWidget(self.mdiArea, 0, 0, 1, 1) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtGui.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 508, 27)) self.menubar.setObjectName("menubar") MainWindow.setMenuBar(self.menubar) self.statusbar = QtGui.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8))
Then, create a main window that should be your application's main window, apply the UI setup above to it in order to add an MDI area and "move" our 3d view to it
ui=Ui_MainWindow() my_mw=QtGui.QMainWindow() ui.setupUi(my_mw) ui.mdiArea.addSubWindow(v) my_mw.show()
Alternatively, you can also use the FreeCADGui module to extract a coin/openInventor representation of the objects of your scene, then use that coin data in an external viewer (your application). Here is an easy way to get the 3d representation of an object:
FreeCAD.activeDocument().addObject("Part::Box","myBox") s=FreeCADGui.activeDocument().getObject("myBox").toString() # store as string from pivy import coin inp.setBuffer(s) myNode=coin.SoDB.readAll(inp) # restore from string
Then, create a standalone viewer with pivy:
from pivy.sogui import * from pivy.coin import * import sys def myViewer(): # Initialize Coin. This returns a main window to use. # If unsuccessful, exit. myWindow = SoGui.init(sys.argv[0]) if myWindow == None: sys.exit(1) # Make an empty scene and add our node to it scene = SoSeparator() scene.addChild(myNode) # Create a viewer in which to see our scene graph. viewer = SoGuiExaminerViewer(myWindow) # Put our scene into viewer, change the title viewer.setSceneGraph(scene) viewer.setTitle("FreeCAD Object Viewer") viewer.show() SoGui.show(myWindow) # Display main window SoGui.mainLoop() # Main Coin event loop
Then you just need to run your viewer:
myViewer()