Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 调用endInsertRows()时QTableView模型崩溃_Python_Python 3.x_Pyqt_Pyqt5_Qabstracttablemodel - Fatal编程技术网

Python 调用endInsertRows()时QTableView模型崩溃

Python 调用endInsertRows()时QTableView模型崩溃,python,python-3.x,pyqt,pyqt5,qabstracttablemodel,Python,Python 3.x,Pyqt,Pyqt5,Qabstracttablemodel,我一直在尝试在插入表示行的新对象时更新QTableViewModel。我确实遵循了SO中几个问题的建议,但我无法找到一个有效的例子 调试后,我发现调用self.endInsertRows()会导致崩溃 这是一个简单的例子: import sys from PyQt5.QtWidgets import * from PyQt5 import QtCore, QtGui, QtWidgets class Wire: def __init__(self, name, x, y, gmr,

我一直在尝试在插入表示行的新对象时更新QTableViewModel。我确实遵循了SO中几个问题的建议,但我无法找到一个有效的例子

调试后,我发现调用
self.endInsertRows()
会导致崩溃

这是一个简单的例子:

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


class Wire:

    def __init__(self, name, x, y, gmr, r):
        self.name = name
        self.x = x
        self.y = y
        self.r = r
        self.gmr = gmr


class WiresCollection(QtCore.QAbstractTableModel):

    def __init__(self, parent=None):
        QtCore.QAbstractTableModel.__init__(self, parent)

        self.header = ['Name', 'R (Ohm/km)', 'GMR (m)']

        self.index_prop = {0: 'name', 1: 'r', 2: 'gmr'}

        self.wires = list()

    def add(self, wire: Wire):
        """
        Add wire
        :param wire:
        :return:
        """
        row = len(self.wires)
        self.beginInsertRows(QtCore.QModelIndex(), row, row)
        self.wires.append(wire)
        self.endInsertRows()

    def delete(self, index):
        """
        Delete wire
        :param index:
        :return:
        """
        row = len(self.wires)
        self.beginRemoveRows(QtCore.QModelIndex(), row, row)
        self.wires.pop(index)
        self.endRemoveRows()

    def rowCount(self, parent=QtCore.QModelIndex()):
        return len(self.wires)

    def columnCount(self, parent=QtCore.QModelIndex()):
        return len(self.header)

    def parent(self, index=None):
        return QtCore.QModelIndex()

    def data(self, index, role=QtCore.Qt.DisplayRole):
        if index.isValid():
            if role == QtCore.Qt.DisplayRole:
                val = getattr(self.wires[index.row()], self.index_prop(index.column()))
                return str(val)
        return None

    def headerData(self, p_int, orientation, role):
        if role == QtCore.Qt.DisplayRole:
            if orientation == QtCore.Qt.Horizontal:
                return self.header[p_int]

    def setData(self, index, value, role=QtCore.Qt.DisplayRole):
        """
        Set data by simple editor (whatever text)
        :param index:
        :param value:
        :param role:
        """
        wire = self.wires[index.row()]
        attr = self.index_prop[index.column()]
        setattr(wire, attr, value)


class TowerBuilderGUI(QtWidgets.QDialog):

    def __init__(self, parent=None):
        """
        Constructor
        Args:
            parent:
        """
        QtWidgets.QDialog.__init__(self, parent)
        self.setWindowTitle('Tower builder')

        # GUI objects
        self.setContextMenuPolicy(QtCore.Qt.NoContextMenu)
        self.layout = QVBoxLayout(self)
        self.wires_tableView = QTableView()
        self.add_wire_pushButton = QPushButton()
        self.add_wire_pushButton.setText('Add')
        self.delete_wire_pushButton = QPushButton()
        self.delete_wire_pushButton.setText('Delete')

        self.layout.addWidget(self.wires_tableView)
        self.layout.addWidget(self.add_wire_pushButton)
        self.layout.addWidget(self.delete_wire_pushButton)

        self.setLayout(self.layout)

        # Model
        self.wire_collection = WiresCollection(self)

        # set models
        self.wires_tableView.setModel(self.wire_collection)

        # button clicks
        self.add_wire_pushButton.clicked.connect(self.add_wire_to_collection)
        self.delete_wire_pushButton.clicked.connect(self.delete_wire_from_collection)

    def msg(self, text, title="Warning"):
        """
        Message box
        :param text: Text to display
        :param title: Name of the window
        """
        msg = QMessageBox()
        msg.setIcon(QMessageBox.Information)
        msg.setText(text)
        # msg.setInformativeText("This is additional information")
        msg.setWindowTitle(title)
        # msg.setDetailedText("The details are as follows:")
        msg.setStandardButtons(QMessageBox.Ok)
        retval = msg.exec_()

    def add_wire_to_collection(self):
        """
        Add new wire to collection
        :return:
        """
        name = 'Wire_' + str(len(self.wire_collection.wires) + 1)
        wire = Wire(name, x=0, y=0, gmr=0, r=0.01)
        self.wire_collection.add(wire)

    def delete_wire_from_collection(self):
        """
        Delete wire from the collection
        :return:
        """
        idx = self.ui.wires_tableView.currentIndex()
        sel_idx = idx.row()

        if sel_idx > -1:
            self.wire_collection.delete(sel_idx)
        else:
            self.msg('Select a wire in the wires collection')


if __name__ == "__main__":

    app = QtWidgets.QApplication(sys.argv)
    window = TowerBuilderGUI()
    window.show()
    sys.exit(app.exec_())

如注释所示,您有两个错误:

  • 第一个是当您按add时,因为当您添加一个新项目时,您必须刷新视图,这就是为什么它被称为
    data()
    方法,错误显示在
    self.index_prop(index.column())
    index_pro
    中,因此您应该使用
    []
    而不是

  • 另一个错误是由行
    idx=self.ui.wires\u tableView.currentIndex()
    生成的,该ui不存在,并且没有必要访问
    wires\u tableView
    ,因为它是类的成员,不必使用中介,您必须使用self直接访问:
    idx=self.wires\u tableView.currentIndex()

以上都是打字错误,可能会标记它,这样问题就结束了。还有一个错误不是,这就是我回答的原因

在self.beginRemoveRows(…)行中,必须传递要删除的行,但传递的是不存在的行:

row = len(self.wires)
self.beginRemoveRows(QtCore.QModelIndex(), row, row)  # <---- row does not exist in the table

您的代码生成错误:1。当按下第
行中的
添加
按钮
返回self.createIndex(行、列、self.m_数据[row])
时,我们得到错误
AttributeError:“WiresCollection”对象没有属性“m_数据”
;2.当按下第
idx=self.ui.wires\u tableView.currentIndex()
行中的
Delete
按钮时,我们得到错误
AttributeError:“TowerBuilderGUI”对象没有属性“ui”
请删除索引方法,因为它不是必需的。我将从示例中删除它。您的代码生成错误:1。当按下第return行中的Add按钮时,
val=getattr(self.wires[index.row()],self.index_prop(index.column())
,我们得到错误
TypeError:“dict”对象不可调用
;2.当按下idx=self.ui.wires\u tableView.currentIndex()行中的Delete按钮时,我们得到了错误AttributeError:“TowerBuilderGUI”对象没有属性“ui”。事实上,我从一个previos代码中输入了拼写错误,仅举一个简单的例子……您是否设法添加了一行??您是否在windows上?
row = len(self.wires)
self.beginRemoveRows(QtCore.QModelIndex(), row, row)  # <---- row does not exist in the table
def delete(self, index):
    """
    Delete wire
    :param index:
    :return:
    """
    self.beginRemoveRows(QtCore.QModelIndex(), index, index)
    self.wires.pop(index)
    self.endRemoveRows()