@@ -15,15 +15,13 @@ def __init__(self, parent: QtWidgets.QWidget = None, *args, **kwargs):
1515 self ._marquee : bool = True
1616 self .timer = QtCore .QTimer ()
1717 self .timer .timeout .connect (self ._scroll_text )
18- self .delay_timer = QtCore .QTimer ()
19- self .delay_timer .setSingleShot (True )
20- self .delay_timer .timeout .connect (self ._start_marquee )
21-
2218 self .scroll_pos = 0.0
23- self .marquee_spacing = 20
19+ self .marquee_spacing = 40
20+ self .scroll_speed = 40
21+ self .scroll_animation_speed = 30
22+ self .max_loops = 2
23+ self .loop_count = 0
2424 self .paused = False
25- self .scroll_speed = 20
26- self .scroll_animation_speed = 50
2725 self .setMouseTracking (True )
2826 self .setTabletTracking (True )
2927 self .setSizePolicy (
@@ -41,8 +39,8 @@ def __init__(self, parent: QtWidgets.QWidget = None, *args, **kwargs):
4139 self .glow_animation .finished .connect (self .repaint )
4240
4341 self .total_scroll_width : float = 0.0
44- self .marquee_delay = 5000
45- self .loop_count = 0
42+ self .text_width : float = 0.0
43+ self .label_width : float = 0. 0
4644 self .first_run = True
4745
4846 def resizeEvent (self , a0 : QtGui .QResizeEvent ) -> None :
@@ -67,6 +65,7 @@ def setPixmap(self, a0: QtGui.QPixmap) -> None:
6765 def setText (self , text : str ) -> None :
6866 """Set widget text"""
6967 self ._text = text
68+ self .scroll_pos = 0.0
7069 self .update_text_metrics ()
7170
7271 @property
@@ -102,7 +101,7 @@ def marquee(self) -> bool:
102101 return self ._marquee
103102
104103 @marquee .setter
105- def marquee (self , activate ) -> None :
104+ def marquee (self , activate : bool ) -> None :
106105 self ._marquee = activate
107106 self .update_text_metrics ()
108107
@@ -130,10 +129,9 @@ def start_glow_animation(self) -> None:
130129 """Start glow animation"""
131130 self .glow_animation .setDuration (self .animation_speed )
132131 start_color = QtGui .QColor ("#00000000" )
132+ end_color = QtGui .QColor ("#E95757" )
133133 self .glow_animation .setStartValue (start_color )
134- base_end_color = QtGui .QColor ("#E95757" )
135- self .glow_animation .setEndValue (base_end_color )
136-
134+ self .glow_animation .setEndValue (end_color )
137135 self .glow_animation .setDirection (QtCore .QPropertyAnimation .Direction .Forward )
138136 self .glow_animation .setLoopCount (- 1 )
139137 self .glow_animation .start ()
@@ -155,145 +153,98 @@ def update_text_metrics(self) -> None:
155153 self .total_scroll_width = float (self .text_width + self .marquee_spacing )
156154
157155 if self ._marquee and self .text_width > self .label_width :
158- self .start_scroll ()
156+ self .scroll_pos = 0.0
157+ QtCore .QTimer .singleShot (2000 , self .start_scroll )
159158 else :
160159 self .stop_scroll ()
161160 self .scroll_pos = 0.0
162161 self .update ()
163162
164163 def start_scroll (self ) -> None :
165- """Start marquee text scroll effect """
166- if not self .delay_timer . isActive () and not self . timer .isActive ():
164+ """Start or restart the scrolling. """
165+ if not self .timer .isActive ():
167166 self .scroll_pos = 0
168167 self .loop_count = 0
169- if self .first_run :
170- self .delay_timer .start (self .marquee_delay )
171- self .first_run = False
172- else :
173- self ._start_marquee ()
174-
175- def _start_marquee (self ) -> None :
176- """Starts the actual marquee animation after the delay or immediately."""
177- if not self .timer .isActive ():
178168 self .timer .start (self .scroll_animation_speed )
179169
180170 def stop_scroll (self ) -> None :
181171 """Stop marquee text scroll effect"""
182172 self .timer .stop ()
183- self .delay_timer . stop ()
173+ self .repaint ()
184174
185175 def _scroll_text (self ) -> None :
186- if self .paused :
176+ """Smoothly scroll the text leftwards."""
177+ if not self ._marquee or self .paused :
187178 return
188-
189179 p_to_m = self .scroll_speed * (self .scroll_animation_speed / 1000.0 )
190180 self .scroll_pos -= p_to_m
191-
192181 if self .scroll_pos <= - self .total_scroll_width :
193182 self .loop_count += 1
194- if self .loop_count >= 2 :
183+ if self .loop_count >= self . max_loops :
195184 self .stop_scroll ()
196- else :
197- self .scroll_pos = 0
198-
199- self .repaint ()
185+ self .scroll_pos = 0.0
186+ self .update ()
200187
201188 def paintEvent (self , a0 : QtGui .QPaintEvent ) -> None :
202189 """Re-implemented method, paint widget"""
203- qp = QtWidgets .QStylePainter (self )
204- opt = QtWidgets .QStyleOption ()
205- opt .initFrom (self )
206-
190+ qp = QtGui .QPainter (self )
207191 qp .setRenderHint (qp .RenderHint .Antialiasing , True )
208192 qp .setRenderHint (qp .RenderHint .SmoothPixmapTransform , True )
209193 qp .setRenderHint (qp .RenderHint .LosslessImageRendering , True )
210- _rect = self .rect ()
211- _style = self .style ()
212-
213- icon_margin = _style .pixelMetric (_style .PixelMetric .PM_HeaderMargin , opt , self )
214- if not _style or _rect .isNull ():
215- return
194+ rect = self .contentsRect ()
195+ if self ._background_color :
196+ qp .setBrush (self ._background_color )
197+ qp .setPen (QtCore .Qt .PenStyle .NoPen )
198+ if self ._rounded :
199+ path = QtGui .QPainterPath ()
200+ path .addRoundedRect (QtCore .QRectF (rect ), 10 , 10 )
201+ qp .fillPath (path , self ._background_color )
202+ else :
203+ qp .fillRect (rect , self ._background_color )
216204
217205 if self .icon_pixmap :
218- qp .setCompositionMode (qp .CompositionMode .CompositionMode_SourceOver )
219- _icon_rect = QtCore .QRectF (
220- 0.0 + icon_margin ,
221- 0.0 + icon_margin ,
222- self .width () - icon_margin ,
223- self .height () - icon_margin ,
224- )
225- _icon_scaled = self .icon_pixmap .scaled (
226- _icon_rect .size ().toSize (),
206+ icon_rect = QtCore .QRectF (0 , 0 , self .height (), self .height ())
207+ scaled = self .icon_pixmap .scaled (
208+ icon_rect .size ().toSize (),
227209 QtCore .Qt .AspectRatioMode .KeepAspectRatio ,
228210 QtCore .Qt .TransformationMode .SmoothTransformation ,
229211 )
230- scaled_width = _icon_scaled .width ()
231- scaled_height = _icon_scaled .height ()
232- adjusted_x = (_icon_rect .width () - scaled_width ) / 2.0
233- adjusted_y = (_icon_rect .height () - scaled_height ) / 2.0
234- adjusted_icon_rect = QtCore .QRectF (
235- _icon_rect .x () + adjusted_x ,
236- _icon_rect .y () + adjusted_y ,
237- scaled_width ,
238- scaled_height ,
239- )
240- qp .drawPixmap (
241- adjusted_icon_rect , _icon_scaled , _icon_scaled .rect ().toRectF ()
242- )
243-
244- big_rect = QtGui .QPainterPath ()
245- rect = self .contentsRect ().toRectF ()
246- big_rect .addRoundedRect (rect , 10.0 , 10.0 , QtCore .Qt .SizeMode .AbsoluteSize )
247- mini_rect = QtCore .QRectF (
248- (rect .width () - rect .width () * 0.99 ) / 2 ,
249- (rect .height () - rect .height () * 0.85 ) / 2 ,
250- rect .width () * 0.99 ,
251- rect .height () * 0.85 ,
252- )
253- mini_path = QtGui .QPainterPath ()
254- mini_path .addRoundedRect (mini_rect , 10.0 , 10.0 , QtCore .Qt .SizeMode .AbsoluteSize )
255- subtracted = big_rect .subtracted (mini_path )
256-
212+ qp .drawPixmap (icon_rect .toRect (), scaled )
257213 if self .glow_animation .state () == self .glow_animation .State .Running :
258- qp . setCompositionMode ( qp . CompositionMode . CompositionMode_SourceAtop )
259- subtracted . setFillRule (QtCore .Qt . FillRule . OddEvenFill )
260- qp .fillPath (subtracted , self .glow_color )
214+ path = QtGui . QPainterPath ( )
215+ path . addRoundedRect (QtCore .QRectF ( rect ), 10 , 10 )
216+ qp .fillPath (path , self .glow_color )
261217 if self ._text :
262- qp .setCompositionMode (qp .CompositionMode .CompositionMode_SourceOver )
263-
264- text_rect = self .contentsRect ()
265- text_rect .translate (int (self .scroll_pos ), 0 )
266- text_path = QtGui .QPainterPath ()
267- text_path .addRect (self .contentsRect ().toRectF ())
268- qp .setClipPath (text_path )
269-
270218 text_option = QtGui .QTextOption (self .alignment ())
271219 text_option .setWrapMode (QtGui .QTextOption .WrapMode .NoWrap )
272- qp .drawText (
273- QtCore .QRectF (text_rect ),
274- self ._text ,
275- text_option ,
220+ qp .save ()
221+ qp .setClipRect (rect )
222+ baseline_y = (
223+ rect .y ()
224+ + (
225+ rect .height ()
226+ + self .fontMetrics ().ascent ()
227+ - self .fontMetrics ().descent ()
228+ )
229+ / 2
276230 )
277- if self ._marquee and self .text_width > self .label_width :
278- second_text_rect = self .rect ()
279- second_text_rect .translate (
280- int (self .scroll_pos + self .text_width + self .label_width / 2 ),
281- 0 ,
231+
232+ if self .text_width > self .label_width :
233+ qp .drawText (
234+ QtCore .QPointF (rect .x () + self .scroll_pos , baseline_y ), self ._text
282235 )
283- qp .drawText (QtCore .QRectF (second_text_rect ), self ._text , text_option )
284- draw_rect = QtCore .QRectF (
285- self .contentsRect ().x ()
286- + self .scroll_pos
287- + self .text_width
288- + self .marquee_spacing ,
289- self .contentsRect ().y (),
290- self .text_width ,
291- self .contentsRect ().height (),
236+ # Draw scrolling repeater text
237+ qp .drawText (
238+ QtCore .QPointF (
239+ rect .x () + self .scroll_pos + self .total_scroll_width , baseline_y
240+ ),
241+ self ._text ,
292242 )
293- qp .drawText (draw_rect , self ._text , text_option )
294243 else :
295- text_rect = self .contentsRect ().toRectF ()
296- qp .drawText (text_rect , self ._text , text_option )
244+ center_x = rect .x () + (rect .width () - self .text_width ) / 2
245+
246+ qp .drawText (QtCore .QPointF (center_x , baseline_y ), self ._text )
247+ qp .restore ()
297248
298249 qp .end ()
299250
0 commit comments