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.68k stars 550 forks source link

主窗口关闭然后再次显示时进行切换主题操作程序崩溃 #513

Closed qianye216 closed 1 year ago

qianye216 commented 1 year ago

主窗口点击退出登录操作,调用以下代码:


            self.trayIcon.hide()
            self.close()
            self.deleteLater()
            signalBus.logout_Signal.emit()

然后回到登录页面,再次登录,再调用主窗口进行显示:

main_window = MainWindow()
 main_window.show()

然后到设置页面切换主题,程序崩溃(其他功能都正常,包括更改主题色):

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/qfluentwidgets/components/widgets/label.py", line 58, in <lambda>
    lambda: self.setTextColor(self.lightColor, self.darkColor))
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/qfluentwidgets/components/widgets/label.py", line 75, in setTextColor
    palette = self.palette()
RuntimeError: wrapped C/C++ object of type BodyLabel has been deleted
zhiyiYo commented 1 year ago

是不是有什么临时组件被析构了,比如 Flyout

qianye216 commented 1 year ago

是不是有什么临时组件被析构了,比如 Flyout

没有用到Flyout,如果我注释掉self.deleteLater()就不会崩溃,但是有其他问题,如果不注释的话切换主题就会崩溃

zhiyiYo commented 1 year ago

deleteLater() 会把子部件也给析构掉

qianye216 commented 1 year ago

deleteLater() 会把子部件也给析构掉

有解决办法吗,切换主题就Label会有问题,其他组件都正常

zhiyiYo commented 1 year ago

label很奇怪,切换主题的时候重新设置palette不起作用,我能想到的方法就是重新设置样式表

liuyichen commented 1 year ago

目前发现问题是如果使用deleteLater或者listwidget的clear等操作,销毁label再修改主题,会触发RuntimeError: wrapped C/C++ object of type BodyLabel has been deleted 错误,原因时label被销毁了,但对应的qconfig.themeChanged事件还会调用,我的解决办法重写了 label.py FluentLabelBase类的_init方法,增加了销毁时触发移除对应set_text_color 事件,Label以外是否有类似问题我没有验证。

    def _init(self):
        self.setFont(self.getFont())
        self.setTextColor()
        set_text_color = lambda: self.setTextColor(self.lightColor, self.darkColor)
        qconfig.themeChanged.connect(set_text_color)
        self.destroyed.connect(lambda: qconfig.themeChanged.disconnect(set_text_color))
        return self

@zhiyiYo @qianye216

zhiyiYo commented 1 year ago

按下面这样改可以吗 @qianye216

class FluentLabelBase(QLabel):
    """ Fluent label base class """

    @singledispatchmethod
    def __init__(self, parent: QWidget = None):
        super().__init__(parent)
        self._init()

    @__init__.register
    def _(self, text: str, parent: QWidget = None):
        self.__init__(parent)
        self.setText(text)

    def _init(self):
        self.setFont(self.getFont())
        self.setTextColor()
        connect = qconfig.themeChanged.connect(
            lambda: self.setTextColor(self.lightColor, self.darkColor))
        self.destroyed.connect(lambda: self.disconnect(connect))
        return self
qianye216 commented 1 year ago

按下面这样改可以吗 @qianye216

class FluentLabelBase(QLabel):
    """ Fluent label base class """

    @singledispatchmethod
    def __init__(self, parent: QWidget = None):
        super().__init__(parent)
        self._init()

    @__init__.register
    def _(self, text: str, parent: QWidget = None):
        self.__init__(parent)
        self.setText(text)

    def _init(self):
        self.setFont(self.getFont())
        self.setTextColor()
        connect = qconfig.themeChanged.connect(
            lambda: self.setTextColor(self.lightColor, self.darkColor))
        self.destroyed.connect(lambda: self.disconnect(connect))
        return self

我目前不方便验证, @liuyichen 有时间帮忙看看这个是否可以?

liuyichen commented 1 year ago

@liuyichen @qianye216 又做了下调整,因为程序退出时,偶尔会出现qconfig已经销毁的情况下,无法disconnect报错。 主题切换的问题是可以解决的。 import sip

class FluentLabelBase(QLabel): """ Fluent label base class """

@singledispatchmethod
def __init__(self, parent: QWidget = None):
    super().__init__(parent)
    self._init()

@__init__.register
def _(self, text: str, parent: QWidget = None):
    self.__init__(parent)
    self.setText(text)

def _init(self):
    self.setFont(self.getFont())
    self.setTextColor()
    set_text_color = lambda: self.setTextColor(self.lightColor, self.darkColor)
    qconfig.themeChanged.connect(set_text_color)
    self.destroyed.connect(lambda: qconfig.themeChanged.disconnect(set_text_color) if not sip.isdeleted(qconfig) else None)
    return self