QTableView Edit Mod的问题

2024-09-27 09:37:46 发布

您现在位置:Python中文网/ 问答频道 /正文

我已经将QStandardItemModel子类化:

class PPSTableEditModel(QStandardItemModel):

    def __init__(self, parent=None):
        super(PPSTableEditModel, self).__init__(parent)
        self.proxy = QSortFilterProxyModel()
        self.proxy.setSourceModel(self)
        self.proxy.setFilterKeyColumn(5)
        self.proxy.setDynamicSortFilter(True)
        self.proxy.setFilterFixedString("0")
        self.editmode = None
        self.history = []

    def edit_record(self, qndx):

        #qndx is passed from a QTableView class and contains view.currentIndex()

        self.editmode = 2
        del self.history[:]
        for ndx in range(0, self.columnCount()):
            self.history.append(self.item(qndx.row(),ndx).data(Qt.DisplayRole))
        self.process_record(qndx) #<---- This works

        #ix = self.index(qndx.row(),2)
        #self.process_record(ix) #<---- This causes the error

    def process_record(self, pndx):
        self.parent().tbl_View.selectionModel().setCurrentIndex(pndx, QItemSelectionModel.Select)
        self.parent().tbl_View.edit(pndx)

我遇到的问题是在edit_record方法中,我将qndx传递给process_record,视图将正确进入编辑模式;但是,如果我试图设置起始(通过重新分配qndx)列,我会得到一个错误:

^{pr2}$

*编辑* 试图映射到代理索引进行编辑,但仍收到相同的错误:

def edit_record(self, qndx):
        self.editmode = 2
        del self.history[:]
        for ndx in range(0, self.columnCount()):
            self.history.append(self.item(qndx.row(),ndx).data(Qt.DisplayRole))
        ix = qndx if not self.proxy else self.proxy.mapToSource(qndx)
        self.process_record(ix)

*编辑* MCVE公司:

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

class PPSTableEditModel(QStandardItemModel):
    model_loaded = pyqtSignal()

    def __init__(self, parent=None):
        super(PPSTableEditModel, self).__init__(parent)
        self.proxy = None

    def edit_record(self, qndx):
        ix = qndx if not self.proxy else self.proxy.mapToSource(qndx)
        self.process_record(ix)

    def process_record(self, pndx):
        self.parent().tbl_View.selectionModel().setCurrentIndex(pndx, QItemSelectionModel.Select)
        self.parent().tbl_View.edit(pndx)


class SclDataModel(PPSTableEditModel):

    def __init__(self, parent=None):
        super(SclDataModel, self).__init__(parent)
        self.proxy = QSortFilterProxyModel(self)
        self.proxy.setSourceModel(self)
        self.proxy.setFilterKeyColumn(5)
        self.proxy.setDynamicSortFilter(True)
        self.proxy.setFilterFixedString("0")

    def load_data(self, parentid):        
        query = QSqlQuery()
        query.prepare('SELECT * FROM scldata WHERE svcdataid=?')
        query.addBindValue(parentid)
        query.exec_()
        while query.next():
            record = []
            for ndx in range(0, query.record().count()):
                item = QStandardItem()
                item.setData(query.value(ndx), Qt.DisplayRole)
                record.append(item)
            record.append(QStandardItem("0"))
            self.insertRow(self.rowCount(), record)
        self.model_loaded.emit()


