用Tkinter打造GUI开发工具(33)Tkinter中的OpenGL组件

前面我们介绍了在Tkinter中运行turtle。这节介绍在Tkinter中运行OpenGL组件。
HP_tk2的支持模块中,我们有这个模块HP_tko。利用HP_tko模块,可以在Tkinter窗口中,放OpenGL的Tkinter组件,来实现三维动画。
下面给出演示代码。

import  tkinter  as  tk   #导入Tkinter
from HP_tko import OpenglFrame,opengl_demo
from HP_tko import GL_BLEND, GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT, GL_DEPTH_TEST, \
                        GL_MODELVIEW, GL_ONE_MINUS_SRC_ALPHA, GL_PROJECTION, GL_QUADS, GL_RENDERER, \
                        GL_SRC_ALPHA, GL_VENDOR, GL_VERSION, \
                        glBegin, glClear, glBlendFunc, glClearColor, \
                        glClearDepth, glColor3f, glEnable, glEnd, glGetString, glFlush, \
                        glLoadIdentity, glMatrixMode, glOrtho, glRotatef, glVertex3f, glViewport


root=tk.Tk()
root.title('Tkinter中的OpenGL演示') 
root.geometry('{}x{}+{}+{}'.format(800, 600, 100, 200))
o = opengl_demo(root, width=320, height=200)
o.pack(fill=tk.BOTH, expand=tk.YES)


root.mainloop()

下面是运行的结果。
在这里插入图片描述
OpenglFrame组件是在Tkinter窗口中放置的OpenGL绘图区,在这个绘图区执行OpenGL绘图命令来实现三维动画。
下面给出opengl_demo的源代码。

class opengl_demo(OpenglFrame):

    rot = 0

    def on_resize(self, event, arg=None):

        if event:
            w = event.width
            h = event.height
        else:
            if arg:
                w = arg['w']
                h = arg['h']
            else:
                raise Exception

        dx = w/h
        glViewport(0, 0, w, h)

        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        glOrtho(
            -2 * dx,
            2 * dx,
            -2,
            2,
            -2,
            2
        )

    def set_ortho_view(self):

        glEnable(GL_BLEND)
        glEnable(GL_DEPTH_TEST)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        glClearColor(0, 0, 0, 0)
        glClearDepth(1)
        glMatrixMode(GL_PROJECTION)

        self.on_resize(None, arg={
            'w': self.winfo_width(),
            'h': self.winfo_height()
        })

        print('%s - %s - %s' % (
            glGetString(GL_VENDOR),
            glGetString(GL_VERSION),
            glGetString(GL_RENDERER)
        ))

    def render_scene(self):

        self.rot += .5

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()
        glRotatef(self.rot, 1, 1, 0.5)

        # Draw a simple cube.
        glBegin(GL_QUADS)

        glColor3f(0, 1, 0)
        glVertex3f(1, 1, -1)
        glVertex3f(-1, 1, -1)
        glVertex3f(-1, 1, 1)
        glVertex3f(1, 1, 1)

        glColor3f(1, 0.5, 0)
        glVertex3f(1, -1, 1)
        glVertex3f(-1, -1, 1)
        glVertex3f(-1, -1, -1)
        glVertex3f(1, -1, -1)

        glColor3f(1, 0, 0)
        glVertex3f(1, 1, 1)
        glVertex3f(-1, 1, 1)
        glVertex3f(-1, -1, 1)
        glVertex3f(1, -1, 1)

        glColor3f(1, 1, 0)
        glVertex3f(1, -1, -1)
        glVertex3f(-1, -1, -1)
        glVertex3f(-1, 1, -1)
        glVertex3f(1, 1, -1)

        glColor3f(0, 0, 1)
        glVertex3f(-1, 1, 1)
        glVertex3f(-1, 1, -1)
        glVertex3f(-1, -1, -1)
        glVertex3f(-1, -1, 1)

        glColor3f(1, 0, 1)
        glVertex3f(1, 1, -1)
        glVertex3f(1, 1, 1)
        glVertex3f(1, -1, 1)
        glVertex3f(1, -1, -1)

        glEnd()

        glFlush()

图形显示比较慢的原因,我们采用了tkinter的after方法,每5秒渲染一次。

    def _render_loop(self):

        self.render_scene()
        ...
        self.parent.after(5, self._render_loop)

实际使用要用多线程,循环方式实现高速图形渲染。

当然也可以插入纹理,实现复杂的动画。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/hepu8/article/details/106322887