Creating Amazing 3D GUIs with PyGLet

In this article, by Burkhard Meier, the author of Python GUI Programming Cookbook, we will create amazing Python GUIs that display true 3-Dimensional images that can be rotated around themselves so that we can look at them from all sides.

We will cover the following recipes in this article:

  • PyGLet transforms our GUI easier than PyOpenGL
  • Our GUI in amazing colors
  • Creating a slide show using tkinter

(For more resources related to this topic, see here.)

PyGLet transforms our GUI easier than PyOpenGL

In this recipe we will use the PyGLet GUI development framework to create our GUIs.

PyGLet is easier to use than PyOpenGL as it comes with its own GUI event loop so we do not need to use tkinter or wxPython to create our GUI.

How to do it...

In order to use Pyglet, we first have to install this third-party Python plug-in.

Using the pip command, we can easily install the library and a successful installation looks like this in our site-packages Python folder:

The online documentation is located at this website for the current release:

https://pyglet.readthedocs.org/en/pyglet-1.2-maintenance/

A first experience using the Pyglet library may look like this:

import pyglet

window = pyglet.window.Window()
label = pyglet.text.Label('PyGLet GUI',
                         font_size=42,
                         x=window.width//2, y=window.height//2,
                         anchor_x='center', anchor_y='center')

@window.event
def on_draw():
   window.clear()
   label.draw()

pyglet.app.run()

The above code is from the official pyglet.org website and results in the following fully functional GUI:

How it works...

In this recipe we used another third-party Python module that wraps the OpenGL library.

This library comes with its own event loop processing power, which enables us to avoid having to rely on yet another library to create a running Python GUI.

We have explored the official website which shows us how to install and use this fantastic GUI library.

Our GUI in amazing colors

In this recipe we will extend our GUI written using Pyglet from the previous recipe, by turning it into true 3D.

We will also add some fancy colors to it. This recipe was inspired by some sample code from the OpenGL SuperBible book series. It creates a very colorful cube which we can turn around in 3-dimensional space using the keyboard up, down, left, and right buttons.

We have slightly improved the sample code by making the image turn when holding down one of the keys instead of having to press and release the key.

Getting ready

The previous recipe explains how to install PyGLet and gives you an introduction to this library. If you have not done so, it is probably a good idea to browse through that recipe.

In the online documentation, PyGLet is usually spelled in all lower-case. While this might be a Pythonic way, we capitalize the first letter of a class in this article and we use lower case for variable, method, and function names to start each name.

We do not use underscores in this article unless necessary to clarify code.

How to do it...

The following code creates the 3-dimensional colored cube shown below it. This time, we will use the keyboard arrow keys to rotate the image, instead of the mouse.

import pyglet
from pyglet.gl import *
from pyglet.window import key
from OpenGL.GLUT import *

WINDOW   = 400
INCREMENT = 5

class Window(pyglet.window.Window):

   # Cube 3D start rotation
   xRotation = yRotation = 30  

   def __init__(self, width, height, title=''):
       super(Window, self).__init__(width, height, title)
       glClearColor(0, 0, 0, 1)
        glEnable(GL_DEPTH_TEST)  

   def on_draw(self):
       # Clear the current GL Window
       self.clear()

       # Push Matrix onto stack
       glPushMatrix()

       glRotatef(self.xRotation, 1, 0, 0)
       glRotatef(self.yRotation, 0, 1, 0)

       # Draw the six sides of the cube
       glBegin(GL_QUADS)

       # White
       glColor3ub(255, 255, 255)
       glVertex3f(50,50,50)

       # Yellow
       glColor3ub(255, 255, 0)
       glVertex3f(50,-50,50)

       # Red
       glColor3ub(255, 0, 0)
       glVertex3f(-50,-50,50)
       glVertex3f(-50,50,50)

       # Blue
       glColor3f(0, 0, 1)
       glVertex3f(-50,50,-50)

         # <… more color defines for cube faces>

       glEnd()

       # Pop Matrix off stack
       glPopMatrix()

