在Python-OpenGL中创建GLUT弹出菜单

2 投票
3 回答
2364 浏览
提问于 2025-04-16 09:54

我正在尝试在一个使用GLUT的Python(2.7)程序中创建一个右键点击弹出菜单。可是我找不到专门针对Python的文档,所以我参考了C++的文档,通常这两者是很相似的。

这是我目前的代码:

if __name__=="__main__":
    glutInit(sys.argv)
    #...more initialization code...
    createMenu()
    init()
    glutMainLoop()

下面是创建菜单的函数:

def createMenu():
    menu = glutCreateMenu(processMenuEvents)
    glutAddMenuEntry("One", 1)
    glutAddMenuEntry("Two", 2)
    glutAttachMenu(GLUT_RIGHT_BUTTON)

def processMenuEvents(option):
    logging.debug("Menu pressed")
    # not using 'option' right now

菜单显示得没问题,但当我点击某个选项时,就出现了这个错误:

DEBUG:root:Menu pressed:
Traceback (most recent call last):
  File "_ctypes/callbacks.c", line 338, in 'converting callback result'
TypeError: an integer is required
Exception  in <function processMenuEvents at 0x1760b90> ignored

请问python-opengl有没有其他的实现方式?我这里做错了什么?

谢谢。

3 个回答

0

这个例子帮我发现了需要为函数参数指定ctypes的要求,以解决同样的问题。我是在查看glutAddMenuEntry()的pyopengl文档时发现的。关于你函数参数的ctype数据类型,可以在这里找到。

下面这个代码片段展示了一个f(int)->int函数的例子,通过一个对象实例来引用:

class Menu:
 def select_menu(self, choice):
    def _exit():
        import sys
        sys.exit(0)
    {
        1: _exit
    }[choice]()
    glutPostRedisplay()
    return 0

 def create_menu(self):
    # --- Right-click Menu --------
    from ctypes import c_int
    import platform
    #platform specific imports:
    if (platform.system() == 'Windows'):
        #Windows
        from ctypes import WINFUNCTYPE
        CMPFUNCRAW = WINFUNCTYPE(c_int, c_int)
        # first is return type, then arg types.
    else:
        #Linux
        from ctypes import CFUNCTYPE
        CMPFUNCRAW = CFUNCTYPE(c_int, c_int)
        # first is return type, then arg types.

    myfunc = CMPFUNCRAW(self.select_menu)

    selection_menu = glutCreateMenu( myfunc )
    glutAddMenuEntry("Quit", 1);
    glutAttachMenu(GLUT_RIGHT_BUTTON);
    # ---------------------------------
1

很遗憾,PyOpenGL定义的回调函数要求返回一个整数,而不是空值(void)。下面是你创建菜单的回调函数的更新版本,应该可以正常工作。

def CreateMenu():
    menu = glutCreateMenu(processMenuEvents)  
    glutAddMenuEntry("One", 1)  
    glutAddMenuEntry("Two", 2)  
    glutAttachMenu(GLUT_RIGHT_BUTTON)
    # Add the following line to fix your code
    return 0
0

在Python中通过ctypes指定回调函数的方式可能和你想象的不太一样。你应该使用CFUNCTYPE来创建回调函数,然后把这个创建出来的变量作为参数传给glutCreateMenu。

你可以在这里找到关于ctypes和回调函数的更多细节:http://docs.python.org/release/2.5.2/lib/ctypes-callback-functions.html

撰写回答