Mixing PyQt and IPLT widgets
PyQt4 is a set of python bindings for Qt4. The exposure from C++ to Python is done with SIP, which has a different mechanism than boost::python. As a consequence, the following example won't work:
from PyQt4.QtCore import * from PyQt4.QtGui import * # create a SIP based widget based on PyQt4 sip_w=QWidget() # and create one of the IPLT gui widgets # based on a proxy mechanism and boost::python giplt_pv=gui.CreatePlotViewer() # attempt to make a layout including our IPLT widget layout=QHBoxLayout() layout.addWidget(QLabel("left"),0) # The following line does not work - giplt_pv is not recognized by SIP layout.addWidget(giplt_pv,1) # layout.addWidget(QLabel("right"),0) sip_w.setLayout(layout)
We have to resort to somewhat of a hack in order to make boost::python and SIP exchange their internally managed objects. SIP provides functionality to retrieve the underlying C++ address in form of an integer, and it provides the functionality to reinterpret a given integer to a SIP supported object. This is combined with either a function or a base-class method in iplt.gui to make the interconversion possible:
# go from sip to iplt giplt_widget = gui.BPQtHandle(sip.unwrapinstance(some_sip_widget)) # go from iplt to sip sip_widget=sip.wrapinstance(some_giplt_proxy.SipHandle(),QWidget)
All giplt proxy classes (iplt::gui::DataViewer, iplt::gui::PlotViewer) are derived from a SipHandler base class, which provides the address of the proxied object via the SipHandle() method.
The above example fixed using these calls:
from PyQt4.QtCore import * from PyQt4.QtGui import * import sip # needed for the wrapping # create a SIP based widget based on PyQt4 sip_w=QWidget() # and create one of the IPLT gui widgets # based on a proxy mechanism and boost::python giplt_pv=gui.CreatePlotViewer() # convert to sip qwidget sip_pv=sip.wrapinstance(giplt_pv.SipHandle(),QWidget) # attempt to make a layout including our IPLT widget layout=QHBoxLayout() layout.addWidget(QLabel("left"),0) # The following line works now layout.addWidget(sip_pv,1) # layout.addWidget(QLabel("right"),0) sip_w.setLayout(layout)
The opposite scenario is also possible - some IPLT widgets take QWidget* as one of their arguments, such as the DataViewer in order to add new docking widgets. Although the created widget is handed over to be managed by IPLT, the signals set up in Python continue to work!
import sip from PyQt4.QtCore import * from PyQt4.QtGui import * def on_two(): mlogn(0,"On Two") i=CreateImage(Size(100,100)) v=Viewer(i) dock = QWidget() vb=QVBoxLayout() vb.addWidget(QLabel("One")) pb=QPushButton("Two") QObject.connect(pb,SIGNAL("clicked()"),on_two) vb.addWidget(pb) vb.addWidget(QCheckBox("Three")) dock.setLayout(vb) v.AddDock(gui.BPQtHandle(sip.unwrapinstance(dock)),"test")
It is also possible to connect to signals of IPLT widgets which are exported to python. See next example.
