通过子QPushButton pyqt删除父窗口小部件

时间:2015-03-11 20:24:24

标签: widget pyqt parent qpushbutton

我已经有一段时间在互联网上搜索,但仍然无法得到答案...基本上我有一个包含几个框架的QVBoxLayout - 每个框架都包含一个按钮,其功能是删除它的父框架。主代码是使用QT Designer和pyuic4创建的。我写了两个额外的函数,一个完美地工作(“createFrame”),但我正在努力与“deleteFrame”一个。框架内的标签显示vert_layout“数组”中该框架的索引。我在代码中注意到的问题是,以这种方式使用它,我只能删除添加的最后一帧。那么,有人可以帮我解决这个问题吗?

请参阅下面的代码:

# -*- coding: utf-8 -*-
from PyQt4 import QtCore, QtGui
import sys

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
    return QtGui.QApplication.translate(context, text, disambig)

#Custom button that sends out its own instance as the signal
class MyPushButton(QtGui.QPushButton):
    mySignal = QtCore.pyqtSignal(QtGui.QWidget)
    def mousePressEvent(self, *args, **kwargs):
        self.mySignal.emit(self)

class Functions:
    def createFrame(self,mainWindow):
        #just local frame no need to store it in the class
        frame = QtGui.QFrame()
        frame.setGeometry(QtCore.QRect(10, 10, 241, 61))
        frame.setFrameShape(QtGui.QFrame.StyledPanel)
        frame.setFrameShadow(QtGui.QFrame.Raised)
        frame.setObjectName(_fromUtf8("frame"))
        pushButton_2 = MyPushButton(frame)
        pushButton_2.setGeometry(QtCore.QRect(94, 10, 141, 41))
        pushButton_2.setObjectName(_fromUtf8("pushButton_2"))
        label = QtGui.QLabel(frame)
        label.setGeometry(QtCore.QRect(20, 10, 71, 41))
        label.setFrameShape(QtGui.QFrame.NoFrame)
        label.setAlignment(QtCore.Qt.AlignCenter)

        #the vert_layout belongs to class Ui_MainWindow
        mainWindow.vert_layout.addWidget(frame)

        label.setObjectName(_fromUtf8("label"))
        label.setText(str(mainWindow.vert_layout.indexOf(frame)))
        pushButton_2.setText(_translate("MainWindow", "delete this frame and all\n its childs", None))

        pushButton_2.mySignal.connect(self.deleteFrame)

        #my initial idea was to include the mainWindow (instance of 
        #Ui_MainWindow class in order to use vert_layout - but apparently
        #I need to modify the signal as well, right?
    def deleteFrame(self,ref,mainWindow):
        #finding the index of the FRAME (mybutton's parent)
        #that is to be deleted
        frame = mainWindow.vert_layout.itemAt(self.vert_layout.indexOf(ref.parent()))
        widget = frame.widget()
        if widget is not None:
            widget.deleteLater()
class Ui_MainWindow(object):

def setupUi(self, MainWindow):
    MainWindow.setObjectName(_fromUtf8("MainWindow"))
    MainWindow.resize(400, 284)

    self.vert_layout = QtGui.QVBoxLayout()

    self.centralwidget = QtGui.QWidget(MainWindow)
    self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
    self.scrollArea = QtGui.QScrollArea(self.centralwidget)
    self.scrollArea.setGeometry(QtCore.QRect(10, 10, 281, 261))
    self.scrollArea.setWidgetResizable(True)
    self.scrollArea.setObjectName(_fromUtf8("scrollArea"))
    self.scrollArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
    self.scrollAreaWidgetContents = QtGui.QWidget()
    self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 277, 257))
    self.scrollAreaWidgetContents.setObjectName(_fromUtf8("scrollAreaWidgetContents")) 

    self.scrollAreaWidgetContents.setLayout(self.vert_layout)

    self.scrollArea.setWidget(self.scrollAreaWidgetContents)
    self.pushButton = QtGui.QPushButton(self.centralwidget)
    self.pushButton.setGeometry(QtCore.QRect(310, 20, 75, 23))
    self.pushButton.setObjectName(_fromUtf8("pushButton"))
    MainWindow.setCentralWidget(self.centralwidget)

    self.retranslateUi(MainWindow)
    QtCore.QMetaObject.connectSlotsByName(MainWindow)

    f = Functions()

    self.pushButton.clicked.connect(lambda: f.createFrame())

