Akshay
Akshay

Reputation: 1706

Creating a GLUT popup menu in Python-OpenGL

I'm trying to create a right-click-popup-menu in a Python(v2.7) program using GLUT. I haven't found Python-specific documentation for doing this, so I used C++ documentation, which is usually almost similar.

Here's what I have:

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

And here are the functions that create the menu:

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

The menu gets displayed correctly, but when I click on an item, I get this error:

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

Does python-opengl have a different way of doing this? What am I doing wrong here?

Thanks.

Upvotes: 2

Views: 2454

Answers (3)

pds
pds

Reputation: 2582

This example helped me identify the requirement for specifying function parameter ctypes to solve the same problem. Found following the pyopengl glut docs on glutAddMenuEntry(). Ctype data types for your function args are specified here.

This snippet shows an example of an f(int)->int function, referenced via an object instance:

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);
    # ---------------------------------

Upvotes: 0

Steve
Steve

Reputation: 11

Unfortunately, the way that PyOpenGL has defined the callback function, it expects an int as the return type, not void. Below is an updated version of your CreateMenu callback function that should work.

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

Upvotes: 1

Vaayu
Vaayu

Reputation: 476

Specifying callback functions via ctypes in Python doesn't quite work like you are expecting. You should use CFUNCTYPE to create the callback function and use the resulting variable as the parameter to glutCreateMenu.

You will find more details on ctypes and callback functions here: http://docs.python.org/release/2.5.2/lib/ctypes-callback-functions.html

Upvotes: 0

Related Questions