Building a screen saver

We will start by building a screen saver for our desktop. The screen saver will consist of several random-colored and random-sized balls bouncing all over the screen at random velocity, as shown in the following screenshot:

Building a screen saver

Engage Thrusters

Carry out the following steps to create the screen saver:

  1. Let's create a class to generate balls with random attributes. Accordingly, we define a new class named RandomBall to achieve this (refer to the 7.01 screensaver.py Python file, available in the code bundle):
    from random import randint
    class RandomBall:
        def __init__(self, canvas, scrnwidth, scrnheight):
            self.canvas = canvas
            self.xpos = randint(10, int(scrnwidth))
            self.ypos = randint(10, int(scrnheight))
            self.xvelocity = randint(6,12)
            self.yvelocity = randint(6,12)
            self.scrnwidth = scrnwidth
            self.scrnheight = scrnheight
            self.radius = randint(40,70)
            r = lambda: randint(0,255)
            self.color = '#%02x%02x%02x' % (r(),r(),r())

    The description of the code is as follows:

    • The __init__ method takes three arguments, an instance of the Canvas widget, the screen width and the screen height. It then initializes the initial x and y positions for a ball as random numbers, starting from 0 up to the maximum screen coordinates.
    • It also initializes the velocity of the ball in x and y directions, the radius and color of the ball changes in a random fashion.
    • Because the hexadecimal color coding system uses two hexadecimal digits for each of red, green and blue colors, there are 16^2 (256) possibilities for each color. We therefore create a lambda function that generates a random number from 0-255, and use this function to generate three random numbers. We convert this decimal number to its two-digit equivalent hexadecimal notation using the format %02x to generate a random color for the balls.
  2. The second method creates the actual ball using the canvas create_oval method (refer to the 7.01 screensaver.py Python file available in the code bundle):
    def create_ball(self):
        x1 = self.xpos-self.radius
        y1 = self.ypos-self.radius
        x2 = self.xpos+self.radius
        y2 = self.ypos+self.radius
        self.itm = canvas.create_oval
    (x1, y1, x2, y2,
        fill=self.color, outline=self.color)
    
  3. Let's now code the method to handle ball movement on the screen.

    The method also checks if the ball has reached the end of the screen on any of the sides. If the ball has actually reached the end of the screen, it simply changes the direction by appending a negative sign to the velocity of the ball.

    The method finally moves the ball using the canvas.move method (refer to 7.01 screensaver.py):

    def move_ball(self):
        self.xpos += self.xvelocity
        self.ypos += self.yvelocity
        #Check if the Direction of ball movement is to be changed
        if self.ypos>= self.scrnheight - self.radius:
            self.yvelocity = - self.yvelocity # change direction
        if self.ypos<= self.radius :
            self.yvelocity = abs(self.yvelocity)
        if self.xpos>= self.scrnwidth- self.radius or self.xpos<= self.radius:
            self.xvelocity = -self.xvelocity # change direction
        self.canvas.move(self.itm
    , self.xvelocity, self.yvelocity)
    

    That is all to our RandomBall class. We can use this class to create as many ball objects as we want to display in our screen saver.

  4. Now, that we have coded methods to generate balls and to move them, let's create our screen saver. We now create a class named ScreenSaver that will show the actual screen saver:
    class ScreenSaver:
    balls = []
    
    def __init__(self, num_balls):
        self.root = Tk()
        w, h = self.root.winfo_screenwidth(),    self.root.winfo_screenheight()
        self.root.overrideredirect(1)
        self.root.geometry("%dx%d+0+0" % (w, h))
        self.root.attributes('-alpha', 0.3)
        self.root.bind('<Any-KeyPress>', quit)
        self.root.bind('<Any-Button>', quit)
        self.root.bind('<Motion>', quit)
        self.canvas = Canvas(self.root, width=w, height=h)
        self.canvas.pack()
        for i in range(num_balls):
            ball = RandomBall(self.canvas, scrnwidth=w, scrnheight=h)
            ball.create_ball()
            self.balls.append(ball)
        self.run_screen_saver()
        self.root.mainloop()

    The description of the code is as follows:

    • The __init__ method of the ScreenSaver class takes the number of balls (num_balls) as its argument.
    • We then create a root window and calculate the height and width of the screen using the winfo method.
    • We use root.overrideredirect(1) to remove the enclosing frame from the parent window.
    • We then specify the geometry of the parent window to fill the entire screen.
    • We make the parent window transparent using root.attributes('-alpha', 0.3). We add a transparency of 0.3 to make the window translucent.
    • We then bind the root to call our quit command on the event of clicking the mouse button, pressing any keyboard button, or mouse motion. This is to ensure that our program behaves like a screen saver, exiting on any interactions from the user's end.
    • We then create a canvas to cover the entire screen with Canvas(self.root, width=w, height=h).
    • We create several random ball objects outs of the RandomBall class, passing along the Canvas widget instance, the width, and the height of the screen as its arguments.
    • We finally make a call to run the screen saver with the run_screen_saver() method within the ScreenSaver class, which is discussed in the following.
  5. In this step, we will run the ScreenSaver class:
    def run_screensaver():
        for ball in balls:
            ball.move_ball()
        canvas.after(20, runScreenSaver)
    

    The description of the code is as follows:

    • The run_screensaver() method simply moves each ball by calling itself at a regular interval of 20 milliseconds
    • We also define the quit method in our ScreenSaver class to quit from the main loop and exit the program:
          def quit(event):
              root.destroy()
      
    • To run the screen saver, we instantiate an object from our ScreenSaver class, passing the number of balls as its argument:
      if __name__ == "__main__":
          ScreenSaver(18)  ##18 is the number of balls
      

Note

We have used two Toplevel window methods root.overrideredirect and root.attributes, in the previous code.

For a complete list of methods that can be applied to the Toplevel window, refer to the The Toplevel window methods section in Appendix B, Quick Reference Sheets.

Objective Complete – Mini Debriefing

Our screen saver is ready!

In fact, if you are working on a Windows platform, and when you learn to create an executable program from Python programs (discussed in Appendix A, Miscellaneous Tips), you can create an executable file with .exe extension for this screen saver. So then, you can change its extension from .exe to .scr and right-click, and select Install to add it to your list of screensavers!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.164.24