zhiyiYo / PyQt-Fluent-Widgets

A fluent design widgets library based on C++ Qt/PyQt/PySide. Make Qt Great Again.
https://qfluentwidgets.com
GNU General Public License v3.0
5.39k stars 520 forks source link

继承ElevatedCardWidget的自定义组件,添加到FlowLayout布局(参数needAni=True)时,鼠标在动画路径中,会出现卡片重叠的现象。 #503

Closed keymou closed 1 year ago

keymou commented 1 year ago

Describe the bug 继承ElevatedCardWidget的自定义组件,添加到FlowLayout布局(参数needAni=True)时,鼠标在动画路径中,会出现卡片重叠的现象。

Environment 环境信息

To Reproduce 复现问题的步骤,推荐使用 gif 进行演示。 动画

Code 最小复现代码

from functools import singledispatch, update_wrapper
from PyQt5.QtCore import pyqtProperty, pyqtSignal as Signal
from PyQt5.QtWidgets import QHBoxLayout
from qfluentwidgets import BodyLabel, CardWidget, TransparentToolButton, ElevatedCardWidget

from ..common.icon import Icon

class Singledispatchmethod:

    def __init__(self, func):
        if not callable(func) and not hasattr(func, "__get__"):
            raise TypeError(f"{func!r} is not callable or a descriptor")

        self.dispatcher = singledispatch(func)
        self.func = func

    def register(self, cls, method=None):
        """generic_method.register(cls, func) -> func

        Registers a new implementation for the given *cls* on a *generic_method*.
        """
        return self.dispatcher.register(cls, func=method)

    def __get__(self, obj, cls=None):
        def _method(*args, **kwargs):
            if args:
                method = self.dispatcher.dispatch(args[0].__class__)
            else:
                method = self.func
                for v in kwargs.values():
                    if v.__class__ in self.dispatcher.registry:
                        method = self.dispatcher.dispatch(v.__class__)
                        if method is not self.func:
                            break

            return method.__get__(obj, cls)(*args, **kwargs)

        _method.__isabstractmethod__ = self.__isabstractmethod__
        _method.register = self.register
        update_wrapper(_method, self.func)
        return _method

    @property
    def __isabstractmethod__(self):
        return getattr(self.func, '__isabstractmethod__', False)

class Tags(ElevatedCardWidget):
    """标签卡片"""
    deleteSignal = Signal(str)

    @Singledispatchmethod
    def __init__(self, parent=None):
        super().__init__(parent)
        self.view = QHBoxLayout(self)
        self.tagText = BodyLabel(self)
        self.btn = TransparentToolButton(self)

        self.view.setContentsMargins(8, 2, 2, 2)
        self.view.setSpacing(6)
        self.view.addWidget(self.tagText)
        self.view.addWidget(self.btn)
        self.setFixedHeight(32)
        self.btn.setIcon(Icon.CLOSE_TAG)
        self.view.setObjectName('view')
        self.tagText.setObjectName('tagText')
        self.btn.setObjectName('btn')
        self.btn.clicked.connect(self._delete)

    @__init__.register
    def _(self, tag: str, parent=None):
        self.__init__(parent)
        self.setTag(tag)

    def getTag(self):
        return self.tagText.text()

    def setTag(self, title: str, light: str = "#000000", dark: str = "#ffffff"):
        self.tagText.setText(title)
        self.tagText.setTextColor(light, dark)

    def setEnabled(self, state: bool):
        self.btn.setEnabled(state)

    def _delete(self):
        self.deleteSignal.emit(self.getTag())

    def deleteLater(self):
        while self.view.count() > 0:
            item = self.view.takeAt(0)
            if isinstance(item, BodyLabel):
                item.deleteLater()
            elif widget := item.widget():
                self.view.removeWidget(widget)
                widget.deleteLater()
        super().deleteLater()

    tag = pyqtProperty(str, getTag, setTag)

Expected behavior

Screenshots

zhiyiYo commented 1 year ago

FlowLayout 的动画会影响到 ElevatedCardWidget 内部保存的初始位置,建议把动画关了

keymou commented 1 year ago

FlowLayout 的动画会影响到 ElevatedCardWidget 内部保存的初始位置,建议把动画关了

ok