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.