Skip to main content

Interactive canvas widget for CustomTkinter with draggable, resizable rectangles

Project description

CTk Interactive Canvas

CodeFactor Python version PyPi version PyPi status PyPi downloads Star this repo

Interactive canvas widget for CustomTkinter with draggable, resizable rectangles featuring multi-selection, alignment, distribution, and professional-grade interaction controls.

Table of Contents

Features

Core Capabilities

  • Draggable Rectangles: Click and drag to move objects
  • Resizable Objects: Bottom-right handle for intuitive resizing
  • Multi-Selection: Shift-click or drag-select multiple objects
  • Alignment Tools: Align multiple rectangles (top, middle, bottom, start, center, end)
  • Distribution Tools: Evenly distribute rectangles horizontally or vertically
  • Panning: Middle-mouse or Space+drag to pan the canvas

Professional Controls

  • Adobe Illustrator-style Constraints:
    • Shift during move: Lock to 45-degree angles (0°, 45°, 90°, 135°, etc.)
    • Shift during resize: Maintain aspect ratio
    • Ctrl during resize: Resize from center
    • Alt during resize: Constrain to one dimension
    • Shift+Ctrl during resize: Aspect ratio + center resize

Advanced Features

  • 26 Magic Methods: NumPy-like interface for geometric operations
  • Unit Conversion: Built-in mm ↔ px conversion with DPI support
  • Intersection & Union: Geometric operations via & and | operators
  • Point Containment: Test if coordinates are inside rectangles
  • Sorting & Comparison: Area-based ordering and equality testing
  • Coordinate Access: Index-based access and iteration

Installation

pip install ctk-interactive-canvas

Quick Start

import customtkinter as ctk
from ctk_interactive_canvas import InteractiveCanvas

root = ctk.CTk()
root.title("Interactive Canvas Demo")

canvas = InteractiveCanvas(root, width=800, height=600, bg='white')
canvas.pack()

rect1 = canvas.create_draggable_rectangle(50, 50, 150, 150, outline='blue', width=5)
rect2 = canvas.create_draggable_rectangle(200, 200, 300, 300, outline='red', width=5)

root.mainloop()

Real-World Applications

CTk Interactive Canvas excels in practical, real-world scenarios. See these complete, production-ready examples:

📄 Document Layout Designer

Professional page layout tool for print design and publishing.

python examples/document_layout_designer.py

Features:

  • A4/US Letter page templates with accurate dimensions
  • Text box and image placeholder management
  • PDF export with actual text rendering (requires reportlab)
  • Professional alignment and distribution tools
  • Real-time visual feedback

Use Cases: Newsletter design, poster creation, document layout, print production

🎯 Bounding Box Editor for ML

Computer vision annotation tool for object detection datasets.

python examples/bounding_box_editor.py

Features:

  • Load images as canvas background (requires Pillow)
  • Multi-class object annotation with color coding
  • Export to YOLO and COCO JSON formats
  • Keyboard shortcuts for efficient workflow
  • Statistics tracking

Use Cases: Machine learning dataset preparation, object detection training, image annotation

🪑 Seating Chart Planner

Event planning tool for arranging tables and guest seating.

python examples/seating_chart_planner.py

Features:

  • Multiple table types (round, rectangular, long tables)
  • Category-based organization (VIP, Family, Friends)
  • Real-world distance measurement (meters)
  • Guest assignment tracking
  • Export seating arrangements and guest lists

Use Cases: Wedding planning, conference organization, banquet setup, office layouts


Usage Examples

Basic Rectangle Creation

canvas = InteractiveCanvas(root, width=800, height=600, bg='white')
canvas.pack()

rect = canvas.create_draggable_rectangle(
    x1=100, y1=100,
    x2=200, y2=200,
    outline='blue',
    width=5,
    fill=''
)

Selection Callbacks

def on_select():
    selected = canvas.get_selected()
    print(f"Selected: {len(selected)} objects")

def on_deselect():
    print("Selection cleared")

canvas = InteractiveCanvas(
    root,
    width=800,
    height=600,
    select_callback=on_select,
    deselect_callback=on_deselect
)

Alignment and Distribution

from ctk_interactive_canvas import DraggableRectangle

rectangles = [rect1, rect2, rect3]

DraggableRectangle.align(rectangles, mode='center')
DraggableRectangle.distribute(rectangles, mode='horizontal')

Mathematical Operations

translated = rect + [50, 30]

doubled = rect * 2

halved = rect / 2

rect += [10, 10]

intersection = rect1 & rect2
bounding = rect1 | rect2

if [x, y] in rect:
    print("Point inside rectangle!")

sorted_rects = sorted([rect1, rect2, rect3])

Unit Conversion

