Changing Background Colour with a While Loop in Python

78 Views Asked by At

I am trying to configure a label in my window with the result of an iteration that produces the range of hexadecimal colour codes from #000000 to #FFFFFF so that the label’s background colour fades through all the possible colors between #000000 and #FFFFFF with a fraction of a second interval but it doesn’t seem to complete the loop before stating at #000000 again.

I have used the the print method to display the colour code being deployed with every loop and it doesn’t seem to be restarting as the display does.

from time import *
from time import sleep
from tkinter import *


def changing_color():
    global color
    while True:
        for i in range(0, 2**24):
            r = format(i, "02x")
            for j in range(0, 255):
                g = format(j, "02x")
                for k in range(0, 255):
                    b = format(k, "02x")
                    color = "#"+r+g+b
                    print(color)
                    date_label.config(bg=color)
                    day_label.config(bg=color)
                    window.update()
                    sleep(0.01)


def update_frame1():

    day_string = strftime("%A")
    day_label.config(text=day_string)

    date_string = strftime("%d, %B %Y")
    date_label.config(text=date_string)

    frame1.after(1000, update_frame1)

def update_frame2():

    time_string = strftime("%I:%M:%S:%p")
    time_label.config(text=time_string)

    frame2.after(1000, update_frame2)


window = Tk()
window.title("RO'Clock")

color = ""


frame1 = Frame(window)
frame1.pack(expand=True, fill="both")

frame2 = Frame(window)
frame2.pack(expand=True, fill="both")

date_label = Label(frame1, font=("Ink Free", 20))
date_label.pack(expand=True, fill="both")

day_label = Label(frame1, font=("Ink Free", 15))
day_label.pack(expand=True, fill="both")

time_label = Label(frame2, font=("Consolas", 30), fg="#00FF00", bg="black")
time_label.pack(expand=True, fill="both")


update_frame2()

update_frame1()

changing_color()


window.mainloop()
1

There are 1 best solutions below

0
Jan_B On BEST ANSWER

I cleaned your imports and translated it into an OOP approach for better readability and also to get rid of global variables. Your endless loop is now a recursive function using after and incrementing the color values each cycle.

from tkinter import Tk, Frame, Label
from time import strftime


class RoClock(Tk):
    def __init__(self):
        super().__init__()
        self.title("RO'Clock")
        self.color = ""

        self.frame1 = Frame(self)
        self.frame1.pack(expand=True, fill="both")

        self.frame2 = Frame(self)
        self.frame2.pack(expand=True, fill="both")

        self.date_label = Label(self.frame1, font=("Ink Free", 20))
        self.date_label.pack(expand=True, fill="both")

        self.day_label = Label(self.frame1, font=("Ink Free", 15))
        self.day_label.pack(expand=True, fill="both")

        self.time_label = Label(self.frame2, font=("Consolas", 30), fg="#00FF00", bg="black")
        self.time_label.pack(expand=True, fill="both")

        self.update_frame2()

        self.update_frame1()

        self.changing_color(0, 0, 0)  # passing starting values

    def changing_color(self, k, j, i):  # new recursive function using after instead of endless while loop
        if k == 256:
            k = 0
            j += 1
        if j == 256:
            j = 0
            i += 1
        if i == 256:
            i = 0

        r = format(i, "02x")
        g = format(j, "02x")
        b = format(k, "02x")
        color = "#"+r+g+b
        print(color)
        self.date_label.config(bg=color)
        self.day_label.config(bg=color)
        self.after(1, self.changing_color, k+1, j, i)

    def update_frame1(self):
        day_string = strftime("%A")
        self.day_label.config(text=day_string)

        date_string = strftime("%d, %B %Y")
        self.date_label.config(text=date_string)

        self.frame1.after(1000, self.update_frame1)

    def update_frame2(self):
        time_string = strftime("%I:%M:%S:%p")
        self.time_label.config(text=time_string)

        self.frame2.after(1000, self.update_frame2)

r = RoClock()
r.mainloop()

While this is working it is not pretty! To get rid of the flickering you have to rethink how you calculate your colors to get colors of equal brightness!