PyQT 5将小部件动态添加到剧透

时间:2020-10-30 08:23:37

标签: python pyqt pyqt5

我正在编写一个小程序,理想情况下,我希望有一个固定大小的组,可以展开,在这些组中,我还有一些扰流板,这些扰流板代表可以打开和关闭的项目,以便向系统中添加一些实体。

我一直在这里寻找类似的问题,并且发现以下问题可以正常工作:

enter image description here

我添加了+按钮以将这些孩子从组中删除,并添加了spoilers.py import sys from PyQt5.QtWidgets import * from PyQt5.QtWidgets import QPushButton from PyQt5.QtGui import * from PyQt5.QtCore import * class Spoiler(QWidget): def __init__(self, parent=None, title='', animationDuration=300, addRemoveOption='None'): super(Spoiler, self).__init__(parent=parent) self.animationDuration = animationDuration self.toggleAnimation = QParallelAnimationGroup() self.contentArea = QScrollArea() self.headerLine = QFrame() self.toggleButton = QToolButton() self.mainLayout = QGridLayout() self.childWidgets = [] self.toggleButton.setStyleSheet("QToolButton { border: none; }") self.toggleButton.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.toggleButton.setArrowType(Qt.RightArrow) self.toggleButton.setText(str(title)) self.toggleButton.setCheckable(True) self.toggleButton.setChecked(False) self.addRemoveOperation = addRemoveOption if addRemoveOption is not 'None': if addRemoveOption is 'Add': self.addRemoveButton = QPushButton('+') else: self.addRemoveButton = QPushButton('-') self.addRemoveButton.clicked.connect(self.onAddRemoveButton) self.contentArea.setStyleSheet("QScrollArea { background-color: white; border: none; }") self.contentArea.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) # start out collapsed self.contentArea.setMaximumHeight(0) self.contentArea.setMinimumHeight(0) # let the entire widget grow and shrink with its content self.toggleAnimation.addAnimation(QPropertyAnimation(self, b"minimumHeight")) self.toggleAnimation.addAnimation(QPropertyAnimation(self, b"maximumHeight")) self.toggleAnimation.addAnimation(QPropertyAnimation(self.contentArea, b"maximumHeight")) # don't waste space self.mainLayout.setVerticalSpacing(0) self.mainLayout.setContentsMargins(0, 0, 0, 0) self.mainLayout.addWidget(self.toggleButton, 0, 0, 1, 1, Qt.AlignLeft) if addRemoveOption is not 'None': self.mainLayout.addWidget(self.addRemoveButton, 0, 2, 1, 1, Qt.AlignRight) self.mainLayout.addWidget(self.contentArea, 1, 0, 1, 3) self.setLayout(self.mainLayout) def start_animation(checked): arrow_type = Qt.DownArrow if checked else Qt.RightArrow direction = QAbstractAnimation.Forward if checked else QAbstractAnimation.Backward self.toggleButton.setArrowType(arrow_type) self.toggleAnimation.setDirection(direction) self.toggleAnimation.start() self.toggleButton.clicked.connect(start_animation) self.contentLayout = QVBoxLayout() self.setContentLayout(self.contentLayout) def setContentLayout(self, contentLayout): self.contentArea.destroy() self.contentArea.setLayout(contentLayout) collapsedHeight = self.sizeHint().height() - self.contentArea.maximumHeight() contentHeight = contentLayout.sizeHint().height() for i in range(self.toggleAnimation.animationCount()-1): spoilerAnimation = self.toggleAnimation.animationAt(i) spoilerAnimation.setDuration(self.animationDuration) spoilerAnimation.setStartValue(collapsedHeight) spoilerAnimation.setEndValue(collapsedHeight + contentHeight) contentAnimation = self.toggleAnimation.animationAt(self.toggleAnimation.animationCount() - 1) contentAnimation.setDuration(self.animationDuration) contentAnimation.setStartValue(0) contentAnimation.setEndValue(contentHeight) def addChild(self, child): self.childWidgets += [child] self.contentLayout.addWidget(child) self.setContentLayout(self.contentLayout) def removeChild(self, child): self.childWidgets.remove(child) #self.contentLayout.removeWidget(child) child.destroy() #self.setContentLayout(self.contentLayout) def onAddRemoveButton(self): self.addChild(LeafSpoiler(root=self)) class LeafSpoiler(Spoiler): def __init__(self, parent=None, root=None, title=''): if(root == None): addRemoveOption = 'None' else: addRemoveOption = 'Sub' super(LeafSpoiler, self).__init__(parent=parent, title=title, addRemoveOption=addRemoveOption) self.root = root def onAddRemoveButton(self): self.root.removeChild(self) 将孩子添加到组中。

只要我不删除或添加小部件,这似乎就可以正常工作。

我的代码如下:

gui.py

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

from spoilers import *


class MainWindow(QMainWindow):

    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):

        self.setGeometry(300, 300, 300, 220)
        # self.setWindowIcon(QIcon('web.png'))

        self.centralWidget = QFrame()
        self.centralLayout = QVBoxLayout()
        self.centralWidget.setLayout(self.centralLayout)

        self.spoiler1 = Spoiler(addRemoveOption='Add', title='Group 1')
        self.spoiler2 = Spoiler(addRemoveOption='Add', title='Group 2')
        for i in range(3):
            leaf = LeafSpoiler(root=self.spoiler1)
            self.spoiler1.addChild(leaf)

            leaf = LeafSpoiler(root=self.spoiler2)
            self.spoiler2.addChild(leaf)
        self.centralLayout.addWidget(self.spoiler1)
        self.centralLayout.addWidget(self.spoiler2)

        self.setCentralWidget(self.centralWidget)
        self.show()



if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = MainWindow()
    sys.exit(app.exec_())


Spoiler.setContentLayout()

我不是很确定为什么这行不通。我假设regresion.Rmd不应被多次调用。

如果有人可以帮助我,我会很高兴!

问候, 芬兰人

1 个答案:

答案 0 :(得分:1)

我不太确定我是否正确理解了您的问题。我以为您是在尝试删除Spoilerleaf时正在谈论pyqt崩溃?至少这是我的机器上正在发生的事情。

您的“ removeChild”方法似乎是这里的罪魁祸首。在不了解崩溃原因太多的情况下,将其替换为对deleteLater()的调用会在我的计算机上删除子项:

class LeafSpoiler(Spoiler):
    # [...] same init as your's

    def onAddRemoveButton(self):
        self.deleteLater()