pyopengl glut 输入

2 投票
2 回答
6351 浏览
提问于 2025-04-17 07:04

在显示GLUT图形的窗口出现后,我想在终端输入内容:

user@computer: python woop.py
# Now displaying a beautiful landscape
(cmd): season winter
# Now changing season to winter
(cmd): event meteor
# Now meteoring otherwise peaceful landscape
(cmd): season summer
# Now changing season to summer
(cmd): exit
#bye ^_^
user@computer:

理想情况下,我希望将Python的cmd与GLUT的glutKeyboardFunc结合起来。但我尝试过的都失败了(只能使用一个,要么是窗口,要么是终端,不能同时使用。此外,还有关于哪个窗口或终端有焦点的问题)。

这里有一些示例代码,可以显示一个旋转的茶壶。目前,按下'm'键会触发一些流星效果(只是个占位符),但如果能输入比如“meteor 500”就更好了。

#! /usr/bin/env python
''' 
Code is a reduced version of http://www.seethroughskin.com/blog/?p=771
'''
import OpenGL 
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *

import time, sys

class dizzyTea:

    global rotY

    def __init__(self):
        self.main()

    def InitGL(self,Width, Height):
        glClearColor(0.0, 0.0, 0.0, 0.0)
        glClearDepth(1.0)
        glShadeModel(GL_SMOOTH)  
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()       
        gluPerspective(45.0, float(Width)/float(Height), 0.1, 100.0)
        glMatrixMode(GL_MODELVIEW)     

    # The main drawing function. 
    def DrawGLScene(self):
        global rotY
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        glLoadIdentity()                    # Reset The View 
        glTranslatef(-0.5, 0.0, -6.0)
        glRotatef(rotY,0.0,1.0,0.0)
        glutWireTeapot(1.0)
        glScalef(0.3,0.3,0.3)
        glutSwapBuffers()
        rotY += 1.0

    # The function called whenever a key is pressed. Note the use of Python tuples to pass in: (key, x, y)  
    def keyPressed(self,*args):

        # If escape is pressed, kill everything.
        if args[0] == '\x1b':
            sys.exit()
        elif args[0] == 'm':
            print "Now meteoring otherwise peaceful teapot"
            # meteor shenanigans

    def main(self):
        global window
        global rotY
        glutInit(sys.argv)
        glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH)
        glutInitWindowSize(640, 480)
        glutInitWindowPosition(0, 0)
        window = glutCreateWindow("Jeff Molofee's desecrated GL Code Tutorial")
        glutDisplayFunc(self.DrawGLScene)
        glutIdleFunc(self.DrawGLScene)
        glutKeyboardFunc(self.keyPressed)
        self.InitGL(800, 600)
        rotY = 0.0
        glutMainLoop()

if __name__ == "__main__":
    x = dizzyTea()

我可以使用glutKeyboardFunc把字符收集到一个全局字符串中,这样也能达到类似的效果,不过用户在输入时是看不见的。“print somestring,”可以在同一行打印,但逗号的存在意味着在输入时不会显示输出。而且“print '\b'”(退格键)并不是在所有情况下都有效……

基本上,我不想要:

user@computer: python woop.py
# Now displaying a beautiful landscape
(cmd): s
(cmd): se
(cmd): sea
(cmd): seas
...etc

输入一个命令

使用的限制:

  • pyopengl
  • GLUT

(不过其他的答案也欢迎给未来的朋友们,帮助他们解决不同的问题)

2 个回答

1

你应该使用 cmd [0] 这个框架来构建你的解释器,并在一个单独的线程中启动 cmd.cmdloop。

0. http://docs.python.org/3/library/cmd.html
2
# The function called whenever a key is pressed. Note the use of Python tuples to pass in: (key, x, y)  
def keyPressed(self,*args):
    if args[0] == '\x08':
        self.keyCache = self.keyCache[:-1]
    elif args[0] == '\x1b':
        sys.exit()
    elif args[0] == 'm':
        print "Now meteoring otherwise peaceful teapot"
        # meteor shenanigans
    else:
        self.keyCache += args[0]
    sys.stdout.write(self.keyCache +"                                                  \r")#print "keypress: <",self.keyCache,">"
    sys.stdout.flush()

然后添加一个新的类变量 'keyCache'。

接下来,只需使用普通的打印方式来将数据写到同一行。唯一有点麻烦的是,你需要在缓存的按键后面写几个空格,否则当你按退格键时,删除的内容仍然会显示在屏幕上。

另一种选择是创建一个独立的键盘线程,专门处理命令行的按键输入。这里最大的麻烦是,glut没有提供一个好的方法来处理窗口关闭时的情况,所以你需要想办法找到其他方法来结束你的线程。

撰写回答