Major changes: - Fixed right-click handler to directly set mode to NONE instead of relying on main app signal handling - Added safety checks in left-click handler to prevent drawing when no draggable point is found in NONE mode - Enhanced mode compatibility by treating Python None as SketchMode.NONE in set_mode() method - Added comprehensive debug logging for mode changes and interaction state tracking - Resolved integration issue where persistent constraint modes were prematurely reset by main app - Ensured point dragging is only enabled in NONE mode, preventing accidental polyline creation This fixes the reported issue where deactivating the line tool would still create lines when dragging, and ensures proper mode transitions between drawing tools and selection/drag mode.
202 lines
9.8 KiB
Python
202 lines
9.8 KiB
Python
"""
|
|
Example integration of the improved sketcher with the main Fluency application
|
|
This shows how to replace the existing sketcher with the improved version
|
|
"""
|
|
|
|
from PySide6.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QHBoxLayout, QWidget, QPushButton, QButtonGroup
|
|
from PySide6.QtCore import Qt
|
|
|
|
from improved_sketcher import ImprovedSketchWidget, SketchMode, SnapMode
|
|
|
|
|
|
class SketcherIntegrationDemo(QMainWindow):
|
|
"""Demo showing how to integrate the improved sketcher with UI controls"""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.setWindowTitle("Improved Sketcher Integration Demo")
|
|
self.resize(1200, 800)
|
|
|
|
# Create central widget
|
|
central_widget = QWidget()
|
|
self.setCentralWidget(central_widget)
|
|
|
|
# Create layout
|
|
main_layout = QHBoxLayout(central_widget)
|
|
|
|
# Create toolbar
|
|
self.create_toolbar(main_layout)
|
|
|
|
# Create sketcher widget
|
|
self.sketcher = ImprovedSketchWidget()
|
|
main_layout.addWidget(self.sketcher, stretch=1)
|
|
|
|
# Connect sketcher signals
|
|
self.connect_sketcher_signals()
|
|
|
|
# Set initial mode
|
|
self.sketcher.set_mode(SketchMode.LINE)
|
|
|
|
def create_toolbar(self, parent_layout):
|
|
"""Create toolbar with sketching tools"""
|
|
toolbar_widget = QWidget()
|
|
toolbar_widget.setFixedWidth(200)
|
|
toolbar_layout = QVBoxLayout(toolbar_widget)
|
|
|
|
# Drawing tools group
|
|
drawing_group = QWidget()
|
|
drawing_layout = QVBoxLayout(drawing_group)
|
|
drawing_layout.addWidget(self.create_label("Drawing Tools"))
|
|
|
|
# Create drawing mode buttons
|
|
self.drawing_buttons = QButtonGroup(self)
|
|
self.drawing_buttons.setExclusive(True)
|
|
|
|
drawing_modes = [
|
|
("Line", SketchMode.LINE),
|
|
("Rectangle", SketchMode.RECTANGLE),
|
|
("Circle", SketchMode.CIRCLE),
|
|
("Point", SketchMode.POINT),
|
|
]
|
|
|
|
for name, mode in drawing_modes:
|
|
button = QPushButton(name)
|
|
button.setCheckable(True)
|
|
button.clicked.connect(lambda checked, m=mode: self.set_drawing_mode(m))
|
|
self.drawing_buttons.addButton(button)
|
|
drawing_layout.addWidget(button)
|
|
|
|
# Set line as default
|
|
self.drawing_buttons.buttons()[0].setChecked(True)
|
|
|
|
# Constraint tools group
|
|
constraint_group = QWidget()
|
|
constraint_layout = QVBoxLayout(constraint_group)
|
|
constraint_layout.addWidget(self.create_label("Constraints"))
|
|
|
|
# Create constraint buttons
|
|
constraint_modes = [
|
|
("Coincident", SketchMode.COINCIDENT_PT_PT),
|
|
("Horizontal", SketchMode.HORIZONTAL),
|
|
("Vertical", SketchMode.VERTICAL),
|
|
("Distance", SketchMode.DISTANCE),
|
|
]
|
|
|
|
for name, mode in constraint_modes:
|
|
button = QPushButton(name)
|
|
button.clicked.connect(lambda checked, m=mode: self.set_constraint_mode(m))
|
|
constraint_layout.addWidget(button)
|
|
|
|
# Settings group
|
|
settings_group = QWidget()
|
|
settings_layout = QVBoxLayout(settings_group)
|
|
settings_layout.addWidget(self.create_label("Settings"))
|
|
|
|
# Construction mode toggle
|
|
self.construction_button = QPushButton("Construction Mode")
|
|
self.construction_button.setCheckable(True)
|
|
self.construction_button.toggled.connect(self.toggle_construction_mode)
|
|
settings_layout.addWidget(self.construction_button)
|
|
|
|
# Snap settings
|
|
snap_buttons = [
|
|
("Point Snap", SnapMode.POINT),
|
|
("Grid Snap", SnapMode.GRID),
|
|
("Midpoint Snap", SnapMode.MIDPOINT),
|
|
]
|
|
|
|
for name, snap_mode in snap_buttons:
|
|
button = QPushButton(name)
|
|
button.setCheckable(True)
|
|
button.toggled.connect(lambda checked, sm=snap_mode: self.toggle_snap_mode(sm, checked))
|
|
settings_layout.addWidget(button)
|
|
|
|
# Set default snaps
|
|
settings_layout.itemAt(1).widget().setChecked(True) # Point snap on by default
|
|
|
|
# View controls
|
|
view_group = QWidget()
|
|
view_layout = QVBoxLayout(view_group)
|
|
view_layout.addWidget(self.create_label("View"))
|
|
|
|
zoom_fit_button = QPushButton("Zoom to Fit")
|
|
zoom_fit_button.clicked.connect(self.sketcher.zoom_to_fit)
|
|
view_layout.addWidget(zoom_fit_button)
|
|
|
|
# Add groups to toolbar
|
|
toolbar_layout.addWidget(drawing_group)
|
|
toolbar_layout.addWidget(constraint_group)
|
|
toolbar_layout.addWidget(settings_group)
|
|
toolbar_layout.addWidget(view_group)
|
|
toolbar_layout.addStretch()
|
|
|
|
parent_layout.addWidget(toolbar_widget)
|
|
|
|
def create_label(self, text):
|
|
"""Create a section label"""
|
|
from PySide6.QtWidgets import QLabel
|
|
from PySide6.QtCore import Qt
|
|
|
|
label = QLabel(text)
|
|
label.setAlignment(Qt.AlignCenter)
|
|
label.setStyleSheet("font-weight: bold; padding: 5px; background-color: #333; color: white;")
|
|
return label
|
|
|
|
def set_drawing_mode(self, mode):
|
|
"""Set the sketcher to drawing mode"""
|
|
self.sketcher.set_mode(mode)
|
|
print(f"Drawing mode set to: {mode.name}")
|
|
|
|
def set_constraint_mode(self, mode):
|
|
"""Set the sketcher to constraint mode"""
|
|
self.sketcher.set_mode(mode)
|
|
# Uncheck all drawing buttons when in constraint mode
|
|
for button in self.drawing_buttons.buttons():
|
|
button.setChecked(False)
|
|
print(f"Constraint mode set to: {mode.name}")
|
|
|
|
def toggle_construction_mode(self, checked):
|
|
"""Toggle construction geometry mode"""
|
|
self.sketcher.set_construction_mode(checked)
|
|
print(f"Construction mode: {'enabled' if checked else 'disabled'}")
|
|
|
|
def toggle_snap_mode(self, snap_mode, enabled):
|
|
"""Toggle snap mode"""
|
|
self.sketcher.toggle_snap_mode(snap_mode, enabled)
|
|
print(f"Snap mode {snap_mode.name}: {'enabled' if enabled else 'disabled'}")
|
|
|
|
def connect_sketcher_signals(self):
|
|
"""Connect to sketcher signals for feedback"""
|
|
self.sketcher.geometry_created.connect(self.on_geometry_created)
|
|
self.sketcher.constraint_applied.connect(self.on_constraint_applied)
|
|
self.sketcher.sketch_modified.connect(self.on_sketch_modified)
|
|
|
|
def on_geometry_created(self, geometry_type):
|
|
"""Handle geometry creation"""
|
|
print(f"Created: {geometry_type}")
|
|
# Update status or trigger other actions
|
|
|
|
def on_constraint_applied(self):
|
|
"""Handle constraint application"""
|
|
print("Constraint applied successfully")
|
|
# Return to line drawing mode after constraint
|
|
self.sketcher.set_mode(SketchMode.LINE)
|
|
self.drawing_buttons.buttons()[0].setChecked(True)
|
|
|
|
def on_sketch_modified(self):
|
|
"""Handle sketch modifications"""
|
|
print("Sketch modified")
|
|
# Could trigger auto-save or update displays
|
|
|
|
|
|
def replace_sketcher_in_main_app():
|
|
"""
|
|
Example of how to replace the existing sketcher in main.py
|
|
|
|
In main.py, replace this code:
|
|
|
|
```python\n from drawing_modules.draw_widget_solve import SketchWidget\n self.sketchWidget = SketchWidget()\n ```\n \n With:\n \n ```python\n from drawing_modules.improved_sketcher import ImprovedSketchWidget, SketchMode\n self.sketchWidget = ImprovedSketchWidget()\n \n # Connect to existing signals (adapt as needed)\n self.sketchWidget.constraint_applied.connect(self.draw_op_complete)\n self.sketchWidget.sketch_modified.connect(self.on_sketch_changed)\n \n # Connect toolbar buttons to new sketcher modes\n self.ui.pb_linetool.clicked.connect(lambda: self.sketchWidget.set_mode(SketchMode.LINE))\n self.ui.pb_rectool.clicked.connect(lambda: self.sketchWidget.set_mode(SketchMode.RECTANGLE))\n # ... etc for other buttons\n ```\n \n The improved sketcher provides these advantages:\n \n 1. **Better Architecture**: Clean separation of concerns, proper error handling\n 2. **Enhanced Features**: Rectangle and circle tools, improved constraints\n 3. **Better Performance**: Optimized rendering and interaction handling\n 4. **Extensibility**: Easy to add new tools and constraints\n 5. **Type Safety**: Proper type hints and validation\n 6. **Logging**: Built-in logging for debugging\n 7. **Settings**: Configurable snap and render settings\n \n Key differences to adapt:\n \n - Use SketchMode enum instead of string modes\n - Connect to new signal names (constraint_applied, geometry_created, sketch_modified)\n - Use set_mode() instead of individual mode methods\n - Access sketch data through self.sketch property\n - Use new geometry classes (Point2D, Line2D, Circle2D)\n """\n pass
|
|
|
|
|
|
if __name__ == "__main__":\n import sys\n \n app = QApplication(sys.argv)\n \n # Create and show the integration demo\n demo = SketcherIntegrationDemo()\n demo.show()\n \n print("Improved Sketcher Integration Demo")\n print("==================================")\n print("Features:")\n print("- Line, Rectangle, Circle, Point drawing")\n print("- Coincident, Horizontal, Vertical, Distance constraints")\n print("- Construction geometry mode")\n print("- Point, Grid, Midpoint snapping")\n print("- Zoom to fit")\n print("- Mouse wheel zoom")\n print("- Right-click to cancel operations")\n print("")\n print("Usage:")\n print("- Select a drawing tool and click in the viewport")\n print("- Right-click to finish multi-point operations")\n print("- Use constraint tools to add relationships")\n print("- Toggle construction mode for helper geometry")\n \n sys.exit(app.exec())
|