proposal.md 6.29 KB

Proposal: Migrate from tkinter to PySide6

Overview

Change ID: migrate-to-pyside6

Problem: Despite multiple attempts to fix tkinter rendering issues on macOS (ttk style configuration, tk.Frame replacement), the LoginWindow remains invisible. tkinter has fundamental macOS compatibility issues that cannot be reliably resolved.

Impact: Critical - Application is unusable on macOS. Migration to a modern, reliable GUI framework is necessary.

Root Cause Analysis

Tkinter Limitations

After three failed fix attempts:

  1. Entry widget styling (added bg/fg colors)
  2. ttk.Frame style configuration (added TFrame/TLabel styles)
  3. tk.Frame replacement (replaced all ttk.Frame with tk.Frame)

Conclusion: tkinter has deep macOS rendering issues that cannot be solved with configuration changes. The framework is aging and has poor macOS support.

Why tkinter Fails on macOS

  • Outdated architecture: tkinter wraps Tk/Tcl from the 1990s
  • Poor theme support: ttk themes don't work consistently on macOS
  • macOS-specific bugs: Many unresolved issues in the bug tracker
  • No native rendering: Uses X11-style rendering that conflicts with macOS

Proposed Solution: Migrate to PySide6

Why PySide6

Technical Benefits:

  1. Native rendering: True native widgets on each platform
  2. Official support: Maintained by Qt Company (not third-party)
  3. Modern: Qt 6 with latest features and performance improvements
  4. Cross-platform: Excellent macOS, Windows, Linux support
  5. Better Windows support: Native Windows 11 styling, high-DPI, touch support

Licensing:

  • PySide6: LGPL (can use in commercial apps without opening source code)
  • PyQt5: GPL (requires commercial license or open source)

Long-term:

  • Qt 6 is the current major version, actively developed
  • Qt 5 (PyQt5) is in maintenance mode
  • Better future-proofing

Migration Scope

Files to Replace:

  • image_generator.py - Complete rewrite using Qt

New Structure:

# Qt-based implementation
from PySide6.QtWidgets import (
    QApplication, QMainWindow, QDialog, QWidget,
    QVBoxLayout, QHBoxLayout, QLabel, QLineEdit,
    QPushButton, QCheckBox, QTextEdit, QComboBox
)
from PySide6.QtCore import Qt, QThread, Signal
from PySide6.QtGui import QPixmap, QFont

class LoginDialog(QDialog):
    """Qt-based login window"""
    # Clean, modern dialog with native rendering

class ImageGeneratorWindow(QMainWindow):
    """Qt-based main application window"""
    # Modern UI with better layout management

Functionality Preserved:

  • ✓ Database authentication
  • ✓ Remember username/password
  • ✓ Image generation with Gemini API
  • ✓ Reference image upload
  • ✓ Image preview and download
  • ✓ Prompt management (favorites)
  • ✓ All existing features

UI Improvements:

  • Better layout management (Qt layouts vs pack/grid)
  • Native look and feel on all platforms
  • Smooth threading (QThread vs threading.Thread)
  • Better image handling (QPixmap)
  • Modern file dialogs
  • Better styling options (QSS - Qt Style Sheets)

Migration Strategy

Phase 1: LoginDialog (Priority: High)

  • Rewrite LoginWindow as QDialog
  • Implement authentication logic
  • Test on macOS to verify visibility
  • Estimated: 2-3 hours

Phase 2: ImageGeneratorWindow (Priority: High)

  • Rewrite ImageGeneratorApp as QMainWindow
  • Implement all existing features
  • Improve layout and responsiveness
  • Estimated: 4-6 hours

Phase 3: Testing & Polish (Priority: Medium)

  • Cross-platform testing
  • UI polish and refinements
  • Performance optimization
  • Estimated: 1-2 hours

Total Estimated Effort: 8-11 hours

Code Structure Comparison

Current (tkinter):

# Procedural, pack-based layout
main_frame = tk.Frame(self.root, bg='white', padx=40, pady=40)
main_frame.pack(fill="both", expand=True)

username_label = tk.Label(main_frame, text="用户名", ...)
username_label.pack(anchor="w")

Proposed (PySide6):

# Layout-based, cleaner structure
layout = QVBoxLayout()

username_label = QLabel("用户名")
username_label.setStyleSheet("color: #666666; font-size: 10pt;")
layout.addWidget(username_label)

self.setLayout(layout)

Benefits:

  • Declarative layouts vs imperative pack/grid
  • Better separation of concerns
  • Easier to maintain and modify
  • Responsive resizing out of the box

Alternative Considered: PyQt5

Rejected because:

  • GPL license (restrictive for commercial use)
  • Based on Qt 5 (older version)
  • Not officially maintained by Qt
  • Worse Windows 11 integration

Dependencies

New Dependency:

  • PySide6>=6.6.0 (latest stable)

Removed Dependency:

  • None (PIL, google-genai, pymysql all compatible with Qt)

Installation:

pip install PySide6

Risks & Mitigation

Risks:

  1. Learning curve: Team needs to learn Qt

    • Mitigation: Qt has excellent documentation, similar concepts to other GUIs
  2. Breaking changes: Complete UI rewrite

    • Mitigation: Preserve all functionality, test thoroughly
  3. Binary size: Qt apps are larger

    • Mitigation: Acceptable for desktop app, better UX worth it
  4. Migration time: ~8-11 hours of work

    • Mitigation: Necessary to make app usable on macOS

Benefits

Immediate:

  • ✓ LoginWindow visible and functional on macOS
  • ✓ Native look on all platforms
  • ✓ Better reliability

Long-term:

  • ✓ Modern, maintained framework
  • ✓ Better performance
  • ✓ More UI possibilities (animations, effects)
  • ✓ Easier to add features
  • ✓ Better cross-platform consistency

Testing Strategy

Manual Testing:

  • macOS: Verify LoginDialog visible and functional
  • macOS: Verify main window renders correctly
  • Windows: Test UI appearance and functionality
  • Linux: Test if available

Functional Testing:

  • Login flow works
  • Image generation works
  • File operations work
  • Database interaction works
  • Config save/load works

Rollback Plan

If migration fails:

  • Keep current tkinter code in git history
  • Can revert if needed
  • Low risk: Qt is proven technology

Recommendation

Proceed with PySide6 migration: This is the only reliable solution to fix the macOS visibility issue. tkinter has proven incompatible with macOS despite multiple fix attempts. PySide6 provides a modern, well-supported foundation for cross-platform desktop applications.