Skip to content

Instantly share code, notes, and snippets.

@iamevn
Created August 25, 2020 00:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iamevn/4af0c2fc1ee596650cd50d473c5d9bf9 to your computer and use it in GitHub Desktop.
Save iamevn/4af0c2fc1ee596650cd50d473c5d9bf9 to your computer and use it in GitHub Desktop.
simple tk canvas to play around with
#/usr/bin/env python3
import tkinter as tk
import random
import threading
from wrapt import synchronized
from typing import Callable, Sequence, Union
class ScaledCanvasWindow:
'''
Tkinter window that just shows an updatable canvas.
initializer args:
t: tkinter.Tk instance
width, height, and scale: integers for the canvas size.
width and height are number of tiles and scale is the pixel size of a tile
initial_color: is a string used to fill out the window (defaults to black)
thread_count: integer number of threads to start with update_fn (defaults to 0)
update_fn: thread function. takes window (the ScaledCanvasWindow instance) and
thread_id (between 0 and thread_count) as args
'''
def __init__(
self, t: tk.Tk,
width: int = 100,
height: int = 100,
scale: int = 2,
initial_color: str ='#%02x%02x%02x' % (0, 0, 0),
thread_count: int = 0,
update_fn: Callable[['ScaledCanvasWindow', int], None]= lambda window, thread_id: None):
self.width = width
self.height = height
self.scale = scale
self.p_width = width * scale
self.p_height = height * scale
self.i = tk.PhotoImage(width=self.p_width, height=self.p_height)
self.i.put(initial_color, (0, 0, self.p_height, self.p_width))
c = tk.Canvas(t, width=self.p_width, height=self.p_height, borderwidth=0, highlightthickness=0)
c.pack()
c.create_image(0, 0, image=self.i, anchor=tk.NW)
self.threads = []
for i in range(thread_count):
t = threading.Thread(target=update_fn, args=(self, i))
t.daemon = True # kill thread when program exits
self.threads.append(t)
t.start()
@synchronized
def update_point(self, x: int, y: int, colorhex: Union[str, Sequence[int]]):
'''
update a tile at x, y to the given color
colorhex should be a string but may be a sequence of integers
'''
if str(colorhex) != colorhex:
colorhex = '#%02x%02x%02x' % tuple(colorhex)
x0 = x * self.scale
y0 = y * self.scale
self.i.put(colorhex, (y0, x0, y0 + self.scale, x0 + self.scale))
# random test window
W = 32
H = 32
SCALE = 32
THREAD_COUNT = 2
def update_fn(window: ScaledCanvasWindow, thread_id: int):
'''
random initial color, pick a channel (r, g, or b) and randomize just that channel each step
update a random tile in window with that color each step
'''
base_color = [random.randint(0, 255) for i in range(3)]
while True:
pt = (random.randint(0, W), random.randint(0, H))
base_color[thread_id % 3] = random.randint(0, 255)
window.update_point(pt[0], pt[1], base_color)
if __name__ == '__main__':
t = tk.Tk()
a = ScaledCanvasWindow(
t, W, H, SCALE,
thread_count=THREAD_COUNT,
update_fn=update_fn)
t.mainloop()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment