How to make a Paint App using Python and Tkinter

TSB Everything
14 min readOct 24, 2023

--

By Aarush Mehta

Python
Here is What You can expect by the end of this article

Want to make a Clone or Replica of Something similar to MS Paint or Google Canvas? Don’t Have any prior experience? Well Don’t Worry.. I’ve Got you Covered…

In this medium article, I’ll tell you how you can build an application similar to paint and gcanvas using Python and Tkinter Module..

So Let’s Begin…

Step 0: About Tkinter

Tkinter is a popular Python library used for creating graphical user interfaces (GUIs). It provides a set of tools and widgets for building desktop applications with interactive and visually appealing interfaces. Tkinter is a standard library in Python, which means it comes bundled with Python installations, making it readily accessible for developers.

With Tkinter, developers can create windows, buttons, labels, input fields, and various other GUI components. These elements can be arranged and customized to design intuitive applications. Tkinter follows the object-oriented programming paradigm, allowing developers to create GUI elements as objects and manipulate them using methods and attributes.

Step 1: Install Tkinter in Python

pip install tkinter

Step 2: Import Required Things from Tkinter

########### Imports ###########

from tkinter import Tk, Frame, Canvas, CENTER, Button, NW, Label, SOLID
from tkinter import colorchooser, filedialog, OptionMenu, messagebox
from tkinter import DOTBOX, StringVar, simpledialog

import os
import pickle

Let’s Understand What are these tools

from tkinter import Tk, Frame, Canvas, CENTER, Button, NW, Label, SOLID: This line imports specific classes and constants from the tkinter library. Here's what each one does:

  • Tk: Represents the main window of the application.
  • Frame: Provides a rectangular area in which widgets can be placed.
  • Canvas: Allows drawing and rendering shapes, images, and other graphical elements.
  • CENTER: A constant used for alignment within widgets.
  • Button: Creates a button widget.
  • NW: A constant representing the northwest direction.
  • Label: Creates a label widget for displaying text or images.
  • SOLID: A constant representing a solid line style for drawing.

from tkinter import colorchooser, filedialog, OptionMenu, messagebox: This line imports additional modules from tkinter for specific functionalities:

  • colorchooser: Provides a dialog for selecting colors.
  • filedialog: Provides dialogs for file-related operations like opening and saving files.
  • OptionMenu: Creates a widget that allows the user to select from a list of options.
  • messagebox: Provides a way to show various types of message boxes (info, warning, error, etc.) to the user.

from tkinter import DOTBOX, StringVar, simpledialog: This line imports more constants and classes:

  • DOTBOX: A constant representing a dotted line style for drawing.
  • StringVar: A class for creating mutable string variables that can be linked to widgets.
  • simpledialog: Provides a simple and easy-to-use interface for creating dialogs to get input from the user.

import os: Imports the os module, which provides a way to use operating system-dependent functionality. This can be used for tasks like file and directory operations.

import pickle: Imports the pickle module, which is used for serializing and deserializing Python objects. It allows you to store complex data structures in a file, which can be reconstructed later in the same or another Python script.

Step 3: Root Window & Windo Settings

########### Imports ###########

from tkinter import Tk, Frame, Canvas, CENTER, Button, NW, Label, SOLID
from tkinter import colorchooser, filedialog, OptionMenu, messagebox
from tkinter import DOTBOX, StringVar, simpledialog

import os
import pickle

########### Window Settings ###########

root = Tk()

root.title("Paint - ECTS v1.0")
root.geometry("1100x650")

root.resizable(False, False)
  1. root = Tk(): This line creates the main window for the application. Tk() is a class in the tkinter library that represents the main window of the application. By calling Tk(), you create an instance of this class, which becomes your main application window. This window is referred to as root in this code.
  2. root.title("Paint - ECTS v1.0"): Sets the title of the main window to "Paint - ECTS v1.0". The title appears in the title bar of the window when the application is running. You can change the text inside the parentheses to set a different title for your application.
  3. root.geometry("1100x650"): Sets the initial size of the main window to 1100 pixels in width and 650 pixels in height. The window will be displayed with these dimensions when the application starts. You can adjust the numbers to set a different initial size for your window.
  4. root.resizable(False, False): This line disables the ability to resize the window both horizontally and vertically. The first argument False prevents horizontal resizing, and the second argument False prevents vertical resizing. By setting both arguments to False, the window will have a fixed size, and users won't be able to resize it by dragging the window borders. If you set either or both arguments to True, the window would be resizable in the corresponding direction(s).

