Исчезающие данные в расширенном QTreeWidgetItem

ОБНОВЛЕНИЕ: (решено)

Спасибо eyllanesc за то, что заставил меня написать рабочий пример кода моей проблемы. Это заставило меня найти проблему. Вот рабочий код с исправленной проблемой:

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

class ExtendedTreeWidgetItem(QTreeWidgetItem):

    def __init__(self, *args, **kwargs):
        super(ExtendedTreeWidgetItem, self).__init__(*args, **kwargs)
        self.rescueFile = None
        print("created first time")

    def setRescueFile(self, rFile):
        self.rescueFile = rFile
        print("setting rescue file", self.rescueFile, "for item", self.text(0))

    def getRescueFile(self):
        return self.rescueFile

class RescueFile:
    def __init__(self, path):
        self.path = path
        self.ischecked = True

    def isChecked(self):
        return self.ischecked

    def setChecked(self, checked):
        if isinstance(checked, bool):
            self.ischecked = checked
        elif isinstance(checked, Qt.CheckState):
            self.ischecked = True if checked == Qt.Checked else False

    def getPath(self):
        return self.path


class Window(QMainWindow):
    def __init__(self):
        super(Window, self).__init__()
        windowSize = (800,400)
        screenSize = QDesktopWidget().availableGeometry()
        self.setGeometry(screenSize.width()/2 - windowSize[0]/2, screenSize.height()/2 - windowSize[1]//2, windowSize[0], windowSize[1])
        self.setWindowTitle("TreeTest")



        self.buildGui()

        self.show()

    def buildGui(self):
        wgt = QWidget()
        vlayout = QVBoxLayout()
        vlayout.setAlignment(Qt.AlignTop)
        grid_layout = QGridLayout()

        self.setupTree(grid_layout)

        vlayout.addLayout(grid_layout)
        wgt.setLayout(vlayout)
        self.setCentralWidget(wgt)


    def setupTree(self, grid_layout):
        self.treeWidget = QTreeWidget()
        self.treeWidget.setHeaderLabel("Results")
        self.treeWidget.setColumnCount(1)

        #INSERTING DATA
        topItem = ExtendedTreeWidgetItem()
        topItem.setText(0, "top item")
        topItem.setCheckState(0, Qt.Checked)
        child1 = ExtendedTreeWidgetItem(topItem)
        child1.setText(0, "child 1")
        child1.setCheckState(0, Qt.Checked)
        topItem.addChild(child1)
        deeper_child = ExtendedTreeWidgetItem(child1)
        deeper_child.setText(0, "deeper child 1")
        deeper_child.setCheckState(0, Qt.Checked)
        r_file = RescueFile("/home/user1/Desktop")
        deeper_child.setRescueFile(r_file)
        child1.addChild(deeper_child)

        self.treeWidget.addTopLevelItem(topItem)
        self.treeWidget.expandAll()

        self.treeWidget.itemChanged.connect(self.singleClickTreeWidget)
        grid_layout.addWidget(self.treeWidget, 1, 1, 4, 3)

    def singleClickTreeWidget(self, widgetItem, column):
        parent = widgetItem.parent()
        if parent and parent.checkState(0) == Qt.Unchecked:
            widgetItem.setCheckState(0, Qt.Unchecked)
            return

        checkState = widgetItem.checkState(0)

        widgetItem.setCheckState(0, checkState)
        rescue_file = widgetItem.getRescueFile()
        if rescue_file:
            rescue_file.setChecked(checkState)
            print("rescue file found, path:", rescue_file.getPath(), "checked:", rescue_file.isChecked())

        self.iterateThroughChildren(widgetItem, checkState)

    def iterateThroughChildren(self, item, checkState):
        for i in range(item.childCount()):
            child = item.child(i)
            print("child:", child, ",text:", child.text(0))
            child.setCheckState(0, checkState)
            # HERE WAS THE MISTAKE
            # -- >> rescue_file = item.getRescueFile()  << --
            rescue_file = child.getRescueFile()  # CORRECT CODE!! 
            print("rescue file", rescue_file, "child", child.text(0))
            if rescue_file is not None:
                rescue_file.setChecked(checkState)
            else:
                self.iterateThroughChildren(child, checkState)



def main():
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        window = Window()
        app.exec_()

main()

ДО ОБНОВЛЕНИЯ:

Я надеюсь, что смогу объяснить свою проблему достаточно четко.

Я пытаюсь создать QTreeWidget, который использует мои расширенные QTreeWidgetItems в Python 3.5.3. Вот мой код для класса элемента:

class ExtendedTreeWidgetItem(QTreeWidgetItem):

    def __init__(self, *args, **kwargs):
        super(ExtendedTreeWidgetItem, self).__init__(*args, **kwargs)
        self.rescueFile = None

    def setRescueFile(self, rFile):
        self.rescueFile = rFile

    def getRescueFile(self):
        return self.rescueFile



class RescueFile:

    def __init__(self, path):
        self.path = path
        self.ischecked = True

    def isChecked(self):
        return self.ischecked

    def setChecked(self, checked):
        if isinstance(checked, bool):
            self.ischecked = checked
        elif isinstance(checked, Qt.CheckState):
            self.ischecked = True if checked == Qt.Checked else False
        print(self.path, self.ischecked)

Я использую этот код для реализации проверки и снятия флажка с файла восстановления:

****
...
self.treeWidget.itemChanged.connect(self.singleClickTreeWidget)
...
****


def singleClickTreeWidget(self, widgetItem, column):
        parent = widgetItem.parent()
        if parent and parent.checkState(0) == Qt.Unchecked:
            widgetItem.setCheckState(0, Qt.Unchecked)
            return

        checkState = widgetItem.checkState(0)

        widgetItem.setCheckState(0, checkState)
        rescue_file = widgetItem.getRescueFile()
        **# I CAN GET THE RESCUE FILE OBJECT HERE FROM**
        if rescue_file:
            rescue_file.setChecked(checkState)

        self.iterateThroughChildren(widgetItem, checkState)



def iterateThroughChildren(self, item, checkState):
    for i in range(item.childCount()):
        child = item.child(i)
        child.setCheckState(0, checkState)
        **# I CAN'T GET ANY FIND HERE ANYMORE**
        rescue_file = item.getRescueFile()
        if rescue_file:
            rescue_file.setChecked(checkState)
        else:
            self.iterateThroughChildren(child, checkState)

Мой код состоит в том, что он генерирует проверяемое дерево, как на картинке: QTreeWidget

Я пытаюсь добиться того, чтобы при отмене выбора / выборе элемента (ExtendedTreeWidgetItem), у которого есть дочерние элементы, все дочерние элементы также выбирались / отменялись, а также объекты RescueFile, связанные с элементами. Только файлы связаны с объектами RescueFile. Каталоги остались с self.rescueFile = None

Например, если я нажал, чтобы отменить выбор 'icons', должен быть также отменен выбор magnifier.png и связанный с ним RescueFile. Снятие флажков работает как талисман, но RescueFile не затрагивается (НЕ НАЙДЕНО), если я нажимаю на родительского файла. Но это работает, если я нажимаю непосредственно на файл, например, magnifier.png.

Я пытался отследить, если это проблема с указателем, но кажется, что все объекты указывают на объекты, которые они должны. Я не понимаю, где исчезает rescueFile, если я рекурсивно обращаюсь к ExtendedTreeWidgetItem через его родительский файл.

0 ответов

Другие вопросы по тегам