class SclDataBrowse(QWidget):
    def __init__(self, parent=None):
        super(SclDataBrowse, self).__init__(parent)
        self.resize(600, 297)
        self.tbl_View = QTableView(self)
        self.line = QFrame(self)
        self.line.setFrameShape(QFrame.HLine)
        self.line.setFrameShadow(QFrame.Sunken)
        self.spacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        self.view_layout = QVBoxLayout(self)
        self.view_layout.setContentsMargins(0, 0, 0, 0)
        self.view_layout.addWidget(self.tbl_View)
        self.view_layout.addWidget(self.line)
        self.model = SclDataModel(self)
        self.parentid = None
        self.setup_view()
        self.setup_connections()

    def setup_view(self):
        self.tbl_View.setModel(self.model.proxy)
        self.tbl_View.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.tbl_View.setSelectionMode(QAbstractItemView.SingleSelection)
        self.tbl_View.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.tbl_View.verticalHeader().setVisible(False)
        self.tbl_View.verticalHeader().setDefaultSectionSize(22)

    def setup_connections(self):
        self.tbl_View.doubleClicked.connect(self.edit_record)
        self.model.model_loaded.connect(self.format_view)

    def set_parent(self, parentid):
        self.parentid = parentid
        self.model.load_data(self.parentid)

    def format_view(self):
        if self.model.rowCount():
            header = ["recorid", "svcdataid", "Start Amount", "End Amount", "Rate", "deleteflag"]
            for n in range(0, len(header)):
                self.model.setHeaderData(n, Qt.Horizontal, header[n])
            self.tbl_View.horizontalHeader().setSectionResizeMode(2, QHeaderView.Stretch)
            self.tbl_View.horizontalHeader().setSectionResizeMode(3, QHeaderView.Stretch)
            self.tbl_View.setColumnWidth(4, 85)
            self.tbl_View.setColumnHidden(0, True)
            self.tbl_View.setColumnHidden(1, True)
            self.tbl_View.setColumnHidden(5, True)

    def set_parent_record(self, parentid):
        self.parentid = parentid
        self.model.load_data(self.parentid)

    def edit_record(self):
        qndx = self.tbl_View.currentIndex()
        self.model.edit_record(qndx)


app = QApplication(sys.argv)
mainWin = SclDataBrowse()
db = QSqlDatabase.addDatabase("QMYSQL")
db.setHostName("myhost")
db.setUserName("myusr")
db.setPassword("mypassword")
db.setDatabaseName("mydbname")
db.open()
mainWin.show()
mainWin.set_parent("a5865717-e125-11e8-80c0-d4ae52cc00a8")
sys.exit(app.exec_())

*编辑* 似乎和QSortFilterProxyModel有关,但我无法确定。将索引传递给process_record而不通过代理映射它允许我编辑,但底层数据不正确。在

*** EDIT ***
import sys

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtSql import *
from PyQt5.QtWidgets import *


class PPSTableEditModel(QStandardItemModel):
    model_loaded = pyqtSignal()

    def __init__(self, parent=None):
        super(PPSTableEditModel, self).__init__(parent)
        self.proxy = None

    def edit_record(self, qndx):
        ix = qndx.sibling(qndx.row(), 2)
        self.process_record(ix)
        #ix = qndx if not self.proxy else self.proxy.mapToSource(qndx)
        #self.process_record(ix)

    def delete_record(self, qndx):
        ix = qndx if not self.proxy else self.proxy.mapToSource(qndx)
        self.item(ix.row(),5).setData("1",Qt.DisplayRole)

    def process_record(self, pndx):
        for ndx in range(0,self.columnCount()):
            print('{0},{1}----->{2}'.format(pndx.row(),ndx,self.item(pndx.row(),ndx).data(Qt.DisplayRole)))
        self.parent().tbl_View.selectionModel().setCurrentIndex(pndx, QItemSelectionModel.Select)
        self.parent().tbl_View.edit(pndx)


class SclDataModel(PPSTableEditModel):

    def __init__(self, parent=None):
        super(SclDataModel, self).__init__(parent)
        self.proxy = QSortFilterProxyModel(self)
        self.proxy.setSourceModel(self)
        self.proxy.setFilterKeyColumn(5)
        self.proxy.setDynamicSortFilter(True)
        self.proxy.setFilterFixedString("0")

    def load_data(self, parentid):
        data = (
            {"recordid": "1", "svcdataid": 1, "samount": .01, "eamount": 5000, "rate": .065, "delflag": "0"},
            {"recordid": "2", "svcdataid": 1, "samount": 5000.01, "eamount": 10000, "rate": .065, "delflag": "0"},
            {"recordid": "3", "svcdataid": 1, "samount": 10000.01, "eamount": 15000, "rate": .060, "delflag": "0"},
            {"recordid": "4", "svcdataid": 1, "samount": 15000.01, "eamount": 20000, "rate": .055, "delflag": "0"},
            {"recordid": "5", "svcdataid": 1, "samount": 20000.01, "eamount": 99999, "rate": .05, "delflag": "0"}
        )
        for ndx,rec in enumerate(data):
            record = []
            for key in rec:
                item = QStandardItem()
                item.setData(rec[key], Qt.DisplayRole)
                record.append(item)
            self.insertRow(self.rowCount(), record)
        self.model_loaded.emit()