Step 4: Creating Frames, Button and Labels

########### Imports ###########

from tkinter import Tk, Frame, Canvas, CENTER, Button, NW, Label, SOLID
from tkinter import colorchooser, filedialog, OptionMenu, messagebox
from tkinter import DOTBOX, StringVar, simpledialog

import os
import pickle

########### Window Settings ###########

root = Tk()

root.title("Paint - ECTS v1.0")
root.geometry("1100x650")

root.resizable(False, False)

########### Paint App ###########

#### Paint Tools Frame ####

# Main Frame
frame1 = Frame(root, height=150, width=1100)
frame1.grid(row=0, column=0)

# Holder Frame
holder = Frame(frame1, height=120, width=1000, bg="white", padx=6, pady=10)
holder.grid(row=0, column=0, sticky=NW)
holder.place(relx=0.5, rely=0.5, anchor=CENTER)

holder.columnconfigure(0, minsize=120)
holder.columnconfigure(1, minsize=120)
holder.columnconfigure(2, minsize=120)
holder.columnconfigure(3, minsize=120)
holder.columnconfigure(4, minsize=120)

holder.rowconfigure(0, minsize=30)

#### Tools ####

# Label for Tool 1,2,3
label123 = Label(holder, text="TOOLS", borderwidth=1, relief=SOLID, width=15)
label123.grid(row=0, column=0)

# Tool 1 - Pencil
pencilButton = Button(holder, text="Pencil", height=1, width=12, command=pencil)
pencilButton.grid(row=1, column=0)

# Tool 2 - Eraser
eraserButton = Button(holder, text="Eraser", height=1, width=12, command=eraser)
eraserButton.grid(row=2, column=0)

# Tool 3 - Color Change
colorButton = Button(
holder, text="Select Color", height=1, width=12, command=colorChoice
)
colorButton.grid(row=3, column=0)

#### FILE ACTIONS ####

# Label for Tool 4,5,6
label456 = Label(holder, text="FILE", borderwidth=1, relief=SOLID, width=15)
label456.grid(row=0, column=1)

# Tool 4 - Save File
saveButton = Button(holder, text="SAVE", height=1, width=12, command=saveImg)
saveButton.grid(row=1, column=1)

# Tool 5 - Open File
openButton = Button(holder, text="OPEN", height=1, width=12, command=openEcts)
openButton.grid(row=2, column=1)

# Tool 6 - New Paint
newButton = Button(holder, text="NEW", height=1, width=12, command=newApp)
newButton.grid(row=3, column=1)

#### OTHER ####

# Label for Tool 7 and 8
label7 = Label(holder, text="OTHER", borderwidth=1, relief=SOLID, width=15)
label7.grid(row=0, column=2)

# Tool 7 - Clear Screen
clearButton = Button(holder, text="CLEAR", height=1, width=12, command=clearScreen)
clearButton.grid(row=1, column=2)

# Tool 8 - Exit App
exitButton = Button(
holder, text="Exit", height=1, width=12, command=lambda: root.destroy()
)
exitButton.grid(row=2, column=2)

#### Stroke Size ####

# Label for Tool 8, 9 and 10
label8910 = Label(holder, text="STROKE SIZE", borderwidth=1, relief=SOLID, width=15)
label8910.grid(row=0, column=3)

# Tool 8 - Increament by 1
sizeiButton = Button(holder, text="Increase", height=1, width=12, command=strokeI)
sizeiButton.grid(row=1, column=3)

# Tool 9 - Decreament by 1
sizedButton = Button(holder, text="Decrease", height=1, width=12, command=strokeD)
sizedButton.grid(row=2, column=3)

