Skip to main content

Standard item already deleted from model when opening Qtreeview for the second time

I am using PySide6 to build a UI with a QTreeView that allows users to select a single item from a hierarchy. I have implemented the QStandardItemModel with user-checkable items, and I am updating the check state of the items in response to user input.

However, after the first time an item is checked, the program crashes with the error "RuntimeError: Internal C++ object (PySide6.QtGui.QStandardItem) already deleted."

I have reduced the code to a minimal example, which follows:

from PySide6.QtWidgets import QDialog, QPushButton, QWidget, QLineEdit
from PySide6.QtWidgets import QVBoxLayout, QHBoxLayout, QSizePolicy, QTreeView
from PySide6.QtGui import QIcon, QStandardItemModel, QStandardItem
from PySide6.QtCore import Qt


class MinimalModel(QStandardItemModel):
    def __init__(self, parent=None):
        super(MinimalModel, self).__init__(parent)

        self.root_item = self.invisibleRootItem()
        for i in range(2):
            item = QStandardItem("parent " + str(i))
            item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
            item.setCheckState(Qt.Unchecked)
            self.root_item.appendRow(item)

            parentItem = item
            for j in range(4):
                item = QStandardItem("item "+ str(j))
                item.setFlags(item.flags() | Qt.ItemIsUserCheckable | Qt.ItemNeverHasChildren)
                item.setCheckState(Qt.Unchecked)
                parentItem.appendRow(item)

class TreeWidgetSingleSelector(QTreeView):
    executing = False
    def __init__(self, model):
        super().__init__()
        self.setModel(model)
        self.setHeaderHidden(True)
        self.model().dataChanged.connect(self.on_check_state_changed)

    def on_check_state_changed(self, index, column):

        if self.executing:
            return
        self.executing = True

        # rest of the method code
        item = self.model().itemFromIndex(index)

        root = self.model().root_item  # invisibleRootItem()
        for i in range(root.rowCount()):
            root.child(i).setCheckState(Qt.Unchecked)

            if root.child(i).hasChildren():
                for j in range(root.child(i).rowCount()):
                    root.child(i).child(j).setCheckState(Qt.Unchecked)
        item.setCheckState(Qt.Checked)
        self.executing = False

class TreeWidgetSingleSelectorWindow(QDialog):
    def __init__(self, model, line_widget):
        super().__init__()
        self.model = model
        self.tree = TreeWidgetSingleSelector(self.model)
        self.line_widget = line_widget
        self.setWindowTitle("Select Single Item")

        layout = QVBoxLayout()
        layout.addWidget(self.tree)
        save_button = QPushButton("Select Item")
        save_button.clicked.connect(self.save_item)

        h_lout = QHBoxLayout()
        h_lout.addStretch(1)
        h_lout.addWidget(save_button)

        layout.addLayout(h_lout)
        self.setLayout(layout)

        self.finished.connect(self.deleteLater)

    def save_item(self):
        if self.tree.model().rowCount() > 0:
            items = [self.tree.model().root_item.child(i) for i in range(self.tree.model().root_item.rowCount())]
            for item in items:
                for i in range(item.rowCount()):
                    if item.child(i).checkState() == Qt.Checked:
                        self.line_widget.clear()
                        self.line_widget.setText(item.text() + "." + item.child(i).text())
                        self.accept()

    def closeEvent(self, event):
        # Clean up the tree views when the main window is closed
        self.tree.deleteLater()
        event.accept()


class LineEditTreeSelector(QWidget):
    def __init__(self, model):
        super().__init__()
        self.model = model
        self.line_edit = QLineEdit()
        button = QPushButton()
        button.setFixedWidth(20)
        button.setFixedHeight(20)
        button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        button.setIcon(QIcon("art/add_24.png"))

        layout = QHBoxLayout(self)
        layout.addWidget(button)
        layout.addWidget(self.line_edit)
        layout.setSpacing(0)

        button.clicked.connect(self.on_button_clicked)

    def on_button_clicked(self):
        tree_selector = TreeWidgetSingleSelectorWindow(self.model, self.line_edit)
        tree_selector.exec()

    def get_text(self):
        return self.line_edit.text()


class scatterplot_widget(QWidget):
    def __init__(self, model):
        QWidget.__init__(self)
        vertical_box = QVBoxLayout(self)

        self.tree_selector_x = LineEditTreeSelector(model)
        self.tree_selector_y = LineEditTreeSelector(model)

        vertical_box.addWidget(self.tree_selector_x)
        vertical_box.addWidget(self.tree_selector_y)


if __name__ == '__main__':
    from PySide6.QtWidgets import QApplication
    import sys

    # creating application
    app = QApplication(sys.argv)

    model = MinimalModel()

    main = scatterplot_widget(model)

    # showing the window
    main.show()

    # loop
    sys.exit(app.exec_())

Any ideas? Thanks in advance.



source https://stackoverflow.com/questions/76076681/standard-item-already-deleted-from-model-when-opening-qtreeview-for-the-second-t

Comments

Popular posts from this blog

How to show number of registered users in Laravel based on usertype?

i'm trying to display data from the database in the admin dashboard i used this: <?php use Illuminate\Support\Facades\DB; $users = DB::table('users')->count(); echo $users; ?> and i have successfully get the correct data from the database but what if i want to display a specific data for example in this user table there is "usertype" that specify if the user is normal user or admin i want to user the same code above but to display a specific usertype i tried this: <?php use Illuminate\Support\Facades\DB; $users = DB::table('users')->count()->WHERE usertype =admin; echo $users; ?> but it didn't work, what am i doing wrong? source https://stackoverflow.com/questions/68199726/how-to-show-number-of-registered-users-in-laravel-based-on-usertype

Confusion between commands.Bot and discord.Client | Which one should I use?

Whenever you look at YouTube tutorials or code from this website there is a real variation. Some developers use client = discord.Client(intents=intents) while the others use bot = commands.Bot(command_prefix="something", intents=intents) . Now I know slightly about the difference but I get errors from different places from my code when I use either of them and its confusing. Especially since there has a few changes over the years in discord.py it is hard to find the real difference. I tried sticking to discord.Client then I found that there are more features in commands.Bot . Then I found errors when using commands.Bot . An example of this is: When I try to use commands.Bot client = commands.Bot(command_prefix=">",intents=intents) async def load(): for filename in os.listdir("./Cogs"): if filename.endswith(".py"): client.load_extension(f"Cogs.{filename[:-3]}") The above doesnt giveany response from my Cogs ...

Why is my reports service not connecting?

I am trying to pull some data from a Postgres database using Node.js and node-postures but I can't figure out why my service isn't connecting. my routes/index.js file: const express = require('express'); const router = express.Router(); const ordersCountController = require('../controllers/ordersCountController'); const ordersController = require('../controllers/ordersController'); const weeklyReportsController = require('../controllers/weeklyReportsController'); router.get('/orders_count', ordersCountController); router.get('/orders', ordersController); router.get('/weekly_reports', weeklyReportsController); module.exports = router; My controllers/weeklyReportsController.js file: const weeklyReportsService = require('../services/weeklyReportsService'); const weeklyReportsController = async (req, res) => { try { const data = await weeklyReportsService; res.json({data}) console...