def on_resize(self, width, height): # set the Viewport glViewport(0, 0, width, height) # using Projection mode glMatrixMode(GL_PROJECTION) glLoadIdentity() aspectRatio = width / height gluPerspective(35, aspectRatio, 1, 1000) glMatrixMode(GL_MODELVIEW) glLoadIdentity() glTranslatef(0, 0, -400) def on_text_motion(self, motion): if motion == key.UP: self.xRotation -= INCREMENT elif motion == key.DOWN: self.xRotation += INCREMENT elif motion == key.LEFT: self.yRotation -= INCREMENT elif motion == key.RIGHT: self.yRotation += INCREMENT if __name__ == '__main__': Window(WINDOW, WINDOW, 'Pyglet Colored Cube') pyglet.app.run()

Using the keyboard arrow keys, we can spin the 3D cube around.

How it works...

In this recipe we have used pyglet to create a colorful cube which we can rotate in 3-dimensional space using the keyboard arrow keys.

We have defined several colors for the six faces of our cube and we have used pyglet to create our main window frame.

The code is similar to a previous recipe in which we used the wxPython library to create a cube.

The reason is that, underneath the hood, both wxPython and pyglet use the OpenGL library.

Creating a slideshow using tkinter

In this recipe we will create a nice working slideshow GUI using pure Python.

We will see the limitations the core Python built-ins have, and then we will explore another third-party module available called Pillow which extends tkinter's built-in functionality in regards to image processing.

While the name Pillow might sound a little bit strange at first, it actually comes with a lot of history behind it.

We are only using Python 3.4 and above in this article.

We are not going back to Python 2.

Guido has expressed his decision to intentionally break backwards compatibility and decide that Python 3 is the future of Python programming.

For GUIs and images, the older line of Python 2 has this very powerful module named

PIL, which stands for Python Image Library. This library comes with a very large amount of functionality which several years after the very successful creation of Python 3 has not been translated for Python 3.

Many developers still choose to use Python 2 instead of the future as designed by the Benevolent Dictator of Python because Python 2 still has more libraries available.

That is a little bit sad.

Fortunately, another imaging library has been created to work with Python 3 and it is named PIL plus something.

Pillow is not compatible with the Python 2 PIL library.

Getting ready

In the first part of this recipe, we will use pure Python. In order to improve the code, we will install another Python module using pip functionality so, while you are most likely familiar with pip,a little knowledge of how to use it might be useful.

How to do it...

First ,we will create a working GUI that shuffles slides within a window frame using pure Python.

Here is the working code and below it are some screenshots of the results of running this code:

from tkinter import Tk, PhotoImage, Label
from itertools import cycle
from os import listdir
class SlideShow(Tk):
   # inherit GUI framework extending tkinter
   def __init__(self, msShowTimeBetweenSlides=1500):
       # initialize tkinter super class
       Tk.__init__(self)

       # time each slide will be shown
       self.showTime = msShowTimeBetweenSlides

       # look for images in current working directory
       listOfSlides = [slide for slide in listdir() if slide.endswith('gif')]

       # cycle slides to show on the tkinter Label
       self.iterableCycle = cycle((PhotoImage(file=slide), slide) for slide in listOfSlides)

       # create tkinter Label widget which can display images
       self.slidesLabel = Label(self)

       # create the Frame widget
       self.slidesLabel.pack()
   def slidesCallback(self):
       # get next slide from iterable cycle
       currentInstance, nameOfSlide = next(self.iterableCycle)

       # assign next slide to Label widget
       self.slidesLabel.config(image=currentInstance)

       # update Window title with current slide
       self.title(nameOfSlide)

       # recursively repeat the Show
       self.after(self.showTime, self.slidesCallback)

#=================================
# Start GUI
#=================================              
win = SlideShow()
win.after(0, win.slidesCallback())
win.mainloop()

Here is another moment in time in the unfolding slideshow.

While the slides sliding are truly impressive, the built-in capabilities of pure Python tkinter GUIs do not support the very popular .jpg format so we have to reach out to another Python library.

In order to use Pillow, we first have to install it using the pip command.

A successful installation looks like this:

Pillow supports .jpg formats and, in order to use it, we to have to slightly change our syntax.

Using Pillow is an advanced topic that will not be covered in this edition of the article.

How it works...

Python is a very wonderful tool and, in this recipe, we have explored several ways to use and extend it.

When a finger points at the moon, it is not the moon itself, just a pointer.

Summary

In this article, we learned various recipes to effectively amazing Python GUIs that display true 3-Dimensional images using PyGLet.

Resources for Article:


Further resources on this subject:


You've been reading an excerpt of:

Python GUI Programming Cookbook

Explore Title