# Tool 10 - Default
defaultButton = Button(holder, text="Default", height=1, width=12, command=strokeDf)
defaultButton.grid(row=3, column=3)

#### Shapes ####

# Label for Tool 11,12,13
label1123 = Label(holder, text="SHAPES", borderwidth=1, relief=SOLID, width=15)
label1123.grid(row=0, column=4)

# Tool 11 - shapeSelector
shapeMenu = OptionMenu(holder, shapeSelect, *shapeList)
shapeMenu.grid(row=1, column=4)
shapeMenu.config(width=8)

# Tool 9 - Decreament by 1
dimentionButton = Button(
holder, text="Dimention", height=1, width=12, command=askShapeDimention
)
dimentionButton.grid(row=2, column=4)

# Tool 10 - Default
fillButton = Button(holder, text="Fill", height=1, width=12, command=shapeColorChoice)
fillButton.grid(row=3, column=4)

Let me explain the code section by section:

Paint Tools Frame Setup:

Main Frame Setup:

  • A main frame named frame1 is created within the root window. It has a height of 150 pixels and a width of 1100 pixels.
  • The grid method is used to specify the placement of the frame in the window.

Holder Frame Setup:

  • Within frame1, a holder frame named holder is created. It has a height of 120 pixels, width of 1000 pixels, a white background, 6 pixels of padding on the x-axis, and 10 pixels of padding on the y-axis.
  • The grid method is used to place the holder frame within frame1 with the sticky parameter set to NW (northwest).
  • relx=0.5, rely=0.5, and anchor=CENTER are used to center the holder frame within frame1.

Tool Layout Setup:

  • The holder frame is configured with columns and rows to organize the buttons and labels.

Tools and Actions Buttons Setup:

  • Tools 1–3: Pencil, Eraser, and Color Change Buttons.
  • Tools 4–6: Save, Open, and New Buttons for file actions.
  • Tools 7–8: Clear Screen and Exit App Buttons.
  • Tools 8–10: Increase, Decrease, and Default Stroke Size Buttons.
  • Tools 11–13: Shape Selector, Dimension, and Fill Buttons for drawing shapes.

Each tool/button is created using the Button widget from Tkinter and placed inside the holder frame in specified rows and columns.

Functions Associated with Buttons:

  • command=pencil, command=eraser, command=colorChoice, etc. Are the functions which we will be creating in the next steps.

Step 5: Creating a Canvas Frame and Canvas

#### Canvas Frame ####

# Main Frame
frame2 = Frame(root, height=500, width=1100)
frame2.grid(row=1, column=0)

# Making a Canvas
canvas = Canvas(frame2, height=450, width=1000, bg="white")
canvas.grid(row=0, column=0)
canvas.place(relx=0.5, rely=0.5, anchor=CENTER)
canvas.config(cursor="pencil")

# Event Binding
canvas.bind("<B1-Motion>", paint)
canvas.bind("<ButtonRelease-1>", paint)
canvas.bind("<Button-1>", paint)

The above code section is responsible for setting up a canvas within the paint application. Let me explain each part of the code:

Canvas Frame Setup:

Main Frame Setup:

  • A main frame named frame2 is created within the root window. It has a height of 500 pixels and a width of 1100 pixels.
  • The grid method is used to specify the placement of the frame in the window. It is placed in the second row (row=1) and the first column (column=0).

Canvas Creation:

  • A canvas widget named canvas is created within frame2. It has a height of 450 pixels, a width of 1000 pixels, and a white background.
  • The grid method is used to place the canvas inside frame2. It is placed in the first row (row=0) and the first column (column=0).
  • relx=0.5, rely=0.5, and anchor=CENTER are used to center the canvas within frame2.

Canvas Cursor Configuration:

  • The canvas cursor is set to “pencil”. This means that when the mouse is over the canvas, it will appear as a pencil cursor, indicating that the canvas is an area where drawing can take place.

