1+ import sys
2+ from PyQt5 .QtWidgets import QApplication , QWidget
3+ from PyQt5 .QtCore import Qt , QPoint
4+ from PyQt5 .QtGui import QPainter , QColor , QPainterPath , QPen , QLinearGradient
5+
6+ class RoundedWindow (QWidget ):
7+ def __init__ (self ):
8+ super ().__init__ ()
9+
10+ # Настройка окна
11+ self .setWindowFlags (Qt .FramelessWindowHint ) # Убираем рамку
12+ self .setAttribute (Qt .WA_TranslucentBackground ) # Делаем фон прозрачным
13+
14+ # Размеры окна
15+ self .window_width = 400
16+ self .window_height = 400
17+
18+ # Радиус закругления
19+ self .corner_radius = 40
20+
21+ # Переменные для перемещения окна
22+ self .dragging = False
23+ self .offset = QPoint ()
24+
25+ # Переменные для изменения размера
26+ self .resizing = False
27+ self .resize_edge = None
28+ self .min_size = 200
29+ self .max_size = 800
30+
31+ # Установка размеров
32+ self .resize (self .window_width , self .window_height )
33+
34+ def paintEvent (self , event ):
35+ # Создаем QPainter для рисования
36+ painter = QPainter (self )
37+ painter .setRenderHint (QPainter .Antialiasing ) # Включаем сглаживание
38+
39+ # Создаем путь с закругленными краями
40+ path = QPainterPath ()
41+ path .addRoundedRect (0 , 0 ,
42+ self .width (),
43+ self .height (),
44+ self .corner_radius ,
45+ self .corner_radius )
46+
47+ # Заливаем черным цветом
48+ painter .fillPath (path , QColor (30 , 30 , 30 ))
49+
50+ # Рисуем блик вокруг окна
51+ self .draw_glow (painter )
52+
53+ # Рисуем градиентный верхний край для красоты
54+ self .draw_top_gradient (painter , path )
55+
56+ def draw_glow (self , painter ):
57+ """Рисуем свечение вокруг окна"""
58+ glow_radius = 10
59+ glow_color = QColor (100 , 150 , 255 , 50 ) # Голубоватое свечение
60+
61+ # Рисуем несколько контуров с разной прозрачностью для эффекта свечения
62+ for i in range (glow_radius , 0 , - 1 ):
63+ alpha = 30 - (i * 3 )
64+ if alpha < 0 :
65+ alpha = 0
66+
67+ glow_path = QPainterPath ()
68+ glow_path .addRoundedRect (- i , - i ,
69+ self .width () + i * 2 ,
70+ self .height () + i * 2 ,
71+ self .corner_radius + i ,
72+ self .corner_radius + i )
73+
74+ painter .setPen (QPen (QColor (100 , 150 , 255 , alpha ), 2 ))
75+ painter .setBrush (Qt .NoBrush )
76+ painter .drawPath (glow_path )
77+
78+ def draw_top_gradient (self , painter , path ):
79+ """Рисуем градиент на верхней части окна"""
80+ gradient = QLinearGradient (0 , 0 , 0 , 50 )
81+ gradient .setColorAt (0 , QColor (60 , 60 , 60 ))
82+ gradient .setColorAt (1 , QColor (30 , 30 , 30 ))
83+
84+ painter .setPen (Qt .NoPen )
85+ painter .setBrush (gradient )
86+ painter .drawPath (path )
87+
88+ def mousePressEvent (self , event ):
89+ # Определяем, где произошел клик
90+ if event .button () == Qt .LeftButton :
91+ # Проверяем, не кликнули ли мы в области для изменения размера
92+ if self .is_resize_area (event .pos ()):
93+ self .resizing = True
94+ self .resize_edge = self .get_resize_edge (event .pos ())
95+ self .setCursor (Qt .SizeFDiagCursor )
96+ else :
97+ # Если не в области изменения размера, то перемещаем окно
98+ self .dragging = True
99+ self .offset = event .pos ()
100+ self .setCursor (Qt .ClosedHandCursor )
101+
102+ def mouseMoveEvent (self , event ):
103+ if self .dragging :
104+ # Перемещаем окно
105+ new_pos = event .globalPos () - self .offset
106+ self .move (new_pos )
107+ elif self .resizing and self .resize_edge :
108+ # Изменяем размер окна
109+ self .resize_window (event .pos ())
110+
111+ def mouseReleaseEvent (self , event ):
112+ # Сбрасываем флаги при отпускании кнопки мыши
113+ self .dragging = False
114+ self .resizing = False
115+ self .resize_edge = None
116+ self .setCursor (Qt .ArrowCursor )
117+
118+ def resize_window (self , mouse_pos ):
119+ """Изменяет размер окна в зависимости от границы"""
120+ if self .resize_edge == 'bottom_right' :
121+ new_width = max (self .min_size , mouse_pos .x ())
122+ new_height = max (self .min_size , mouse_pos .y ())
123+ self .resize (new_width , new_height )
124+ elif self .resize_edge == 'right' :
125+ new_width = max (self .min_size , mouse_pos .x ())
126+ self .resize (new_width , self .height ())
127+ elif self .resize_edge == 'bottom' :
128+ new_height = max (self .min_size , mouse_pos .y ())
129+ self .resize (self .width (), new_height )
130+
131+ # Обновляем окно
132+ self .update ()
133+
134+ def is_resize_area (self , pos ):
135+ """Проверяет, находится ли позиция в области для изменения размера"""
136+ resize_margin = 10
137+
138+ # Проверяем правую границу
139+ if pos .x () > self .width () - resize_margin :
140+ return True
141+ # Проверяем нижнюю границу
142+ if pos .y () > self .height () - resize_margin :
143+ return True
144+ # Проверяем нижний правый угол
145+ if (pos .x () > self .width () - resize_margin and
146+ pos .y () > self .height () - resize_margin ):
147+ return True
148+
149+ return False
150+
151+ def get_resize_edge (self , pos ):
152+ """Определяет, какую границу мы изменяем"""
153+ resize_margin = 10
154+
155+ if (pos .x () > self .width () - resize_margin and
156+ pos .y () > self .height () - resize_margin ):
157+ return 'bottom_right'
158+ elif pos .x () > self .width () - resize_margin :
159+ return 'right'
160+ elif pos .y () > self .height () - resize_margin :
161+ return 'bottom'
162+
163+ return None
164+
165+ if __name__ == '__main__' :
166+ app = QApplication (sys .argv )
167+
168+ # Создаем окно
169+ window = RoundedWindow ()
170+
171+ # Устанавливаем заголовок
172+ window .setWindowTitle ("Rounded Window with Glow" )
173+
174+ # Показываем окно
175+ window .show ()
176+
177+ sys .exit (app .exec_ ())
0 commit comments