Search code examples
pythonpython-2.7pygame-clock

How to set a clicking clock in a pygame window


#!/usr/bin/python
# -*- coding: utf-8 -*-
import pygame
import sys
import datetime
import time


class TextPicture(pygame.sprite.Sprite):

    def __init__(self, speed, location):
        pygame.sprite.Sprite.__init__(self)
        now = datetime.datetime.now()
        text = now.strftime("%H:%M:%S")
        font = pygame.font.Font(None, 40)
        time_text = font.render(text, 1, [0, 0, 0])  # show now time
        self.image = time_text
        self.speed = speed
        self.rect = self.image.get_rect()
        self.rect.left, self.rect.top = location

    def move(self):
        self.rect = self.rect.move(self.speed)
        if self.rect.left < 0 or self.rect.left > screen.get_width() - self.image.get_width():
            self.speed[0] = -self.speed[0]
        if self.rect.top < 0 or self.rect.top > screen.get_height() - self.image.get_height():
            self.speed[1] = -self.speed[1]


pygame.init()
screen = pygame.display.set_mode([640, 480])
my_time_picture = TextPicture([1, 1], [50, 50])


while 1:
    screen.fill([255, 255, 255])
    my_time_picture.move()
    screen.blit(my_time_picture.image, my_time_picture.rect)
    pygame.display.flip()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

I am designing a clock which can move in the screen. But what my code can do now is to show a invariant time. I want to clicking and count the time. My invariable clock picture

And I want to make my clock more beautiful, but don't know how. I will be super grateful if anyone can make any suggestions.


Solution

  • You could do it by using pygame.time.set_timer() to make "tick events" be generated which cause the clock's image to be updated when encountered in the event processing loop.

    To make implementing this easier, an update() method could be added to the DigitalClock class (which is what I renamed your generic TextPicture class) which only updates the image, but leaving the current location alone:

    import datetime
    import sys
    import time
    import pygame
    
    class DigitalClock(pygame.sprite.Sprite):
        def __init__(self, speed, location):
            pygame.sprite.Sprite.__init__(self)
            self.speed = speed
            self.font = pygame.font.Font(None, 40)
            self.rect = pygame.Rect(location, (0, 0))  # placeholder
            self.update()
    
        def update(self):
            location = self.rect.left, self.rect.top  # save position
            time_text = datetime.datetime.now().strftime("%H:%M:%S")
            self.image = self.font.render(time_text, 1, [0, 0, 0])
            self.rect = self.image.get_rect()
            self.rect.left, self.rect.top = location  # restore position
    
        def move(self):
            self.rect = self.rect.move(self.speed)
            if (self.rect.left < 0
                or self.rect.left > screen.get_width()-self.image.get_width()):
                self.speed[0] = -self.speed[0]
            if (self.rect.top < 0
                or self.rect.top > screen.get_height()-self.image.get_height()):
                self.speed[1] = -self.speed[1]
    

    Following that, you'd need to modify the processing to be something along these lines:

    pygame.init()
    framerate_clock = pygame.time.Clock()
    screen = pygame.display.set_mode([640, 480])
    my_digital_clock = DigitalClock([1, 1], [50, 50])
    TICK_EVENT = pygame.USEREVENT + 1
    pygame.time.set_timer(TICK_EVENT, 1000)  # periodically create TICK_EVENT
    
    while True:
        for event in pygame.event.get():
            if event.type == TICK_EVENT:
                my_digital_clock.update()  # call new method
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
    
        screen.fill([255, 255, 255])
        my_digital_clock.move()
        screen.blit(my_digital_clock.image, my_digital_clock.rect)
    
        framerate_clock.tick(60)  # limit framerate
        pygame.display.flip()
    

    You could make it more beautiful by using a different font and color. Generally anything that made it look more realistic would be an improvement. It might be cool to make the colons between the digit characters blink on and off (using a similar technique).