Event Binding:

  • canvas.bind("<B1-Motion>", paint): This line binds the <B1-Motion> event to the paint function. The <B1-Motion> event occurs when the left mouse button is moved (dragged) while being pressed. The paint function is expected to handle the drawing logic when the mouse is moved.
  • canvas.bind("<ButtonRelease-1>", paint): This line binds the <ButtonRelease-1> event to the paint function. The <ButtonRelease-1> event occurs when the left mouse button is released after being pressed. This event is typically used to signal the end of a drawing action.
  • canvas.bind("<Button-1>", paint): This line binds the <Button-1> event to the paint function. The <Button-1> event occurs when the left mouse button is pressed. This binding likely indicates the start of a drawing action when the mouse button is initially pressed down.

Step 6: Creating all Suitable Functions and Variables

########### Functions ###########

# Variables
prevPoint = [0, 0]
currentPoint = [0, 0]

penColor = "black"
stroke = 1

canvas_data = []

shapeSelect = StringVar()
shapeList = ["None", "Square", "Circle/Oval", "Rectangle", "Line"]
shapeSelect.set("None")
shapeFill = "black"
width = 0
height = 0


# Increase Stroke Size By 1
def strokeI():
global stroke

if stroke != 10:
stroke += 1

else:
stroke = stroke


# Decrease Stroke Size By 1
def strokeD():
global stroke

if stroke != 1:
stroke -= 1

else:
stroke = stroke


def strokeDf():
global stroke
stroke = 1


# Pencil
def pencil():
global penColor

penColor = "black"
canvas["cursor"] = "pencil"


# Eraser
def eraser():
global penColor

penColor = "white"
canvas["cursor"] = DOTBOX


# Pencil Choose Color
def colorChoice():
global penColor

color = colorchooser.askcolor(title="Select a Color")
canvas["cursor"] = "pencil"

if color[1]:
penColor = color[1]

else:
pass


# Shape Color Chooser
def shapeColorChoice():
global shapeFill

color = colorchooser.askcolor(title="Select a Color")
canvas["cursor"] = "pencil"

if color[1]:
shapeFill = color[1]

else:
shapeFill = "black"


# Paint Function
def paint(event):
global prevPoint
global currentPoint

x = event.x
y = event.y

currentPoint = [x, y]

if prevPoint != [0, 0]:
canvas.create_polygon(
prevPoint[0],
prevPoint[1],
currentPoint[0],
currentPoint[1],
fill=penColor,
outline=penColor,
width=stroke,
)

prevPoint = currentPoint

if event.type == "5":
prevPoint = [0, 0]


# Close App
def newApp():
os.startfile("paint.py")


# Clear Screen
def clearScreen():
canvas.delete("all")


# Save Images
def saveImg():
global canvas_data
for obj in canvas.find_all():
obj_type = canvas.type(obj)
if obj_type == "polygon":
color = canvas.itemcget(obj, "fill")
coords = canvas.coords(obj)
canvas_data.append({"type": "polygon", "color": color, "coords": coords})

saveEcts()


# Saving the canvas data to ects files
def saveEcts():
global canvas_data
file_path = filedialog.asksaveasfilename(
defaultextension=".ects",
filetypes=[
("ECTS files", "*.ects"),
("PNG files", "*.png"),
("JPG files", "*.jpg"),
],
)
if file_path:
with open(file_path, "wb") as file:
pickle.dump(canvas_data, file)


# Opening already or earlier made ects files
def openEcts():
global canvas_data
file_path = filedialog.askopenfilename(
defaultextension=".ects",
filetypes=[
("ECTS files", "*.ects"),
("PNG files", "*.png"),
("JPG files", "*.jpg"),
],
)
if file_path:
with open(file_path, "rb") as file:
canvas_data = pickle.load(file)

redrawCanvas()


# Redrawing the Canvas Data after opening it
def redrawCanvas():
global canvas_data
# Clear the canvas
canvas.delete("all")
# Draw objects from canvas_data
for obj in canvas_data:
if obj["type"] == "polygon":
color = obj["color"]
coords = obj["coords"]
canvas.create_polygon(coords, fill=color, outline=color, width=stroke)


# Asking Shape Dimentions
def askShapeDimention():
global width, height

width = simpledialog.askinteger(
"ECTS - Paint App", f"Enter Width for {shapeSelect.get()}"
)