class SclDataBrowse(QWidget):
    def __init__(self, parent=None):
        super(SclDataBrowse, self).__init__(parent)
        self.resize(600, 297)
        self.tbl_View = QTableView(self)
        self.line = QFrame(self)
        self.line.setFrameShape(QFrame.HLine)
        self.line.setFrameShadow(QFrame.Sunken)
        self.spacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        self.view_layout = QVBoxLayout(self)
        self.view_layout.setContentsMargins(0, 0, 0, 0)
        self.view_layout.addWidget(self.tbl_View)
        self.view_layout.addWidget(self.line)
        self.btn_layout = QHBoxLayout()
        self.btn_layout.setContentsMargins(6, 6, 6, 6)
        self.btn_delete = QPushButton()
        self.btn_delete.setText("Delete")
        self.btn_layout.addWidget(self.btn_delete)
        self.view_layout.addLayout(self.btn_layout)
        self.model = SclDataModel(self)
        self.parentid = None
        self.setup_view()
        self.setup_connections()

    def setup_view(self):
        self.tbl_View.setModel(self.model.proxy)
        self.tbl_View.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.tbl_View.setSelectionMode(QAbstractItemView.SingleSelection)
        self.tbl_View.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.tbl_View.verticalHeader().setVisible(False)
        self.tbl_View.verticalHeader().setDefaultSectionSize(22)

    def setup_connections(self):
        self.tbl_View.doubleClicked.connect(self.edit_record)
        self.btn_delete.clicked.connect(self.delete_record)
        self.model.model_loaded.connect(self.format_view)

    def set_parent(self, parentid):
        self.parentid = parentid
        self.model.load_data(self.parentid)

    def format_view(self):
        if self.model.rowCount():
            header = ["recorid", "svcdataid", "Start Amount", "End Amount", "Rate", "deleteflag"]
            for n in range(0, len(header)):
                self.model.setHeaderData(n, Qt.Horizontal, header[n])
            self.tbl_View.horizontalHeader().setSectionResizeMode(2, QHeaderView.Stretch)
            self.tbl_View.horizontalHeader().setSectionResizeMode(3, QHeaderView.Stretch)
            self.tbl_View.setColumnWidth(4, 85)
            self.tbl_View.setColumnHidden(0, True)
            self.tbl_View.setColumnHidden(1, True)
            self.tbl_View.setColumnHidden(5, True)

    def set_parent_record(self, parentid):
        self.parentid = parentid
        self.model.load_data(self.parentid)

    def edit_record(self):
        qndx = self.tbl_View.currentIndex()
        self.model.edit_record(qndx)

    def delete_record(self):
        qndx = self.tbl_View.currentIndex()
        self.model.delete_record(qndx)



app = QApplication(sys.argv)
mainWin = SclDataBrowse()
mainWin.show()
mainWin.set_parent("a5865717-e125-11e8-80c0-d4ae52cc00a8")
sys.exit(app.exec_())

使用此代码,表中有5个条目。如果删除第二条记录,过滤器会正确地隐藏“已删除”记录。现在双击第3行或第4行,process_record中输出的数据报告了正确的行,但是与该行相关联的数据是不正确的。在


Tags: selfnoneviewmodelinitdefrecordedit
1条回答
网友
1楼 · 发布于 2024-09-27 09:37:46

根据您的代码,您希望访问位于同一行但在第二列中的索引,即,它是QModelIndex的同级,因此必须使用sibling函数:

def edit_record(self, qndx):
    ix = qndx.sibling(qndx.row(), 2)
    self.process_record(ix)

问题是因为您使用该项来获取数据,QTableView不知道k,它只知道已经建立的模型,即QSortFilterProxyModel,所以需要edit()和{}的QModelIndex必须是QSortFilterProxyModel,所以我的初始解决方案是有效的,但在您的印象中,您使用的是PPSTableEditModel模型,因此解决方案是使用代理,但不必存储它,因为QModelIndex将模型引用保存到属于:

^{pr2}$

相关问题 更多 >

    热门问题