Загрузка данных
import sys
import keyboard
from PyQt6.QtCore import Qt
from PyQt6.QtGui import QPainter, QPen, QColor
from PyQt6.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QLabel, QSpinBox, QLineEdit
class DrawingOverlay(QWidget):
def __init__(self):
super().__init__()
# Инициализируем окно как подсказку поверх всех окон без рамок
self.setWindowFlags(
Qt.WindowType.FramelessWindowHint |
Qt.WindowType.WindowStaysOnTopHint |
Qt.WindowType.SubWindow
)
self.start_point = None
self.end_point = None
self.line_thickness = 5
self.is_active = False
def resize_to_screen(self):
screen = QApplication.primaryScreen().geometry()
self.setGeometry(screen)
def paintEvent(self, event):
painter = QPainter(self)
painter.setRenderHint(QPainter.RenderHint.Antialiasing)
# Если режим включен, но точки еще не выбраны — заливаем экран легкой дымкой,
# чтобы показать, что программа ждет кликов
if self.is_active and (not self.start_point or not self.end_point):
painter.fillRect(self.rect(), QColor(0, 0, 0, 30)) # Едва заметная маска (альфа 30)
return
# Если точки выбраны — рисуем линию на прозрачном фоне
if self.start_point and self.end_point:
pen = QPen(QColor(255, 0, 0, 255), self.line_thickness)
pen.setCapStyle(Qt.PenCapStyle.RoundCap)
painter.setPen(pen)
painter.drawLine(self.start_point, self.end_point)
class SettingsWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Настройки Линии")
self.setFixedSize(300, 150)
self.setWindowFlags(Qt.WindowType.WindowStaysOnTopHint)
self.overlay = DrawingOverlay()
self.overlay.resize_to_screen()
# Важно: С самого начала делаем окно прозрачным и сквозным
self.overlay.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground, True)
self.overlay.setAttribute(Qt.WidgetAttribute.WA_TransparentForMouseEvents, True)
self.overlay.show()
self.init_ui()
self.current_hotkey = "F4"
keyboard.add_hotkey(self.current_hotkey, self.toggle_drawing_mode)
self.click_count = 0
def init_ui(self):
central_widget = QWidget()
self.setCentralWidget(central_widget)
layout = QVBoxLayout(central_widget)
thick_layout = QHBoxLayout()
thick_label = QLabel("Толщина линии (px):")
self.thick_spin = QSpinBox()
self.thick_spin.setRange(1, 50)
self.thick_spin.setValue(5)
self.thick_spin.valueChanged.connect(self.change_thickness)
thick_layout.addWidget(thick_label)
thick_layout.addWidget(self.thick_spin)
layout.addLayout(thick_layout)
hk_layout = QHBoxLayout()
hk_label = QLabel("Горячая клавиша:")
self.hk_input = QLineEdit(r"F4")
self.hk_input.editingFinished.connect(self.update_hotkey)
hk_layout.addWidget(hk_label)
hk_layout.addWidget(self.hk_input)
layout.addLayout(hk_layout)
self.status_label = QLabel("Статус: Ожидание. Нажмите F4")
self.status_label.setStyleSheet("color: gray;")
layout.addWidget(self.status_label)
def change_thickness(self, value):
self.overlay.line_thickness = value
self.overlay.update()
def update_hotkey(self):
new_key = self.hk_input.text().strip()
if new_key and new_key != self.current_hotkey:
try:
keyboard.remove_hotkey(self.current_hotkey)
self.current_hotkey = new_key
keyboard.add_hotkey(self.current_hotkey, self.toggle_drawing_mode)
self.status_label.setText(f"Клавиша изменена на {new_key}")
except Exception:
self.status_label.setText("Ошибка: Неверная клавиша!")
def toggle_drawing_mode(self):
if not self.overlay.is_active:
# АКТИВАЦИЯ РЕЖИМА
self.overlay.is_active = True
self.click_count = 0
self.overlay.start_point = None
self.overlay.end_point = None
# Временно ОТКЛЮЧАЕМ сквозной клик мыши, чтобы поймать координаты
self.overlay.setAttribute(Qt.WidgetAttribute.WA_TransparentForMouseEvents, False)
self.overlay.mousePressEvent = self.handle_overlay_click
# Принудительно выводим окно на передний план и обновляем дымку
self.overlay.raise_()
self.overlay.update()
self.status_label.setText("Режим включен! Кликни точку 1")
self.status_label.setStyleSheet("color: green;")
else:
# СБРОС ЛИНИИ
self.reset_overlay()
def handle_overlay_click(self, event):
if event.button() == Qt.MouseButton.LeftButton:
if self.click_count == 0:
self.overlay.start_point = event.position().toPoint()
self.click_count += 1
self.status_label.setText("Точка 1 есть. Кликни точку 2")
self.overlay.update()
elif self.click_count == 1:
self.overlay.end_point = event.position().toPoint()
# ЛИНИЯ ГОТОВА: Возвращаем полную сквозную прозрачность для мыши
self.overlay.setAttribute(Qt.WidgetAttribute.WA_TransparentForMouseEvents, True)
self.overlay.update()
self.status_label.setText("Линия готова! F4 — стереть")
self.status_label.setStyleSheet("color: blue;")
self.click_count += 1
def reset_overlay(self):
self.overlay.is_active = False
self.overlay.start_point = None
self.overlay.end_point = None
self.overlay.setAttribute(Qt.WidgetAttribute.WA_TransparentForMouseEvents, True)
self.overlay.update()
self.status_label.setText(f"Сброшено. Нажмите {self.current_hotkey}")
self.status_label.setStyleSheet("color: gray;")
def closeEvent(self, event):
self.overlay.close()
keyboard.unhook_all()
event.accept()
if __name__ == "__main__":
app = QApplication(sys.argv)
window = SettingsWindow()
window.show()
sys.exit(app.exec())