2012-06-07 91 views
3

在閱讀了關於VPythonGTK threading的文檔後,我認爲可以將VPython圖形嵌入到gtk GUI中。我知道這是可能的wx on Windows,但我在Linux上並使用PyGTK。現在,我已經設法得到了一部分。我可以嵌入一個VPython窗口,前提是它生成一個單獨的進程。我想將它嵌入爲一個線程。後者將使控制OpenGL的GUI事件更容易實現 - 通過線程而不是套接字和網絡調用。GTK窗口截圖:VPython(OpenGL)應用程序

編輯:顯然沒有人知道這件事......呃。

這是我的代碼。取消註釋掉兩條註釋過的行並評論其他一些明顯的其他行,並且可以獲取進程產卵代碼。

#!/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() 

回答

3

這是在任何人關心的情況下工作的代碼。

#!/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() 

注意:這並不侏儒下工作,但在工作FVWM2。去圖...

+0

老線程,同樣的問題。我在C中有類似的問題,實現相同的邏輯。你有沒有試圖問GTK開發團隊?無論如何,你有沒有找到其他解決方案?謝謝 – tmow

+0

@tmow:不,我沒有。 – Sardathrion