You are browsing as a guest. Sign up (or log in) to start making projects!

InkFlow

  • 3 Devlogs
  • 4 Total hours

A modern infinite whiteboard application built with Python and PySide6

Ship #1 Changes requested

InkFlow

A modern infinite whiteboard application built with Python and PySide6.


πŸš€ Project Status

InkFlow is currently in active development. The foundation of the application has been built, focusing on creating a scalable architecture that will support multiple drawing tools and future features.


Features Implemented till date

Pen Tool

  • Smooth freehand drawing
  • Rounded stroke caps
  • Rounded joins for natural handwriting
  • Adjustable pen width
  • Automatic stroke creation using QPainterPath

β€’ Single Click Dot Drawing

InkFlow automatically detects when the mouse is clicked without movement and draws a perfectly centered filled dot instead of creating an empty stroke.


Infinite Canvas

The application currently provides a large virtual drawing area using QGraphicsScene, allowing users to freely move around while drawing.

Current scene size:

5000 Γ— 5000 px

This will later evolve into a dynamically expanding infinite canvas.


Panning

Navigate around the canvas using:

  • Middle Mouse Button + Drag
  • Hold Space + Left Mouse Drag

The camera moves independently of the drawing system, allowing a smooth workflow similar to professional whiteboard applications.


Zoom

Implemented mouse-wheel zoom with:

  • Zoom centered around the mouse cursor
  • Geometric zoom progression
  • Minimum zoom limit
  • Maximum zoom limit

This provides smooth navigation without distortion.


Architecture

One of the major goals of InkFlow is maintaining a clean and extensible architecture.

Instead of placing all functionality inside a single Canvas class, responsibilities have been separated.

MainWindow
β”‚
└── Canvas
     β”‚
     β”œβ”€β”€ Camera (Pan & Zoom)
     β”œβ”€β”€ Scene Management
     └── Tool System
             β”‚
             └── Active Tool

Tool System

InkFlow has a modular tool architecture, which makes it easier to maintain.

Current hierarchy:

BaseTool
    β”‚
    └── PenTool

Each tool is responsible for implementing its own:

  • Mouse Press
  • Mouse Move
  • Mouse Release

This allows future tools to be added without modifying the core canvas.


Tool Registry

Canvas maintains a registry of available tools.

Example:

self.tools = {
    "pen": PenTool(self)
}

The active tool is simply a reference to one of these objects.

self.active_tool = self.tools["pen"]

This makes switching tools straightforward while preserving each tool’s internal state.


Current Project Structure

InkFlow/
β”‚
β”œβ”€β”€ main.py
β”‚
β”œβ”€β”€ ui/
β”‚   β”œβ”€β”€ main_window.py
β”‚   └── canvas.py
β”‚
β”œβ”€β”€ tools/
β”‚   β”œβ”€β”€ base_tool.py
β”‚   └── pen_tool.py
β”‚
└── assets/

Current Development Goals

  • Build a modular tool system
  • Keep the codebase clean and scalable
  • Separate UI logic from drawing logic
  • Prepare the project for future expansion

Planned Features

The following features are planned for future versions:

  • Tool Toolbar
  • Eraser Tool
  • Rectangle Tool
  • Circle Tool
  • Line Tool
  • Arrow Tool
  • Text Tool
  • Selection Tool
  • Color Picker
  • Brush Size Controls
  • Undo / Redo
  • Layers
  • Infinite Dynamic Canvas
  • Save / Load Projects
  • Export to PNG
  • Export to PDF
  • Keyboard Shortcuts
  • Custom Themes

Design Philosophy

InkFlow is being designed with long-term maintainability in mind.

Instead of building features as one large class, the project follows an object-oriented architecture where each component has a single responsibility.

This approach makes adding new tools and features significantly easier while keeping the codebase organized and maintainable.


Controls:-
Panning = Mouse scroll wheel button
= space bar + mouse left click button

Drawing = left mouse button

  • 3 devlogs
  • 4h
Try project β†’ See source code β†’
Open comments for this post

54m 34s logged

Devlog #3 - Improved the code formatting

I divided the the working of the code into different pipelines
I also added new folders to organize everything I added the folders UI and tools to organize the pipelines

I divided the tools from the main Canvas.py to sub scripts in the Tools Folder, like base_tool.py and pen_tool.py
Then in canvas.py I added a simple method to check the current active tool and how to call it actively.

0
0
3
Open comments for this post

1h 4m 58s logged

Devlog #2 - making it Pan and Zoom and Adding infinite space

I implemented infinite panning, precision scroll-wheel zooming, and smoother pen aesthetics along with Infinite Canvas

Challenges and Solutions

The problem I faced was that

It was difficult to add support for both space bar and left click(of the mouse) 
being pressed at the same time

So to solve it I introduced 3 variables self.panning = False, self.pan_start = None and self.space_pressed = False

then while checking for the key press, we check for space bar and set the variable self.space_pressed to true
and then while checking for the mouse press event we set the variable self.panning to True
And then finally in the mouse move event we actually pan in the canvas by moving the camera

self.horizontalScrollBar().setValue(Β self.horizontalScrollBar().value() - int(delta.x()))Β  Β  Β 
self.verticalScrollBar().setValue(self.verticalScrollBar().value() - int(delta.y()))
0
0
3
Open comments for this post

2h 12m 57s logged

Devlog #1 - Making it Click, Draw lines & Dots

Today I created a window on the screen that scales nicely to the user’s monitor and created a responsive digital canvas on which you can draw Lines and dots till now

The Problem and solution

I faced a problem that didn’t let me draw dots the problem was:-

clicking on the canvas without dragging the mouse left absolutely nothing on the screen.
The path-drawing logic expected continuous cursor updates to generate lines. 
Tapping the screen to place a single dot was functionally invisible.

So I introduced a self.has_moved variable which is set to False by default and when the user presses the left button and moves the mouse it is set to True
then we run a Check in the release event that if has_moved = False then it draws a dot otherwise it draws a line using self.last_point and self.current_point

0
0
3

Delete project?

Are you sure you want to permanently delete this project? This action cannot be undone.

All devlogs, followers, and associated data will be removed.

Followers

Loading…