height = simpledialog.askinteger(
"ECTS - Paint App", f"Enter Height for {shapeSelect.get()}"
)
if width and height:
print(width, height)

The above code is required for performing all the actions when respective buttons are clicked or any event is fired.

Here’s the code explaination

Variable Declarations:

  • prevPoint and currentPoint: Store the previous and current coordinates of the mouse pointer.
  • penColor: Stores the color to be used for drawing.
  • stroke: Represents the stroke size of the drawing tool.
  • canvas_data: Stores data about the drawn objects on the canvas.
  • shapeSelect: A StringVar that holds the selected shape type.
  • shapeList: A list of available shape options.
  • shapeFill: Stores the fill color for shapes.
  • width and height: Variables to store width and height of shapes.

Functions:

  • strokeI() and strokeD(): Increase and decrease the stroke size, respectively.
  • strokeDf(): Set the stroke size to default (1).
  • pencil(): Set the drawing tool to pencil and cursor to pencil shape.
  • eraser(): Set the drawing tool to eraser and cursor to dot shape.
  • colorChoice() and shapeColorChoice(): Open color chooser dialogs to select colors for drawing and shapes, respectively.
  • paint(event): Function bound to canvas events. Draws on the canvas based on mouse movements.
  • newApp(): Open a new instance of the paint application.
  • clearScreen(): Clear the canvas by deleting all objects.
  • saveImg() and saveEcts(): Save canvas data to files in ECTS format (a custom format) or as PNG/JPG images.
  • openEcts() and redrawCanvas(): Open ECTS files, load canvas data, and redraw the canvas.
  • askShapeDimention(): Ask the user for width and height dimensions for shapes.

These functions control various aspects of the paint application, such as drawing, color selection, shape selection, saving and opening files, and managing canvas data. The application uses event bindings to trigger the paint() function, allowing users to draw on the canvas as they move the mouse. Additionally, the functions interact with file dialogs and simple dialogs to obtain user input for saving, opening, and specifying shape dimensions.

Note:

I have given my app name “ECTS” and have also created a personal file type called ECTS files which stands for Editing and Canvas Tools Set. If you want to, you can replace the ECTS with your personal file type too.

Step 7: The Complete Code

########### Imports ###########

from tkinter import Tk, Frame, Canvas, CENTER, Button, NW, Label, SOLID
from tkinter import colorchooser, filedialog, OptionMenu, messagebox
from tkinter import DOTBOX, StringVar, simpledialog

import os
import pickle

########### Window Settings ###########

root = Tk()

root.title("Paint - ECTS v1.0")
root.geometry("1100x650")

root.resizable(False, False)

########### Functions ###########

# Variables
prevPoint = [0, 0]
currentPoint = [0, 0]

penColor = "black"
stroke = 1

canvas_data = []

shapeSelect = StringVar()
shapeList = ["None", "Square", "Circle/Oval", "Rectangle", "Line"]
shapeSelect.set("None")
shapeFill = "black"
width = 0
height = 0


# Increase Stroke Size By 1
def strokeI():
global stroke

if stroke != 10:
stroke += 1

else:
stroke = stroke


# Decrease Stroke Size By 1
def strokeD():
global stroke

if stroke != 1:
stroke -= 1

else:
stroke = stroke


def strokeDf():
global stroke
stroke = 1


# Pencil
def pencil():
global penColor

penColor = "black"
canvas["cursor"] = "pencil"


# Eraser
def eraser():
global penColor

penColor = "white"
canvas["cursor"] = DOTBOX


# Pencil Choose Color
def colorChoice():
global penColor

color = colorchooser.askcolor(title="Select a Color")
canvas["cursor"] = "pencil"

if color[1]:
penColor = color[1]

else:
pass


# Shape Color Chooser
def shapeColorChoice():
global shapeFill

color = colorchooser.askcolor(title="Select a Color")
canvas["cursor"] = "pencil"

if color[1]:
shapeFill = color[1]

else:
shapeFill = "black"


# Paint Function
def paint(event):
global prevPoint
global currentPoint

