Some live coding to draw on the screen. I’ve already made this once, but I wanted to make it simple because I have intention to add this feature to my latest project called pygpoint, a mix among pygame and powerpoint to show slides that are images like in powerpoint. In the last version of this program I added a blackboard where you can draw, but in another window. Now I want to add the feature so that you can also draw on the slides and have the chance to save also the image with the drawings on.
So this is the code to implement this. Next time I will add it to pygpoint.
The code
import pygame as pg # pip install pygame==2.0.0.dev10 """ With this program you can draw on the screen with pygame pythonprogramming.altervista.org """ def init(): global screen pg.init() screen = pg.display.set_mode((400, 400)) mainloop() drawing = False last_pos = None w = 1 color = (255, 0, 255) def draw(event): global drawing, last_pos, w if event.type == pg.MOUSEMOTION: if (drawing): mouse_position = pg.mouse.get_pos() if last_pos is not None: pg.draw.line(screen, color, last_pos, mouse_position, w) last_pos = mouse_position elif event.type == pg.MOUSEBUTTONUP: mouse_position = (0, 0) drawing = False last_pos = None elif event.type == pg.MOUSEBUTTONDOWN: drawing = True def mainloop(): global screen loop = 1 while loop: # checks every user interaction in this list for event in pg.event.get(): if event.type == pg.QUIT: loop = 0 if event.type == pg.KEYDOWN: if event.key == pg.K_s: pg.image.save(screen, "image.png") draw(event) pg.display.flip() pg.quit() init()
The live coding video of drawing on the screen with pygame
This project on repl.it
How to clear the screen
drawnsave2.py
=============
changes:
c to clear the screen:
I simply paint the screen in black when hit c key
screen.fill((0, 0, 0))
The code in the while loop in the mainloop function
if event.type == pg.KEYDOWN: if event.key == pg.K_s: pg.image.save(screen, "image.png") if event.key == pg.K_c: screen.fill((0, 0, 0))
Save multiple images
With the following changes you can save different images with different names, progressively ordinated.
import pygame as pg # pip install pygame==2.0.0.dev10 """ With this program you can draw on the screen with pygame pythonprogramming.altervista.org drawnsave2.py ============= changes: c to clear the screen: I simply paint the screen in black when hit c key screen.fill((0, 0, 0)) """ def init(): global screen pg.init() screen = pg.display.set_mode((400, 400)) mainloop() drawing = False last_pos = None w = 1 color = (255, 0, 255) def draw(event): global drawing, last_pos, w if event.type == pg.MOUSEMOTION: if (drawing): mouse_position = pg.mouse.get_pos() if last_pos is not None: pg.draw.line(screen, color, last_pos, mouse_position, w) last_pos = mouse_position elif event.type == pg.MOUSEBUTTONUP: mouse_position = (0, 0) drawing = False last_pos = None elif event.type == pg.MOUSEBUTTONDOWN: drawing = True def mainloop(): global screen loop = 1 imagecount = 0 while loop: # checks every user interaction in this list for event in pg.event.get(): if event.type == pg.QUIT: loop = 0 if event.type == pg.KEYDOWN: if event.key == pg.K_s: if imagecount < 10: imagecount = "0" + str(imagecount) pg.image.save(screen, "image{}.png".format(imagecount)) imagecount = int(imagecount) imagecount +=1 if event.key == pg.K_c: screen.fill((0, 0, 0)) draw(event) pg.display.flip() pg.quit() init()
Lets see the images with imageslider
With this code you can opend another python file (I made this some times ago) to watch the files you created).
if event.key == pg.K_i: os.startfile("imageslider.py")
imageslider.py
This is the code of the program to watch the images
import tkinter as tk import glob from PIL import Image, ImageTk import os def insertfiles(): "loads the list of files in the directory" for filename in glob.glob("*.png"): lst.insert(tk.END, filename) def delete_item(event): "Deletes a file in the list: called by lst.bind('<Control-d>', delete_item)" n = lst.curselection() os.remove(lst.get(n)) lst.delete(n) def get_window_size(): "Returns the width and height of the screen to set images and canvas alike it: called by root.bind <Configure>" root_w = root.winfo_width() if root.winfo_width() > 200 and root.winfo_height() >30: w = root.winfo_width() - 200 h = root.winfo_height() - 30 else: w = 200 h = 30 return w, h def showimg(event): "takes the selected image to show it, called by root.bind <Configure> and lst.bind <<ListboxSelect>>" n = lst.curselection() filename = lst.get(n) im = Image.open(filename) im = im.resize((get_window_size()), Image.ANTIALIAS) img = ImageTk.PhotoImage(im) w, h = img.width(), img.height() canvas.image = img canvas.config(width=w, height=h) canvas.create_image(0, 0, image=img, anchor=tk.NW) root.bind("<Configure>", lambda x: showimg(x)) root = tk.Tk() root.geometry("800x600+300+50") lst = tk.Listbox(root, width=20) lst.pack(side="left", fill=tk.BOTH, expand=0) lst.bind("<<ListboxSelect>>", showimg) lst.bind("<Control-d>", delete_item) insertfiles() canvas = tk.Canvas(root) canvas.pack() root.mainloop()
Now you will see something like this
Let’s use it as an animator and the imageslider inside the main file
Now we can create gif pressing g and we can see the images in the image slider without the external file, because we put that code into a class insider the main file. Here is the code:
import pygame as pg import os import glob from PIL import Image import tkinter as tk from PIL import Image, ImageTk # pip install pygame==2.0.0.dev10 """ With this program you can draw on the screen with pygame pythonprogramming.altervista.org drawnsave2.py ============= changes: c to clear the screen: I simply paint the screen in black when hit c key screen.fill((0, 0, 0)) You can save all images with different progressive names You can see the images with imageslider pressing i drawnsave4.py added g to make gif from saved files now i opens imageslider from inside the progam drawnsave.py without external programs """ def init(): global screen pg.init() screen = pg.display.set_mode((400, 400)) mainloop() drawing = False last_pos = None w = 1 color = (255, 0, 255) def draw(event): global drawing, last_pos, w if event.type == pg.MOUSEMOTION: if (drawing): mouse_position = pg.mouse.get_pos() if last_pos is not None: pg.draw.line(screen, color, last_pos, mouse_position, w) last_pos = mouse_position elif event.type == pg.MOUSEBUTTONUP: mouse_position = (0, 0) drawing = False last_pos = None elif event.type == pg.MOUSEBUTTONDOWN: drawing = True def mainloop(): global screen loop = 1 imagecount = 0 while loop: # checks every user interaction in this list for event in pg.event.get(): if event.type == pg.QUIT: loop = 0 if event.type == pg.KEYDOWN: if event.key == pg.K_s: if imagecount < 10: imagecount = "0" + str(imagecount) pg.image.save(screen, "image{}.png".format(imagecount)) imagecount = int(imagecount) imagecount +=1 if event.key == pg.K_c: screen.fill((0, 0, 0)) if event.key == pg.K_i: ImgSlide() elif event.key == pg.K_g: frames = [] imgs = glob.glob("*.png") for i in imgs: new_frame = Image.open(i) frames.append(new_frame) # Save into a GIF file that loops forever frames[0].save('animated.gif', format='GIF', append_images=frames[1:], save_all=True, duration=300, loop=0) os.startfile("animated.gif") draw(event) pg.display.flip() pg.quit() class ImgSlide(): def __init__(self): self.root = tk.Tk() self.root.geometry("800x600+300+50") self.lst = tk.Listbox(self.root, width=20) self.lst.pack(side="left", fill=tk.BOTH, expand=0) self.lst.bind("<<ListboxSelect>>", self.showimg) self.lst.bind("<Control-d>", self.delete_item) self.canvas = tk.Canvas(self.root) self.canvas.pack() self.insertfiles() self.root.mainloop() def insertfiles(self): "loads the list of files in the directory" for filename in glob.glob("*.png"): self.lst.insert(tk.END, filename) def delete_item(self, event): "Deletes a file in the list: called by self.lst.bind('<Control-d>', delete_item)" n = self.lst.curselection() os.remove(lst.get(n)) lst.delete(n) def get_window_size(self): "Returns the width and height of the screen to set images and self.canvas alike it: called by self.root.bind <Configure>" self.root_w = self.root.winfo_width() if self.root.winfo_width() > 200 and self.root.winfo_height() >30: w = self.root.winfo_width() - 200 h = self.root.winfo_height() - 30 else: w = 200 h = 30 return w, h def showimg(self, event): "takes the selected image to show it, called by self.root.bind <Configure> and lst.bind <<ListboxSelect>>" n = self.lst.curselection() filename = self.lst.get(n) im = Image.open(filename) im = im.resize((self.get_window_size()), Image.ANTIALIAS) img = ImageTk.PhotoImage(im) w, h = img.width(), img.height() self.canvas.image = img self.canvas.config(width=w, height=h) self.canvas.create_image(0, 0, image=img, anchor=tk.NW) self.root.bind("<Configure>", lambda x: self.showimg(x)) init()
Subscribe to the newsletter for updates
Tkinter templates
My youtube channel
Twitter: @pythonprogrammi - python_pygame