Вот мой код:
```py
from PyQt5.QtWidgets import QWidget, QApplication
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtGui import QPainter, QColor
import sys
import threading
import time
import random


class LitRectangle(QWidget):
    def __init__(self, fov_size=512):
        super().__init__()
        # Установка флагов окна для отображения поверх всех окон
        self.setWindowFlags(
            Qt.FramelessWindowHint |
            Qt.WindowStaysOnTopHint |
            Qt.Tool
        )
        # Установка прозрачного фона
        self.setAttribute(Qt.WA_TranslucentBackground)

        # Инициализация параметров
        self.fov_size = fov_size
        self.boxes = []  # [{x:0, y:0, w:0, h:0}, ...]

        # Получение размеров экрана
        self.screen = QApplication.primaryScreen().geometry()

        # Вычисление позиции FOV workspace
        self.workspace_x = (self.screen.width() - self.fov_size) // 2
        self.workspace_y = (self.screen.height() - self.fov_size) // 2

        # Установка размеров окна на весь экран
        self.setGeometry(0, 0, self.screen.width(), self.screen.height())

        # Таймер для обновления отрисовки
        self.update_timer = QTimer()
        self.update_timer.timeout.connect(self.update)
        self.update_timer.start(16)  # ~60 FPS

        # Флаг для работы демонстрационного цикла
        self.is_running = False

    def set_boxes(self, new_boxes):
        """Установить новые боксы для отрисовки"""
        self.boxes = new_boxes

    def get_workspace_coords(self):
        """Получить координаты рабочей области (FOV)"""
        return {
            'x': self.workspace_x,
            'y': self.workspace_y,
            'size': self.fov_size
        }

    def paintEvent(self, event):
        """Событие отрисовки"""
        painter = QPainter(self)

        # Настройка прозрачности и цвета
        painter.setRenderHint(QPainter.Antialiasing)

        # Отрисовка рамки workspace
        workspace_color = QColor(255, 255, 255, 50)
        painter.setPen(workspace_color)
        painter.drawRect(
            self.workspace_x,
            self.workspace_y,
            self.fov_size,
            self.fov_size
        )

        # Отрисовка боксов
        box_color = QColor(0, 255, 0, 100)
        painter.setPen(box_color)
        painter.setBrush(QColor(0, 255, 0, 30))

        for box in self.boxes:
            # Преобразование координат относительно workspace
            x = self.workspace_x + box['x']
            y = self.workspace_y + box['y']
            w = box['w']
            h = box['h']

            painter.drawRect(x, y, w, h)

    def show_overlay(self):
        """Показать оверлей"""
        self.show()

    def hide_overlay(self):
        """Скрыть оверлей"""
        self.hide()

    def set_fov_size(self, size):
        """Изменить размер FOV"""
        self.fov_size = size
        self.workspace_x = (self.screen.width() - self.fov_size) // 2
        self.workspace_y = (self.screen.height() - self.fov_size) // 2

    def _demo_thread(self):
        """Демонстрационный поток с случайными квадратами"""
        while self.is_running:
            # Генерация двух случайных квадратов
            boxes = []
            for _ in range(2):
                x = random.randint(0, self.fov_size - 100)
                y = random.randint(0, self.fov_size - 100)
                w = random.randint(50, 100)
                h = random.randint(50, 100)
                boxes.append({'x': x, 'y': y, 'w': w, 'h': h})

            self.set_boxes(boxes)
            time.sleep(0.5)

    def run_thread(self):
        """Запуск в отдельном потоке"""
        self.is_running = True
        self.show_overlay()

        # Запуск демонстрационного потока, если нужен
        if False:  # Отключено для вашего случая
            demo_thread = threading.Thread(target=self._demo_thread)
            demo_thread.daemon = True
            demo_thread.start()

    def stop(self):
        """Остановка приложения"""
        self.is_running = False
        self.hide()
```

main.py
```py
import random
import time
from LitAiM.LitRectangle import LitRectangle
from PyQt5.QtWidgets import QApplication
import sys
import threading

# Создание приложения
app = QApplication(sys.argv)

# Создание оверлея
overlay = LitRectangle(fov_size=512)
overlay.run_thread()

def update_boxes():
    while True:
        time.sleep(0.01)
        overlay.set_boxes([
            {'x': random.randint(1, 300), 'y': random.randint(1, 300), 'w': 50, 'h': 50},
            {'x': random.randint(1, 300), 'y': random.randint(1, 300), 'w': 100, 'h': 100}
        ])
        print("next")

# Запуск обновления боксов в отдельном потоке
update_thread = threading.Thread(target=update_boxes)
update_thread.daemon = True
update_thread.start()

# Запуск основного цикла Qt
sys.exit(app.exec_())
```
Сделай рефакторинг кода модуля, а также чтобы код main.py был более дружелюбным. Мне не нравится `sys.exit(app.exec_())`. Я не смогу тогда использовать этот код в качестве чего-то необязательного. Мне нужно будет основываясь на нем строить приложение. А я хочу его использовать свободно