【问题标题】:Recursion Error on PyQt QStackedWidget when using enterEvent and leaveEvent使用 enterEvent 和 leaveEvent 时 PyQt QStackedWidget 上的递归错误
【发布时间】:2020-06-12 23:52:57
【问题描述】:

我使用的是QStackedWidget,它有自己的enterEventleaveEvent。当我将鼠标移动到QStackedWidget 时,enterEvent 将当前索引设置为1,在leaveEvent 上将当前索引设置为0,以便在鼠标进入和鼠标离开时显示不同的小部件在QStackedWidget 的区域内。只有当我快速将鼠标移入和移出时,它才会执行我想要的操作,如果我将鼠标放在我得到RecursionError: maximum recursion depth exceeded 的区域中太长。

这是因为小部件变化太快以至于内部堆栈跟不上吗?我的问题是“我如何确保不会发生此错误?我想显示一个小部件只要鼠标在QStackedWidget 上,当它不是时我想显示原始小部件。”

以下是我修改的代码(Original Source使用按钮设置索引,是PyQt4

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import QTimeLine
from PyQt5.QtGui import *

class FaderWidget(QWidget):

    def __init__(self, old_widget, new_widget):
        QWidget.__init__(self, new_widget)
        self.old_pixmap = QPixmap(new_widget.size())
        old_widget.render(self.old_pixmap)
        self.pixmap_opacity = 1.0
        self.timeline = QTimeLine()
        self.timeline.valueChanged.connect(self.animate)
        self.timeline.finished.connect(self.close)
        self.timeline.setDuration(333)
        self.timeline.start()

        self.resize(new_widget.size())
        self.show()


    def animate(self, value):

        self.pixmap_opacity = 1.0 - value
        self.repaint()

class StackedWidget(QStackedWidget):

    def __init__(self, parent = None):
        QStackedWidget.__init__(self, parent)

    def setCurrentIndex(self, index):
        self.fader_widget = FaderWidget(self.currentWidget(), self.widget(index))
        super().setCurrentIndex(index)

    def enterEvent(self,event):
        self.setCurrentIndex(1)

    def leaveEvent(self,event):
        self.setCurrentIndex(0)


if __name__ == "__main__":

    app = QApplication(sys.argv)

    window = QWidget()

    stack = StackedWidget()
    cal=QCalendarWidget()
    stack.addWidget(cal)
    editor = QTextEdit()
    editor.setPlainText("Hello world! "*100)
    stack.addWidget(editor)

    layout = QGridLayout(window)
    layout.addWidget(stack, 0, 0, 1, 2)

    window.show()
    sys.exit(app.exec_())

【问题讨论】:

    标签: python pyqt5


    【解决方案1】:

    发生递归是因为当您启动 FaderWidget 时,它会更改焦点并再次调用 enterEvent,从而创建一个新的 FaderWidget。

    解决方法是验证旧索引与新索引不同,才创建FadeWidget:

    import sys
    
    from PyQt5.QtCore import QTimeLine
    from PyQt5.QtGui import QPainter, QPixmap
    from PyQt5.QtWidgets import (
        QApplication,
        QCalendarWidget,
        QGridLayout,
        QStackedWidget,
        QTextEdit,
        QWidget,
    )
    
    
    class FaderWidget(QWidget):
        def __init__(self, old_widget, new_widget):
            QWidget.__init__(self, new_widget)
            self.pixmap_opacity = 1.0
            self.old_pixmap = QPixmap(new_widget.size())
            old_widget.render(self.old_pixmap)
    
            self.timeline = QTimeLine()
            self.timeline.valueChanged.connect(self.animate)
            self.timeline.finished.connect(self.close)
            self.timeline.setDuration(333)
            self.timeline.start()
    
            self.resize(new_widget.size())
            self.show()
    
        def paintEvent(self, event):
            painter = QPainter(self)
            painter.setOpacity(self.pixmap_opacity)
            painter.drawPixmap(0, 0, self.old_pixmap)
    
        def animate(self, value):
            self.pixmap_opacity = 1.0 - value
            self.update()
    
    
    class StackedWidget(QStackedWidget):
        def setCurrentIndex(self, index):
            if self.currentIndex() != index:
                self.fader_widget = FaderWidget(self.currentWidget(), self.widget(index))
            super().setCurrentIndex(index)
    
        def enterEvent(self, event):
            self.setCurrentIndex(1)
    
        def leaveEvent(self, event):
            self.setCurrentIndex(0)
    
    
    if __name__ == "__main__":
    
        app = QApplication(sys.argv)
    
        window = QWidget()
    
        stack = StackedWidget()
        cal = QCalendarWidget()
        stack.addWidget(cal)
        editor = QTextEdit()
        editor.setPlainText("Hello world! " * 100)
        stack.addWidget(editor)
    
        layout = QGridLayout(window)
        layout.addWidget(stack, 0, 0, 1, 2)
    
        window.show()
        sys.exit(app.exec_())
    

    【讨论】:

    • 感谢您的解释和修复,我真的不敢相信它,您的其他 PyQt 答案对我有很大帮助:)
    猜你喜欢
    • 2021-01-08
    • 1970-01-01
    • 2012-08-11
    • 2012-08-31
    • 1970-01-01
    • 1970-01-01
    • 2018-10-13
    • 2016-07-30
    • 2011-01-07
    相关资源
    最近更新 更多