Skip to content

Commit

Permalink
Merge pull request #124 from ChinaIceF/reconst
Browse files Browse the repository at this point in the history
perf: use `SiExpAccelerateAnimation` to prevent lagging
  • Loading branch information
ChinaIceF authored Aug 24, 2024
2 parents b2b6fd8 + 4bd28b6 commit ed9e377
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 29 deletions.
2 changes: 0 additions & 2 deletions examples/Gallery for siui/components/page_icons/page_icons.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
from siui.components.combobox import SiComboBox
from siui.components.page import SiPage
from siui.core.color import SiColor
from siui.core.effect import SiQuickEffect
from siui.core.globals import SiGlobal
from siui.core.silicon import Si

Expand Down Expand Up @@ -68,7 +67,6 @@ def __init__(self, *args, **kwargs):
self.package_operation_container = SiDenseHContainer(self)
self.package_operation_container.setFixedHeight(48)
self.package_operation_container.setAlignment(Qt.AlignCenter)
# SiQuickEffect.applyDropShadowOn(self.package_operation_container, (0, 0, 0, 80), blur_radius=32)

self.package_selection_description = SiLabel(self)
self.package_selection_description.setStyleSheet(f"color: {self.colorGroup().fromToken(SiColor.TEXT_D)}")
Expand Down
35 changes: 24 additions & 11 deletions siui/components/widgets/container.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import random
import time
from typing import Union

from PyQt5.Qt import QColor
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtWidgets import QGraphicsDropShadowEffect
from PyQt5.QtWidgets import QGraphicsDropShadowEffect, QWidget

from siui.components.widgets.label import SiLabel
from siui.components.widgets.abstracts.container import ABCSiDividedContainer
from siui.components.widgets.abstracts.widget import SiWidget
from siui.components.widgets.label import SiLabel


class PlaceHolderWidget(QWidget):
pass


class ABCDenseContainer(SiWidget):
Expand Down Expand Up @@ -76,6 +79,14 @@ def setSpacing(self, spacing: int):
def widgets(self):
raise NotImplementedError()

@staticmethod
def get_widget_except_placeholders(widgets):
no_placeholders = []
for widget in widgets:
if isinstance(widget, PlaceHolderWidget) is False:
no_placeholders.append(widget)
return no_placeholders

def __enter__(self):
return self

Expand All @@ -102,7 +113,7 @@ def addPlaceholder(self, length, side="left", index=10000):
:param index: 插入位置
:return:
"""
new_label = SiLabel(self)
new_label = PlaceHolderWidget(self)
new_label.setVisible(False)
new_label.resize(length, 0)
self.addWidget(new_label, side=side, index=index)
Expand Down Expand Up @@ -140,13 +151,14 @@ def getSpareSpace(self):

def widgets(self, side=None):
if side is None:
return self.widgets_left + self.widgets_right
widgets = self.widgets_left + self.widgets_right
elif side == "left":
return self.widgets_left
widgets = self.widgets_left
elif side == "right":
return self.widgets_right
widgets = self.widgets_right
else:
raise ValueError(f"Unexpected side: {side}")
return self.get_widget_except_placeholders(widgets)

def removeWidget(self, widget):
"""
Expand Down Expand Up @@ -287,7 +299,7 @@ def addPlaceholder(self, length, side="top", index=10000):
:param index: 插入位置
:return:
"""
new_label = SiLabel(self)
new_label = PlaceHolderWidget(self)
new_label.setVisible(False)
new_label.resize(0, length)
self.addWidget(new_label, side=side, index=index)
Expand Down Expand Up @@ -349,13 +361,14 @@ def getSpareSpace(self):

def widgets(self, side=None):
if side is None:
return self.widgets_top + self.widgets_bottom
widgets = self.widgets_top + self.widgets_bottom
elif side == "top":
return self.widgets_top
widgets = self.widgets_top
elif side == "bottom":
return self.widgets_bottom
widgets = self.widgets_bottom
else:
raise ValueError(f"Unexpected side: {side}")
return self.get_widget_except_placeholders(widgets)

def removeWidget(self, widget):
"""
Expand Down
4 changes: 2 additions & 2 deletions siui/components/widgets/scrollarea.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from siui.components.widgets.abstracts.widget import SiWidget
from siui.components.widgets.label import SiDraggableLabel, SiLabel
from siui.core.animation import SiExpAnimation
from siui.core.animation import SiExpAnimation, SiExpAccelerateAnimation
from siui.core.globals import SiGlobal
from siui.core.silicon import Si

Expand Down Expand Up @@ -31,7 +31,7 @@ def __init__(self, *args, **kwargs):
self.scroll_bar_horizontal.dragged.connect(self._scroll_horizontal_handler)