x = event.x
y = event.y

currentPoint = [x, y]

if prevPoint != [0, 0]:
canvas.create_polygon(
prevPoint[0],
prevPoint[1],
currentPoint[0],
currentPoint[1],
fill=penColor,
outline=penColor,
width=stroke,
)

prevPoint = currentPoint

if event.type == "5":
prevPoint = [0, 0]


# Close App
def newApp():
os.startfile("paint.py")


# Clear Screen
def clearScreen():
canvas.delete("all")


# Save Images
def saveImg():
global canvas_data
for obj in canvas.find_all():
obj_type = canvas.type(obj)
if obj_type == "polygon":
color = canvas.itemcget(obj, "fill")
coords = canvas.coords(obj)
canvas_data.append({"type": "polygon", "color": color, "coords": coords})

saveEcts()


# Saving the canvas data to ects files
def saveEcts():
global canvas_data
file_path = filedialog.asksaveasfilename(
defaultextension=".ects",
filetypes=[
("ECTS files", "*.ects"),
("PNG files", "*.png"),
("JPG files", "*.jpg"),
],
)
if file_path:
with open(file_path, "wb") as file:
pickle.dump(canvas_data, file)


# Opening already or earlier made ects files
def openEcts():
global canvas_data
file_path = filedialog.askopenfilename(
defaultextension=".ects",
filetypes=[
("ECTS files", "*.ects"),
("PNG files", "*.png"),
("JPG files", "*.jpg"),
],
)
if file_path:
with open(file_path, "rb") as file:
canvas_data = pickle.load(file)

redrawCanvas()


# Redrawing the Canvas Data after opening it
def redrawCanvas():
global canvas_data
# Clear the canvas
canvas.delete("all")
# Draw objects from canvas_data
for obj in canvas_data:
if obj["type"] == "polygon":
color = obj["color"]
coords = obj["coords"]
canvas.create_polygon(coords, fill=color, outline=color, width=stroke)


# Asking Shape Dimentions
def askShapeDimention():
global width, height

width = simpledialog.askinteger(
"ECTS - Paint App", f"Enter Width for {shapeSelect.get()}"
)

height = simpledialog.askinteger(
"ECTS - Paint App", f"Enter Height for {shapeSelect.get()}"
)
if width and height:
print(width, height)


########### Paint App ###########

#### Paint Tools Frame ####

# Main Frame
frame1 = Frame(root, height=150, width=1100)
frame1.grid(row=0, column=0)

# Holder Frame
holder = Frame(frame1, height=120, width=1000, bg="white", padx=6, pady=10)
holder.grid(row=0, column=0, sticky=NW)
holder.place(relx=0.5, rely=0.5, anchor=CENTER)

holder.columnconfigure(0, minsize=120)
holder.columnconfigure(1, minsize=120)
holder.columnconfigure(2, minsize=120)
holder.columnconfigure(3, minsize=120)
holder.columnconfigure(4, minsize=120)

holder.rowconfigure(0, minsize=30)

#### Tools ####

# Label for Tool 1,2,3
label123 = Label(holder, text="TOOLS", borderwidth=1, relief=SOLID, width=15)
label123.grid(row=0, column=0)

# Tool 1 - Pencil
pencilButton = Button(holder, text="Pencil", height=1, width=12, command=pencil)
pencilButton.grid(row=1, column=0)

# Tool 2 - Eraser
eraserButton = Button(holder, text="Eraser", height=1, width=12, command=eraser)
eraserButton.grid(row=2, column=0)

# Tool 3 - Color Change
colorButton = Button(
holder, text="Select Color", height=1, width=12, command=colorChoice
)
colorButton.grid(row=3, column=0)

#### FILE ACTIONS ####

# Label for Tool 4,5,6
label456 = Label(holder, text="FILE", borderwidth=1, relief=SOLID, width=15)
label456.grid(row=0, column=1)

# Tool 4 - Save File
saveButton = Button(holder, text="SAVE", height=1, width=12, command=saveImg)
saveButton.grid(row=1, column=1)