rect = canvas.create_draggable_rectangle(0, 0, 100, 100)

pos_mm = rect.get_topleft_pos(in_mm=True, dpi=300)
print(f"Position in mm: {pos_mm}")

rect.set_size([50, 50], in_mm=True, dpi=300)

Coordinate Access

x0, y0, x1, y1 = rect

rect[2] = 300

coords = rect[:]

for coord in rect:
    print(coord)

Keyboard Modifiers

Action Modifier Behavior
Move Shift Lock to 45° angles
Resize Shift Maintain aspect ratio
Resize Ctrl Resize from center
Resize Alt Constrain to one axis
Resize Shift+Ctrl Aspect ratio + center
Pan Space Enable pan mode
Select Shift+Click Add to selection
Delete Delete Remove selected

API Reference

InteractiveCanvas

InteractiveCanvas(
    master=None,
    select_callback=None,
    deselect_callback=None,
    delete_callback=None,
    select_outline_color='#16fff6',
    dpi=300,
    create_bindings=True,
    **kwargs
)

Methods:

  • create_draggable_rectangle(x1, y1, x2, y2, **kwargs) → DraggableRectangle
  • copy_draggable_rectangle(rect, offset=[21, 21], **kwargs) → DraggableRectangle
  • delete_draggable_rectangle(item_id) → None
  • get_selected() → List[DraggableRectangle]
  • get_draggable_rectangle(item_id) → DraggableRectangle
  • select_all() → None
  • deselect_all() → None

DraggableRectangle

Position & Size:

  • get_topleft_pos(relative_pos=None, in_mm=False, dpi=None) → [x, y]
  • set_topleft_pos(new_pos, relative_pos=None, in_mm=False, dpi=None)
  • get_size(in_mm=False, dpi=None) → [width, height]
  • set_size(new_size, in_mm=False, dpi=None)

Transformations:

  • safe_rotate(angle, anchor='topleft') - Rotate 90°/180°/-90°/-180°
  • copy_(offset=[50, 50], **kwargs) → DraggableRectangle

Class Methods:

  • align(rectangles, mode, relative_pos=None) - Align multiple rectangles
  • distribute(rectangles, mode, relative_pos=None) - Distribute evenly
  • compare(rect1, rect2) → (bool, dict) - Compare two rectangles
  • get_instances() → List[DraggableRectangle] - Get all alive instances

Magic Methods:

  • Arithmetic: +, -, *, /, +=, -=, *=, /=
  • Comparison: ==, !=, <, <=, >, >=
  • Bitwise: & (intersection), | (union)
  • Unary: -, +, abs()
  • Container: len(), [], in, iter()
  • Representation: str(), repr(), format(), bool(), hash()

Requirements

  • Python ≥ 3.9
  • CustomTkinter ≥ 5.1.0

Development

Install Development Dependencies

pip install -e ".[dev]"

Run Tests

pytest

Code Quality

black .
ruff check .
mypy src/ctk_interactive_canvas

License

MIT License - see LICENSE file for details.

Credits

Author

T. K. Joram Smith (DeltaGa)

Acknowledgments

  • CustomTkinter - Modern UI framework
  • Python Community - Continuous ecosystem evolution

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

Changelog

See CHANGELOG.md for version history.

Support


Note: This package is in active development. APIs may change between minor versions until 1.0.0 release.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ctk_interactive_canvas-0.3.3.tar.gz (30.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ctk_interactive_canvas-0.3.3-py3-none-any.whl (20.3 kB view details)

Uploaded Python 3

File details

Details for the file ctk_interactive_canvas-0.3.3.tar.gz.

File metadata

  • Download URL: ctk_interactive_canvas-0.3.3.tar.gz
  • Upload date:
  • Size: 30.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ctk_interactive_canvas-0.3.3.tar.gz
Algorithm Hash digest
SHA256 bb977265b974dcaa1ca100226c5d797e056c397a7598553e487baaa2f2b260f6
MD5 18b032af301daa121104bd7c8e6563a9
BLAKE2b-256 edba6022f52a3be1a1ef4bf81b139f6e91de0c521de79e36c40a898282632c35

See more details on using hashes here.

File details

Details for the file ctk_interactive_canvas-0.3.3-py3-none-any.whl.

File metadata

File hashes

Hashes for ctk_interactive_canvas-0.3.3-py3-none-any.whl
Algorithm Hash digest
SHA256 0de166ee42c3359b63e5ba5f020a8ae8e61f1ea0a4ab43825cde40bd5edc031c
MD5 bd7c204d231c0e34b6b68713068daae8
BLAKE2b-256 f718992ca09b456855dd3a0cc01cfb6e7d7b406b21c02714cd8c3488c07c3f81

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page