w3resource

Python Project - Basic Drawing App using Tkinter and PyQt5

Basic Drawing App:

Create a simple drawing application with basic shapes and colors.

Input values:
User interacts with the drawing application by selecting drawing tools (pencil, rectangle, etc.), shapes, colors, and making strokes on the canvas.

Output value:
Visual representation of the drawn elements on the canvas, including shapes and colors.

Example:

Input values:
1. Select Pencil tool
2. Select Red color
3. Draw a freehand stroke on the canvas
Output value:
Canvas displays a Red freehand stroke.
Input values:
1. Select Rectangle tool
2. Select Blue color
3. Draw a rectangle on the canvas
Output value:
Canvas displays a blue rectangle.
Input values:
1. Select Eraser tool
2. Erase part of the drawn elements
Output value:
Canvas displays the erased portion.
Input values:
4. Save the drawing to a file
Output value:
Drawing saved successfully to "my_drawing.png".

Solution 1: Basic Drawing App Using Tkinter

‘Tkinter’ is a popular Python library for creating simple GUI applications. This solution will use Tkinter's ‘Canvas’ widget to draw shapes, freehand strokes, and save the drawing to a file.

Code:

# Solution 1: Basic Drawing App Using Tkinter

import tkinter as tk  # Import the Tkinter library for creating GUI applications
from tkinter import colorchooser  # Import the colorchooser module to select colors
from tkinter import filedialog  # Import the filedialog module to save the drawing
from PIL import Image  # Import PIL (Pillow) to handle image saving

# Main class for the Drawing App
class DrawingApp:
    """Class to create a simple drawing application with basic shapes and colors."""

    def __init__(self, root):
        """Initialize the DrawingApp with a Tkinter window."""
        self.root = root
        self.root.title("Basic Drawing App")
        
        # Initialize drawing settings
        self.color = "black"  # Default color is black
        self.tool = "pencil"  # Default tool is pencil
        self.canvas = tk.Canvas(root, bg="white", width=400, height=300)  # Create a canvas for drawing
        self.canvas.pack(fill=tk.BOTH, expand=True)  # Pack the canvas to fill the window

        # Bind mouse events to canvas for drawing
        self.canvas.bind("", self.draw)  # Bind mouse movement with the left button pressed
        self.canvas.bind("", self.start_draw)  # Bind mouse button press to start drawing

        # Create a toolbar for selecting tools and colors
        toolbar = tk.Frame(root, bg="lightgray")  # Create a toolbar frame
        toolbar.pack(side=tk.TOP, fill=tk.X)  # Pack the toolbar at the top
        
        # Add buttons for tools
        pencil_btn = tk.Button(toolbar, text="Pencil", command=lambda: self.select_tool("pencil"))
        pencil_btn.pack(side=tk.LEFT, padx=2, pady=2)
        rect_btn = tk.Button(toolbar, text="Rectangle", command=lambda: self.select_tool("rectangle"))
        rect_btn.pack(side=tk.LEFT, padx=2, pady=2)
        eraser_btn = tk.Button(toolbar, text="Eraser", command=lambda: self.select_tool("eraser"))
        eraser_btn.pack(side=tk.LEFT, padx=2, pady=2)

        # Add button for color selection
        color_btn = tk.Button(toolbar, text="Color", command=self.choose_color)
        color_btn.pack(side=tk.LEFT, padx=2, pady=2)

        # Add button for saving the drawing
        save_btn = tk.Button(toolbar, text="Save", command=self.save_drawing)
        save_btn.pack(side=tk.LEFT, padx=2, pady=2)

        self.previous_x = None  # Store the previous x-coordinate of the mouse for drawing
        self.previous_y = None  # Store the previous y-coordinate of the mouse for drawing

    def select_tool(self, tool):
        """Select the current drawing tool."""
        self.tool = tool

    def choose_color(self):
        """Choose a color for drawing."""
        self.color = colorchooser.askcolor()[1]  # Open the color chooser dialog and store the selected color

    def start_draw(self, event):
        """Initialize drawing when the mouse button is pressed."""
        self.previous_x, self.previous_y = event.x, event.y  # Store the starting coordinates for drawing

    def draw(self, event):
        """Draw on the canvas based on the selected tool and mouse movement."""
        if self.tool == "pencil":
            self.canvas.create_line(self.previous_x, self.previous_y, event.x, event.y, fill=self.color, width=2)
        elif self.tool == "rectangle":
            self.canvas.create_rectangle(self.previous_x, self.previous_y, event.x, event.y, outline=self.color)
        elif self.tool == "eraser":
            self.canvas.create_line(self.previous_x, self.previous_y, event.x, event.y, fill="white", width=10)
        
        # Update the previous coordinates to the current coordinates
        self.previous_x, self.previous_y = event.x, event.y

    def save_drawing(self):
        """Save the drawing to a file."""
        filename = filedialog.asksaveasfilename(defaultextension=".png", filetypes=[("PNG files", "*.png")])
        if filename:
            # Save the canvas content to a file
            self.canvas.postscript(file="temp.ps", colormode='color')
            img = Image.open("temp.ps")
            img.save(filename, 'png')
            print("Drawing saved successfully to", filename)


# Create the main window
root = tk.Tk()
app = DrawingApp(root)
root.mainloop() 

Output:

Python: Basic Drawing App.