# Tool 5 - Open File
openButton = Button(holder, text="OPEN", height=1, width=12, command=openEcts)
openButton.grid(row=2, column=1)

# Tool 6 - New Paint
newButton = Button(holder, text="NEW", height=1, width=12, command=newApp)
newButton.grid(row=3, column=1)

#### OTHER ####

# Label for Tool 7 and 8
label7 = Label(holder, text="OTHER", borderwidth=1, relief=SOLID, width=15)
label7.grid(row=0, column=2)

# Tool 7 - Clear Screen
clearButton = Button(holder, text="CLEAR", height=1, width=12, command=clearScreen)
clearButton.grid(row=1, column=2)

# Tool 8 - Exit App
exitButton = Button(
holder, text="Exit", height=1, width=12, command=lambda: root.destroy()
)
exitButton.grid(row=2, column=2)

#### Stroke Size ####

# Label for Tool 8, 9 and 10
label8910 = Label(holder, text="STROKE SIZE", borderwidth=1, relief=SOLID, width=15)
label8910.grid(row=0, column=3)

# Tool 8 - Increament by 1
sizeiButton = Button(holder, text="Increase", height=1, width=12, command=strokeI)
sizeiButton.grid(row=1, column=3)

# Tool 9 - Decreament by 1
sizedButton = Button(holder, text="Decrease", height=1, width=12, command=strokeD)
sizedButton.grid(row=2, column=3)

# Tool 10 - Default
defaultButton = Button(holder, text="Default", height=1, width=12, command=strokeDf)
defaultButton.grid(row=3, column=3)

#### Shapes ####

# Label for Tool 11,12,13
label1123 = Label(holder, text="SHAPES", borderwidth=1, relief=SOLID, width=15)
label1123.grid(row=0, column=4)

# Tool 11 - shapeSelector
shapeMenu = OptionMenu(holder, shapeSelect, *shapeList)
shapeMenu.grid(row=1, column=4)
shapeMenu.config(width=8)

# Tool 9 - Decreament by 1
dimentionButton = Button(
holder, text="Dimention", height=1, width=12, command=askShapeDimention
)
dimentionButton.grid(row=2, column=4)

# Tool 10 - Default
fillButton = Button(holder, text="Fill", height=1, width=12, command=shapeColorChoice)
fillButton.grid(row=3, column=4)

#### Canvas Frame ####

# Main Frame
frame2 = Frame(root, height=500, width=1100)
frame2.grid(row=1, column=0)

# Making a Canvas
canvas = Canvas(frame2, height=450, width=1000, bg="white")
canvas.grid(row=0, column=0)
canvas.place(relx=0.5, rely=0.5, anchor=CENTER)
canvas.config(cursor="pencil")

# Event Binding
canvas.bind("<B1-Motion>", paint)
canvas.bind("<ButtonRelease-1>", paint)
canvas.bind("<Button-1>", paint)

########### Main Loop ###########

root.mainloop()

Kindly Note, there are some flaws in the above code, the shapes tool will not work as desired due to lack of some code in the Program, will update that soon, sorry and thanks…

Summary:

The above code establishes a paint application using Python’s Tkinter library. It begins by configuring the main window with specific dimensions and a fixed size. The GUI is structured into two frames: one for the paint tools and another for the canvas. The paint tools frame contains buttons for drawing tools (pencil, eraser), file actions (save, open, new), stroke size adjustments, shape selection, and color choices. These buttons are associated with functions controlling stroke size, color selection, canvas clearing, and file operations like saving and opening ECTS files. The canvas frame sets up a canvas area where drawing occurs, with event bindings enabling mouse interactions for drawing and shape creation. Functions handle drawing logic, cursor settings, color selection dialogs, and file operations. The application allows users to draw, erase, select colors, adjust stroke sizes, create shapes, and save/open drawings using a simple and intuitive graphical interface.

Contributions:

  1. Code By: Aarush Mehta
  2. Code Explained By: Aarush Mehta & ChatGPT
  3. Article By: Aarush Mehta ( Codec07 )

--

--

TSB Everything

All You Need To Know about Science and Technology | By Aarush Mehta