def retranslateUi(self, MainWindow):
    MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
    self.pushButton.setText(_translate("MainWindow", "create", None))

class Main(QtGui.QMainWindow):
def __init__(self):
    QtGui.QMainWindow.__init__(self)
    self.ui = Ui_MainWindow()
    self.ui.setupUi(self)

if __name__== '__main__':
app = QtGui.QApplication(sys.argv)
window = Main()
window.show()
sys.exit(app.exec_())

1 个答案:

答案 0 :(得分:0)

您目前正在做的就是每次都删除self.frame小部件。 因此,只有最后创建的一个被删除。而不是你实际点击的那个。

根据需要修改代码。希望它能帮助你理解。

# -*- coding: utf-8 -*-
from PyQt4 import QtCore, QtGui
import sys

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

#Custom button that sends out its own instance as the signal
class MyPushButton(QtGui.QPushButton):
    mySignal = QtCore.pyqtSignal(QtGui.QWidget)
    def mousePressEvent(self, *args, **kwargs):
        self.mySignal.emit(self)

class Ui_MainWindow(object):

    def setupUi(self, MainWindow):
        MainWindow.setObjectName(_fromUtf8("MainWindow"))
        MainWindow.resize(400, 284)

        self.vert_layout = QtGui.QVBoxLayout()

        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.scrollArea = QtGui.QScrollArea(self.centralwidget)
        self.scrollArea.setGeometry(QtCore.QRect(10, 10, 281, 261))
        self.scrollArea.setWidgetResizable(True)
        self.scrollArea.setObjectName(_fromUtf8("scrollArea"))
        self.scrollArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
        self.scrollAreaWidgetContents = QtGui.QWidget()
        self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 277, 257))
        self.scrollAreaWidgetContents.setObjectName(_fromUtf8("scrollAreaWidgetContents")) 

        self.scrollAreaWidgetContents.setLayout(self.vert_layout)

        self.scrollArea.setWidget(self.scrollAreaWidgetContents)
        self.pushButton = QtGui.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(310, 20, 75, 23))
        self.pushButton.setObjectName(_fromUtf8("pushButton"))
        MainWindow.setCentralWidget(self.centralwidget)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

        self.pushButton.clicked.connect(lambda: self.createFrame())

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
        self.pushButton.setText(_translate("MainWindow", "create", None))

    def createFrame(self):
        #just local frame no need to store it in the class
        frame = QtGui.QFrame()
        frame.setGeometry(QtCore.QRect(10, 10, 241, 61))
        frame.setFrameShape(QtGui.QFrame.StyledPanel)
        frame.setFrameShadow(QtGui.QFrame.Raised)
        frame.setObjectName(_fromUtf8("frame"))
        pushButton_2 = MyPushButton(frame)
        pushButton_2.setGeometry(QtCore.QRect(94, 10, 141, 41))
        pushButton_2.setObjectName(_fromUtf8("pushButton_2"))
        label = QtGui.QLabel(frame)
        label.setGeometry(QtCore.QRect(20, 10, 71, 41))
        label.setFrameShape(QtGui.QFrame.NoFrame)
        label.setAlignment(QtCore.Qt.AlignCenter)

        self.vert_layout.addWidget(frame)

        label.setObjectName(_fromUtf8("label"))
        label.setText(str(self.vert_layout.indexOf(frame)))
        pushButton_2.setText(_translate("MainWindow", "delete this frame and all\n its childs", None))

        pushButton_2.mySignal.connect(self.deleteFrame)

    def deleteFrame(self,ref):
        #finding the index of the FRAME (mybutton's parent)
        #that is to be deleted
        frame = self.vert_layout.itemAt(self.vert_layout.indexOf(ref.parent()))
        widget = frame.widget()
        if widget is not None:
            widget.deleteLater()

class Main(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

if __name__== '__main__':
    app = QtGui.QApplication(sys.argv)
    window = Main()
    window.show()
    sys.exit(app.exec_())