Explanation:

  • Imports:
    • tkinter: Used for creating the GUI and handling user interactions.
    • colorchooser and filedialog: Used for selecting colors and saving files.
    • Pillow (PIL): Used for converting the canvas content to an image file format (e.g., PNG).
  • Class DrawingApp:
    • __init__: Initializes the drawing application, sets up the canvas, tools, and toolbar.
    • select_tool: Allows users to select different drawing tools (pencil, rectangle, eraser).
    • choose_color: Opens a color chooser to select drawing colors.
    • start_draw: Initializes the starting point for drawing when the mouse button is pressed.
    • draw: Handles the drawing logic based on the selected tool and mouse movement.
    • save_drawing: Saves the current drawing to a file.

Solution 2: Basic Drawing App Using PyQt5

'PyQt5' is a set of Python bindings for Qt libraries that provides tools to create a GUI application.

Code:

# Solution 2: Basic Drawing App Using PyQt5

from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QColorDialog, QFileDialog, QHBoxLayout, QVBoxLayout, QWidget
from PyQt5.QtGui import QPainter, QPen, QImage
from PyQt5.QtCore import Qt, QPoint

class DrawingApp(QMainWindow):
    """Class to create a simple drawing application with PyQt5."""

    def __init__(self):
        """Initialize the DrawingApp with a PyQt5 main window."""
        super().__init__()
        self.setWindowTitle("Basic Drawing App")
        self.setGeometry(100, 100, 600, 400)
        
        # Initialize drawing settings
        self.image = QImage(self.size(), QImage.Format_RGB32)
        self.image.fill(Qt.white)
        self.drawing = False
        self.brush_color = Qt.black
        self.brush_size = 2
        self.last_point = QPoint()

        # Set up the main layout
        main_widget = QWidget()
        main_layout = QVBoxLayout()
        main_widget.setLayout(main_layout)
        self.setCentralWidget(main_widget)

        # Canvas area: the space above buttons
        self.canvas = QWidget(self)
        main_layout.addWidget(self.canvas)  # Add canvas to the main layout

        # Add horizontal layout for buttons at the bottom
        button_layout = QHBoxLayout()
        main_layout.addLayout(button_layout)

        # Add buttons for tools
        pencil_btn = QPushButton("Pencil", self)
        pencil_btn.clicked.connect(self.select_pencil)
        button_layout.addWidget(pencil_btn)

        rect_btn = QPushButton("Rectangle", self)
        rect_btn.clicked.connect(self.select_rectangle)
        button_layout.addWidget(rect_btn)

        color_btn = QPushButton("Color", self)
        color_btn.clicked.connect(self.select_color)
        button_layout.addWidget(color_btn)

        save_btn = QPushButton("Save", self)
        save_btn.clicked.connect(self.save_image)
        button_layout.addWidget(save_btn)

    def select_pencil(self):
        """Select the pencil tool for drawing."""
        self.tool = 'pencil'

    def select_rectangle(self):
        """Select the rectangle tool for drawing."""
        self.tool = 'rectangle'

    def select_color(self):
        """Open a color dialog to choose the drawing color."""
        color = QColorDialog.getColor()
        if color.isValid():
            self.brush_color = color

    def save_image(self):
        """Save the drawn image to a file."""
        file_path, _ = QFileDialog.getSaveFileName(self, "Save Image", "", "PNG(*.png);;JPEG(*.jpg *.jpeg);;All Files(*.*) ")
        if file_path:
            self.image.save(file_path)

    def mousePressEvent(self, event):
        """Handle mouse press events for drawing."""
        if event.button() == Qt.LeftButton:
            self.drawing = True
            self.last_point = event.pos()

    def mouseMoveEvent(self, event):
        """Handle mouse move events for drawing."""
        if event.buttons() & Qt.LeftButton and self.drawing:
            painter = QPainter(self.image)
            painter.setPen(QPen(self.brush_color, self.brush_size, Qt.SolidLine))
            painter.drawLine(self.last_point, event.pos())
            self.last_point = event.pos()
            self.update()

    def mouseReleaseEvent(self, event):
        """Handle mouse release events to stop drawing."""
        if event.button() == Qt.LeftButton:
            self.drawing = False

    def paintEvent(self, event):
        """Update the canvas to display the drawn elements."""
        canvas_painter = QPainter(self)
        canvas_painter.drawImage(self.rect(), self.image, self.image.rect())

# Run the PyQt5 application
app = QApplication([])
window = DrawingApp()
window.show()
app.exec_()  

Output:

Python: Basic Drawing App Pyqt5.

Explanation:

  • Imports:
    • PyQt5: Provides classes (QMainWindow, QPainter, QPen, QColorDialog, QFileDialog, etc.) for creating the GUI application.
    • QApplication: Manages the GUI application's control flow.
  • Class DrawingApp:
    • __init__: Initializes the application window, sets up the drawing canvas, and adds tool buttons.
    • select_pencil, select_rectangle, select_color: Handle user selections for tools and color.
    • save_image: Saves the drawing to an image file.
    • mousePressEvent, mouseMoveEvent, mouseReleaseEvent: Handle mouse events for drawing on the canvas.
    • paintEvent: Updates the display to show drawn elements.

Summary of Differences:

  • Tkinter Solution:
    • Framework: Tkinter
    • Features: Simple setup, minimal code, easy-to-understand GUI elements.
    • Tools: Pencil, rectangle, color picker, eraser.
    • Output: Saves drawing to a file.
  • PyQt5 Solution:
    • Framework: PyQt5
    • Features: More advanced GUI features, customizable drawing tools.
    • Tools: Pencil, rectangle, color picker.
    • Output: Saves drawing to various image formats.

Both solutions provide a basic drawing application with essential functionalities, such as drawing shapes, selecting colors, and saving files.



Become a Patron!

Follow us on Facebook and Twitter for latest update.

It will be nice if you may share this link in any developer community or anywhere else, from where other developers may find this content. Thanks.

https://w3resource.com/projects/python/python-basic-drawing-app-project.php