django
django

Reputation: 2909

python call parent method from child widget

I am trying to call parent method printName from child widget treeView but Get error like

  1. AttributeError: 'QSplitter' object has no attribute 'printName'
  2. QObject::startTimer: QTimer can only be used with threads started with QThread

why parent is referring to QSplitter ?

Parent of TreeView is supposed to be compositeWidget since TreeViewwas created in compositeWidget

CODE:

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys


class MainExample(QMainWindow):

    def __init__(self, parent=None):
        super(MainExample, self).__init__(parent)
        self.initUI()

    def initUI(self):
        self.mainWidget = compositeWidget(self)
        self.setCentralWidget(self.mainWidget)
        self.mainWidget.treeView.setPath('D:\DATA')
        self.setGeometry(300, 300, 300, 200)


class TreeView(QTreeView):

    def __init__(self, parent):
        super(TreeView, self).__init__(parent)
        self.clicked.connect(self.on_treeView_clicked)

    @pyqtSlot(QModelIndex)
    def on_treeView_clicked(self, index):
        indexItem = self.FileSystemModel.index(index.row(), 0, index.parent())
        filePath = self.FileSystemModel.filePath(indexItem)
        self.parent().printName(filePath)
        #

    def setPath(self, path):
        self.FileSystemModel = QFileSystemModel()
        self.FileSystemModel.setFilter(QDir.Dirs | QDir.NoDotAndDotDot)
        self.FileSystemModel.setRootPath(path)
        self.setModel(self.FileSystemModel)
        index = self.FileSystemModel.index(path)
        self.setRootIndex(index)


class compositeWidget(QWidget):

    def __init__(self, parent):
        super(compositeWidget, self).__init__(parent)
        self.treeView = TreeView(self)
        self.frame = QFrame()
        splitterHorizontal = QSplitter(Qt.Horizontal)
        splitterHorizontal.addWidget(self.treeView)
        splitterHorizontal.addWidget(self.frame)
        splitterHorizontal.setSizes([10, 190])
        self.layout = QHBoxLayout(self)
        self.layout.addWidget(splitterHorizontal)
        self.setLayout(self.layout)

    def printName(self):
        print 'fileName'


def main():

    app = QApplication(sys.argv)
    ex = MainExample()
    ex.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

Upvotes: 3

Views: 8393

Answers (2)

three_pineapples
three_pineapples

Reputation: 11869

Unfortunately this doesn't seem to be documented (which seems like a little bit of an oversight) but as with other addWidget() methods in Qt (like QLayout.addWidget()) the QSplitter.addWidget() method takes ownership of the child by becoming it's parent.

This is why the QSplitter is returned by Treeview.parent(). You should use another way to access the parent you want (for instance like explictly storing a reference to the parent you pass into the constructor)

class TreeView(QTreeView):

    def __init__(self, parent):
        super(TreeView, self).__init__(parent)
        self.clicked.connect(self.on_treeView_clicked)
        self.composite_widget = parent

    @pyqtSlot(QModelIndex)
    def on_treeView_clicked(self, index):
        indexItem = self.FileSystemModel.index(index.row(), 0, index.parent())
        filePath = self.FileSystemModel.filePath(indexItem)
        self.composite_widget.printName(filePath)
        #

    def setPath(self, path):
        self.FileSystemModel = QFileSystemModel()
        self.FileSystemModel.setFilter(QDir.Dirs | QDir.NoDotAndDotDot)
        self.FileSystemModel.setRootPath(path)
        self.setModel(self.FileSystemModel)
        index = self.FileSystemModel.index(path)
        self.setRootIndex(index)

Upvotes: 2

djangoliv
djangoliv

Reputation: 1788

The QTreeView is under QSplitter witch is under compositeWidget. You need to call

self.parent().parent().printName(filePath)

Upvotes: 7

Related Questions