# 定义滚动动画,为了让所有控件都能用上滚动动画
self.widget_scroll_animation = SiExpAnimation(self)
self.widget_scroll_animation = SiExpAccelerateAnimation(self)
self.widget_scroll_animation.setFactor(1/9)
self.widget_scroll_animation.setBias(1)
self.widget_scroll_animation.setCurrent([0, 0])
Expand Down
2 changes: 1 addition & 1 deletion siui/core/animation/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from siui.core.animation import abstract
from siui.core.animation.animation import SiCounterAnimation, SiExpAnimation # noqa: F401
from siui.core.animation.animation import SiCounterAnimation, SiExpAccelerateAnimation, SiExpAnimation # noqa: F401
from siui.core.animation.group import SiAnimationGroup # noqa: F401


Expand Down
95 changes: 82 additions & 13 deletions siui/core/animation/animation.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import numpy

import siui.core.animation.abstract as abstract
from .abstract import ABCSiAnimation, Curve


class SiExpAnimation(abstract.ABCSiAnimation):
"""
级数动画类,每次动画的进行步长都与当前进度有关
"""
class SiExpAnimation(ABCSiAnimation):
""" 级数动画类,每次动画的进行步长都与当前进度有关 """

def __init__(self, parent=None):
super().__init__(parent)
Expand All @@ -18,15 +16,13 @@ def setFactor(self, factor: float):
"""
Set the factor of the animation.
:param factor: number between 0 and 1
:return:
"""
self.factor = factor

def setBias(self, bias: float):
"""
Set the factor of the animation.
:param bias: positive float number
:return:
"""
if bias <= 0:
raise ValueError(f"Bias is expected to be positive but met {bias}")
Expand All @@ -44,10 +40,7 @@ def _step_length(self):
return arr

def isCompleted(self):
"""
To check whether we meet the point that the animation should stop
:return: bool
"""
""" To check whether we meet the point that the animation should stop """
return (self._distance() == 0).all()

def _process(self):
Expand All @@ -66,14 +59,90 @@ def _process(self):
self.ticked.emit(self.current_)


class SiCounterAnimation(abstract.ABCSiAnimation):
class SiExpAccelerateAnimation(SiExpAnimation):
def __init__(self, parent=None):
super().__init__(parent)

self.accelerate_function = lambda x: x ** 1.6
self.step_length_bound = 0
self.frame_counter = 0

def setAccelerateFunction(self, function):
self.accelerate_function = function

def setStepLengthBound(self, bound):
self.step_length_bound = bound

def refreshStepLengthBound(self):
self.setStepLengthBound(min(self.accelerate_function(self.frame_counter), 10000)) # prevent getting too large

def _step_length(self):
dis = self._distance()
if (abs(dis) <= self.bias).all() is True:
return dis

cut = numpy.array(abs(dis) <= self.bias, dtype="int8")
arr = numpy.clip(abs(dis) * self.factor + self.bias, 0, self.step_length_bound) # 基本指数动画运算
arr = arr * (numpy.array(dis > 0, dtype="int8") * 2 - 1) # 确定动画方向
arr = arr * (1 - cut) + dis * cut # 对于差距小于偏置的项,直接返回差距
return arr

def _process(self):
self.frame_counter += 1
self.refreshStepLengthBound()
super()._process()

def stop(self, delay=None):
super().stop(delay)
self.frame_counter = 0
self.refreshStepLengthBound()


class SiSqrExpAnimation(ABCSiAnimation):
def __init__(self, parent=None):
super().__init__(parent)

self.mean_rate = 0.5
self.base = 1/2
self.peak = 10
self.bias = 1
raise NotImplementedError()

def setMeanRate(self, mean_rate):
self.mean_rate = mean_rate

def setBase(self, base):
self.base = base

def setPeak(self, peak):
self.peak = peak

def setBias(self, bias):
self.bias = bias

def _step_length(self):
dis = self._distance()
if (abs(dis) <= self.bias).all() is True:
return dis

cut = numpy.array(abs(dis) <= self.bias, dtype="int8")
arr = abs(dis) * self.factor + self.bias # 基本指数动画运算
arr = arr * (numpy.array(dis > 0, dtype="int8") * 2 - 1) # 确定动画方向
arr = arr * (1 - cut) + dis * cut # 对于差距小于偏置的项,直接返回差距
return arr

def isCompleted(self):
return (self._distance() == 0).all()


class SiCounterAnimation(ABCSiAnimation):
def __init__(self, parent=None):
super().__init__(parent)

self.duration = 1000 # 动画总时长,单位毫秒
self.reversed = False # 是否倒序运行动画
self.counter_addend = self._get_addend()
self.curve = abstract.Curve.LINEAR
self.curve = Curve.LINEAR

def setReversed(self, reversed_):
"""
Expand Down

0 comments on commit ed9e377

Please sign in to comment.