Interactive canvas widget for CustomTkinter with draggable, resizable rectangles
Project description
CTk Interactive Canvas
Interactive canvas widget for CustomTkinter with draggable, resizable rectangles featuring multi-selection, alignment, distribution, and professional-grade interaction controls.
Table of Contents
- Features
- Installation
- Quick Start
- Real-World Applications
- Usage Examples
- Keyboard Modifiers
- API Reference
- Requirements
- Development
- License
- Credits
- Contributing
- Changelog
- Support
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)→ DraggableRectanglecopy_draggable_rectangle(rect, offset=[21, 21], **kwargs)→ DraggableRectangledelete_draggable_rectangle(item_id)→ Noneget_selected()→ List[DraggableRectangle]get_draggable_rectangle(item_id)→ DraggableRectangleselect_all()→ Nonedeselect_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 rectanglesdistribute(rectangles, mode, relative_pos=None)- Distribute evenlycompare(rect1, rect2)→ (bool, dict) - Compare two rectanglesget_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)
- Email: dev.github.tkjoramsmith@outlook.com
- GitHub: @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
- Issues: GitHub Issues
- Discussions: GitHub Discussions
Note: This package is in active development. APIs may change between minor versions until 1.0.0 release.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bb977265b974dcaa1ca100226c5d797e056c397a7598553e487baaa2f2b260f6
|
|
| MD5 |
18b032af301daa121104bd7c8e6563a9
|
|
| BLAKE2b-256 |
edba6022f52a3be1a1ef4bf81b139f6e91de0c521de79e36c40a898282632c35
|
File details
Details for the file ctk_interactive_canvas-0.3.3-py3-none-any.whl.
File metadata
- Download URL: ctk_interactive_canvas-0.3.3-py3-none-any.whl
- Upload date:
- Size: 20.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0de166ee42c3359b63e5ba5f020a8ae8e61f1ea0a4ab43825cde40bd5edc031c
|
|
| MD5 |
bd7c204d231c0e34b6b68713068daae8
|
|
| BLAKE2b-256 |
f718992ca09b456855dd3a0cc01cfb6e7d7b406b21c02714cd8c3488c07c3f81
|