-
-
Save nikhilkumarsingh/85501ee2c3d8c0cfa9d1a27be5781f06 to your computer and use it in GitHub Desktop.
from tkinter import * | |
from tkinter.colorchooser import askcolor | |
class Paint(object): | |
DEFAULT_PEN_SIZE = 5.0 | |
DEFAULT_COLOR = 'black' | |
def __init__(self): | |
self.root = Tk() | |
self.pen_button = Button(self.root, text='pen', command=self.use_pen) | |
self.pen_button.grid(row=0, column=0) | |
self.brush_button = Button(self.root, text='brush', command=self.use_brush) | |
self.brush_button.grid(row=0, column=1) | |
self.color_button = Button(self.root, text='color', command=self.choose_color) | |
self.color_button.grid(row=0, column=2) | |
self.eraser_button = Button(self.root, text='eraser', command=self.use_eraser) | |
self.eraser_button.grid(row=0, column=3) | |
self.choose_size_button = Scale(self.root, from_=1, to=10, orient=HORIZONTAL) | |
self.choose_size_button.grid(row=0, column=4) | |
self.c = Canvas(self.root, bg='white', width=600, height=600) | |
self.c.grid(row=1, columnspan=5) | |
self.setup() | |
self.root.mainloop() | |
def setup(self): | |
self.old_x = None | |
self.old_y = None | |
self.line_width = self.choose_size_button.get() | |
self.color = self.DEFAULT_COLOR | |
self.eraser_on = False | |
self.active_button = self.pen_button | |
self.c.bind('<B1-Motion>', self.paint) | |
self.c.bind('<ButtonRelease-1>', self.reset) | |
def use_pen(self): | |
self.activate_button(self.pen_button) | |
def use_brush(self): | |
self.activate_button(self.brush_button) | |
def choose_color(self): | |
self.eraser_on = False | |
self.color = askcolor(color=self.color)[1] | |
def use_eraser(self): | |
self.activate_button(self.eraser_button, eraser_mode=True) | |
def activate_button(self, some_button, eraser_mode=False): | |
self.active_button.config(relief=RAISED) | |
some_button.config(relief=SUNKEN) | |
self.active_button = some_button | |
self.eraser_on = eraser_mode | |
def paint(self, event): | |
self.line_width = self.choose_size_button.get() | |
paint_color = 'white' if self.eraser_on else self.color | |
if self.old_x and self.old_y: | |
self.c.create_line(self.old_x, self.old_y, event.x, event.y, | |
width=self.line_width, fill=paint_color, | |
capstyle=ROUND, smooth=TRUE, splinesteps=36) | |
self.old_x = event.x | |
self.old_y = event.y | |
def reset(self, event): | |
self.old_x, self.old_y = None, None | |
if __name__ == '__main__': | |
Paint() |
PVkolos
commented
Apr 24, 2021
Thank you @nikhilkumarsingh. I have updated the code a bit. May I upload that code on my git, crediting you for base code?
code to completely clear the canvas ?
thank you in advance
and also is there any way to save my "Masterpiece"
&
how to implement eraser tool in this app? I mean not just painting white...
@andreys42 & @RVSNS try this fork by me - https://gist.github.com/Kaabasane/a4f1fb10d27611bdd6b4ccf6b9206a9b
Thank you.
can you do a save option? i have a similar program but i don't know how to make a file save option
hello
how can i paint in turtle in python with(alt)kebind?
Can someone review my code . I am not getting final expected output - import tkinter as tk
import zipfile
import os
create a directory to store the extracted images
if not os.path.exists('images'):
os.mkdir('images')
extract the contents of the images.zip file to the images directory
with zipfile.ZipFile('images.zip', 'r') as zip_ref:
zip_ref.extractall('images')
#Step 1: Import necessary libraries
from tkinter import *
from tkinter import ttk
from PIL import Image, ImageTk
#Step 2: Create a class for the Pizza Builder app and extend it from the tk.Frame class
class PizzaBuilderApp(Frame):
def __init__(self, parent):
super().__init__(parent)
#Step 3: Create the overall layout of the app using grid geometry manager
self.grid(column=0, row=0, sticky=(N, W, E, S))
self.columnconfigure(0, weight=1)
self.rowconfigure(0, weight=1)
#Step 4: Create a separator widget to separate each section of the app
ttk.Separator(self, orient="horizontal").grid(row=0, column=0, sticky="ew")
#Step 5: Create radio buttons for pizza size options
size_label = Label(self, text="Pizza Size")
size_label.grid(row=1, column=0, sticky=W, padx=5)
self.size_var = StringVar(value="Small")
size_options = ["Small", "Medium", "Large"]
for i, size in enumerate(size_options):
Radiobutton(self, text=size, variable=self.size_var, value=size, command=self.update_pizza_image).grid(row=2, column=i, padx=5)
#Step 6: Create radio buttons for crust options
crust_label = Label(self, text="Crust")
crust_label.grid(row=3, column=0, sticky=W, padx=5)
self.crust_var = StringVar(value="New York Thin Crust")
crust_options = ["New York Thin Crust", "Chicago Deep Dish"]
for i, crust in enumerate(crust_options):
Radiobutton(self, text=crust, variable=self.crust_var, value=crust, command=self.update_pizza_image).grid(row=4, column=i, padx=5)
#Step 7: Create an OptionMenu for sauce options
sauce_label = Label(self, text="Sauce")
sauce_label.grid(row=5, column=0, sticky=W, padx=5)
self.sauce_var = StringVar(value="Tomato")
sauce_options = ["Tomato", "Pesto", "Barbecue", "Alfredo"]
sauce_menu = OptionMenu(self, self.sauce_var, *sauce_options, command=self.update_pizza_image)
sauce_menu.grid(row=6, column=0, padx=5, pady=5)
#Step 8: Create a ListBox for cheese options
cheese_label = Label(self, text="Cheese")
cheese_label.grid(row=7, column=0, sticky=W, padx=5)
self.cheese_var = StringVar(value="Normal")
cheese_options = ["None", "Normal", "Extra"]
cheese_listbox = Listbox(self, listvariable=self.cheese_var, selectmode=SINGLE, height=len(cheese_options))
for i, cheese in enumerate(cheese_options):
cheese_listbox.insert(i, cheese)
cheese_listbox.grid(row=8, column=0, padx=5, pady=5)
cheese_scrollbar = Scrollbar(self, orient="vertical", command=cheese_listbox.yview)
cheese_scrollbar.grid(row=8, column=1, sticky=N+S)
cheese_listbox.configure(yscrollcommand=cheese_scrollbar.set)
#Step 9: Implement the "Build Pizza" Button
class PizzaBuilder(Frame):
def init(self, parent):
super().init(parent)
# create "Build Pizza" button
self.build_button = Button(self, text="Build Pizza", command=self.build_pizza_handler)
self.build_button.grid(row=9, column=0, padx=5, pady=5)
#build_button = Button(self, text="Build Pizza", command=self.build_pizza_handler)
#build_button.grid(row=9, column=0, padx=5, pady=5)
def build_pizza_handler(self):
# Collect user's selected options
pizza_size = self.pizza_size.get()
crust = self.crust.get()
sauce = self.sauce.get()
cheeses = self.cheeses.curselection()
toppings = [topping.get() for topping in self.toppings]
seasoning = self.seasoning_var.get()
# Create a list of images to stack on top of each other
images = []
images.append(Image.open(f'images/crust_{crust.lower().replace(" ", "_")}.png'))
images.append(Image.open(f'images/sauce_{sauce.lower().replace(" ", "_")}.png'))
if "0" not in cheeses:
images.append(Image.open(f'images/cheese_normal.png'))
if "1" in cheeses:
images.append(Image.open(f'images/cheese_extra.png'))
for i, topping_selected in enumerate(toppings):
if topping_selected:
images.append(Image.open(f'images/topping_{i+1}.png'))
if seasoning:
images.append(Image.open('images/seasoning.png'))
# Resize images to 600x600
images_resized = []
for image in images:
image_resized = image.resize((600, 600))
images_resized.append(image_resized)
# Create a composite image
pizza_image = Image.new('RGBA', (600, 600), (255, 255, 255, 0))
for image in images_resized:
pizza_image = Image.alpha_composite(pizza_image, image)
# Display the composite image on the GUI
pizza_image_tk = ImageTk.PhotoImage(pizza_image)
self.pizza_display_label.config(image=pizza_image_tk)
self.pizza_display_label.image = pizza_image_tk
# Create a new blank image to paste the pizza layers onto
pizza_image = Image.new('RGBA', (600, 600), (255, 255, 255, 255))
# Paste each layer onto the pizza image
for img in images:
pizza_image.paste(img, (0, 0), img)
# Display the final pizza image
pizza_image.show()
############################################################################################
def update_pizza_image(self):
# Collect user's selected options
pizza_size = self.size_var.get()
crust = self.crust_var.get()
sauce = self.sauce_var.get()
# Load the crust and sauce images
crust_image = Image.open(f'images/crust_{crust.lower().replace(" ", "_")}.png')
sauce_image = Image.open(f'images/sauce_{sauce.lower().replace(" ", "_")}.png')
# Resize the crust and sauce images based on the pizza size
if pizza_size == 'Small':
crust_image = crust_image.resize((200, 200))
sauce_image = sauce_image.resize((200, 200))
elif pizza_size == 'Medium':
crust_image = crust_image.resize((300, 300))
sauce_image = sauce_image.resize((300, 300))
else:
crust_image = crust_image.resize((400, 400))
sauce_image = sauce_image.resize((400, 400))
# Combine the crust and sauce images into one
pizza_image = Image.alpha_composite(crust_image, sauce_image)
# Display the pizza image
self.pizza_image_tk = ImageTk.PhotoImage(pizza_image)
self.pizza_image_label.config(image=self.pizza_image_tk)
def build_pizza_handler(self):
# Collect user's selected options
pizza_size = self.size_var.get()
crust = self.crust_var.get()
sauce = self.sauce_var.get()
cheeses = self.cheese_var.get()
toppings = [topping_var.get() for topping_var in self.topping_vars]
seasoning = self.seasoning_var.get()
# Create a list of images to stack on top of each other
images = []
crust_image = Image.open(f'images/crust_{crust.lower().replace(" ", "_")}.png')
images.append(crust_image)
sauce_image = Image.open(f'images/sauce_{sauce.lower().replace(" ", "_")}.png')
images.append(sauce_image)
if cheeses == "Normal":
cheese_image = Image.open(f'images/cheese_normal.png')
images.append(cheese_image)
elif cheeses == "Extra":
cheese_image = Image.open(f'images/cheese_extra.png')
images.append(cheese_image)
for i, topping_selected in enumerate(toppings):
if topping_selected:
topping_image = Image.open(f'images/topping_{i+1}.png')
images.append(topping_image)
if seasoning:
seasoning_image = Image.open('images/seasoning.png')
images.append(seasoning_image)
############################################################################################
#Step 10: Initialize the GUI
class PizzaBuilder(tk.Frame):
def init(self, parent):
super().init(parent)
if name == 'main':
root = tk.Tk()
root.title("Procedural Object-Oriented Pizza Company")
root.geometry("800x600")
pizza_builder = PizzaBuilder(root)
pizza_builder.pack(expand=True, fill='both')
root.mainloop()
################################################################################################
import os
import uuid
import base64
from PIL import Image
from io import BytesIO
from typing import Dict, List
from fastapi import FastAPI, HTTPException, status
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
app = FastAPI()
Allow Cross-Origin Resource Sharing (CORS)
app.add_middleware(
CORSMiddleware,
allow_origins=[""],
allow_credentials=True,
allow_methods=[""],
allow_headers=["*"],
)
class Pizza(BaseModel):
crust: str
cheese: List[str]
sauce: str
toppings: List[str]
def generate_pizza_image(pizza: Pizza) -> str:
# Load the pizza image
pizza_image_path = os.path.join("images", "pizza.jpg")
pizza_image = Image.open(pizza_image_path)
# Resize the pizza image
pizza_image = pizza_image.resize((500, 500))
# Add the selected toppings to the pizza image
toppings_path = os.path.join("images", "toppings")
for topping in pizza.toppings:
topping_path = os.path.join(toppings_path, f"{topping}.png")
topping_image = Image.open(topping_path)
pizza_image.paste(topping_image, (0, 0), topping_image)
# Convert the pizza image to base64 string
buffered = BytesIO()
pizza_image.save(buffered, format="PNG")
return base64.b64encode(buffered.getvalue()).decode()
@app.post("/build_pizza")
async def build_pizza_handler(pizza: Pizza):
try:
# Generate the pizza image
pizza_image = generate_pizza_image(pizza)
# Return the pizza image as a base64 string
return {"pizza_image": pizza_image}
except Exception as e:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=str(e)
)