Captura de ventana GTK: aplicación VPython (OpenGL)

Después de leer la documentación para los subprocesos VPython y GTK , me parece que sería posible incrustar gráficos VPython dentro de una GUI de gtk. Sé que es posible con wx en Windows pero estoy en Linux y estoy usando PyGTK. Ahora, he logrado obtener parte del camino. Puedo incrustar una ventana de VPython siempre que se genere un proceso separado . Lo que me gustaría es incrustarlo como un hilo. Esto último haría que los eventos GUI que controlan el OpenGL sean más fáciles de implementar, a través de un hilo en lugar de un socket y llamadas de red.

Edit: Al parecer, nadie sabe nada de esto … Meh.

Aquí está el código que tengo. Descomente las dos líneas comentadas y comente algunas otras obvias, y podrá acceder al código de generación del proceso.

#!/usr/bin/env python # -*- coding: utf-8 -*- import time from visual import * import threading import Queue import gtk import pygtk import re import subprocess class OPenGLThreadClass (threading.Thread): """Thread running the VPython code.""" def __init__(self, queue): threading.Thread.__init__(self) self.queue = queue self.name = 'OpenGLThread' def run (self): gtk.threads_enter() self.scene = display.get_selected() self.scene.title = 'OpenGL test' s = sphere() gtk.threads_leave() #P = subprocess.Popen(['python', 'opengl.py']) time.sleep(2) self.queue.put(self.find_window_id()) self.queue.task_done() def find_window_id (self): """Gets the OpenGL window ID.""" pattern = re.compile('0x[0-9abcdef]{7}') P = subprocess.Popen(['xwininfo', '-name', self.scene.title], #P = subprocess.Popen(['xwininfo', '-name', 'Visual WeldHead'], stdout=subprocess.PIPE) for line in P.stdout.readlines(): match = pattern.findall(line) if len(match): ret = long(match[0], 16) print("OpenGL window id is %d (%s)" % (ret, hex(ret))) return ret class GTKWindowThreadClass (threading.Thread): """Thread running the GTK code.""" def __init__ (self, winID): threading.Thread.__init__(self) self.OpenGLWindowID = winID self.name = 'GTKThread' def run (self): """Draw the GTK GUI.""" gtk.threads_enter() window = gtk.Window() window.show() socket = gtk.Socket() socket.show() window.add(socket) window.connect("destroy", lambda w: gtk.main_quit()) print("Got winID as %d (%s)" % (self.OpenGLWindowID, hex(self.OpenGLWindowID))) socket.add_id(long(self.OpenGLWindowID)) gtk.main() gtk.threads_leave() def main (): thread = {} print("Embedding OpenGL/VPython into GTK GUI") queue = Queue.Queue() thread['OpenGL'] = OPenGLThreadClass(queue) thread['OpenGL'].start() winID = queue.get() print("Got winID as %d (%s)" % (winID, hex(winID))) gtk.gdk.threads_init() thread['GTK'] = GTKWindowThreadClass(winID) thread['GTK'].start() if __name__ == "__main__": main() 

    Este es el código que funciona en caso de que a alguien le importe.

     #!/usr/bin/env python # -*- coding: utf-8 -*- import subprocess import sys import os import re import time from visual import * def find_window_id (title): """Gets the OpenGL window ID.""" pattern = re.compile('0x[0-9abcdef]{7}') proc = subprocess.Popen(['xwininfo', '-name', title], stdout=subprocess.PIPE, stderr=subprocess.PIPE) errors = proc.stderr.readlines() if errors: return None for line in proc.stdout.readlines(): match = pattern.findall(line) if len(match): return long(match[0], 16) return None class Setting (): """VPython/OpenGL class.""" def __init__ (self, w=256, h=256, title='OpenGL via VPython'): """Initiator.""" self.width = w self.height = h self.title = title self.scene = display.get_selected() self.scene.title = self.title self.scene.width = self.width self.scene.height = self.height self.sphere = sphere() class GTKDisplay (): def __init__ (self, winID): """Initiator: Draws the GTK GUI.""" import gtk import pygtk self.OpenGLWindowID = winID window = gtk.Window() window.show() socket = gtk.Socket() socket.show() window.add(socket) window.connect("destroy", lambda w: gtk.main_quit()) socket.add_id(long(self.OpenGLWindowID)) gtk.main() def main (): """Main entry point.""" name = 'sphere OpenGL window' child_pid = os.fork() if 0 == child_pid: sut = Setting(title=name) else: winID = None while not winID: time.sleep(.1) winID = find_window_id(name) try: gui = GTKDisplay(winID) except KeyboardInterrupt, err: print '\nAdieu monde cruel!' if __name__ == "__main__": main() 

    Nota : Esto no funciona bajo Gnome pero funciona bajo fvwm2. Imagínate…