Panda and PyQt integration (Linux only)

Hi all,

I have been reading posts on this forum about Panda3D and PyQt integration. They provide an excellent foundation. Thank you to all the posters.

Unfortunately, the solutions provided using setParentWindow() do not work for me since I am trying to embed the Panda3D windows inside an MDI framework using Qt. One needs to be careful with the winId exposed by Qt since it tends to change during run-time (as mentioned in its own documentation). I tried to react to winId changes using the Qt widget’s event handler but so far I could not make it work without gazillions of X11 error messages about invalid window parameters.

Then I thought “Why not try to embed the Panda3D window inside Qt?”. Apparently Qt provides a clean (at least at the user level) interface to do that using X Embed. Fortunately, it worked! Still no luck with the MDI though :frowning:

Here is my 2 cents:

from direct.showbase.ShowBase import ShowBase

from PyQt4.QtCore import *
from PyQt4.QtGui import *

import sys

class QPandaWindow(QX11EmbedContainer):
    
    def __init__(self,showBase,title='',size=QSize(640,480),parent=None):
        
        super(QX11EmbedContainer, self).__init__(parent=parent)

        self.setWindowTitle(title)
        self.setGeometry(0,0,size.width(),size.height())
        
        self.win = base.openWindow()

        self.embedClient(self.win.getWindowHandle().getIntHandle())

class PandaWorld(ShowBase):   

    def __init__(self):
        
        ShowBase.__init__(self)
        
        self.accept("escape", sys.exit)
   
        self.world = self.loader.loadModel("my_model")
        self.world.reparentTo(self.render)
        self.world.setPos(0, 0, 0)
   
        self.openDefaultWindow()


if __name__ == '__main__':
    
    panda_world = PandaWorld()

    app = QApplication(sys.argv)

    panda_window = QPandaWindow(showBase=panda_world)

    main_window = QMainWindow()
    
    timer = QTimer(main_window)
    main_window.connect(timer, SIGNAL("timeout()"), base.taskMgr.step)
    timer.start(0)

    panda_window.show()

    app.exec_()

DISCLAIMER: This code is a quick cook-up to show the idea.

The good:

No need to reimplement widget listeners to window events like resize etc. It comes for free with this approach.

Relatively compact code.

Good exercise towards more sophisticated approaches.:slight_smile:

The bad:

It will NOT work in Windows. I could not find any Qt interface doing the same thing as X11 embedding for Windows.

Still could not make it work in a Qt MDI window. But when I try to, I do not see any errors as opposed to the previous approach. It looks like Qt puts another level of window management for its MDI subwindows.

Possibly more than I can think of right now.:unamused:

Note that in this code the panda_window will not have keyboard or mouse interface functionality. You will have to add it.

Hope this helps!

Comments/suggestions are welcome!

UB