Проблема с режимом редактирования QTableView - PullRequest
0 голосов
/ 12 ноября 2018

Я вложил в подкласс 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), я получаю сообщение об ошибке:

edit: index was invalid
edit: editing failed

* EDIT * Попытка отобразить индекс прокси для редактирования, и яя все еще получаю ту же ошибку:

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, сообщают о правильной строке, но данные, связанные с этой строкой, неверны.

1 Ответ

0 голосов
/ 12 ноября 2018

Согласно вашему коду, вы хотите получить доступ к индексу, который находится в той же строке, но во втором столбце, то есть это брат или сестра QModelIndex, поэтому вы должны использовать функцию брата:

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

Проблема в том, что вы используете элемент для получения данных, QTableView не знает k, он знает только модель, которая была установлена, то есть QSortFilterProxyModel, поэтому QModelIndex, который требует edit() и selectionModel().SetCurrentIndex() должны быть QSortFilterProxyModel, поэтому мое первоначальное решение работает, но у вас сложилось впечатление, что вы используете модель PPSTableEditModel, поэтому решение состоит в том, чтобы использовать прокси, но хранить его не нужно, поскольку QModelIndex сохраняет ссылку на модель, к которой принадлежит:

def process_record(self, pndx):
    model = pndx.model()
    for ndx in range(model.columnCount()):
        print('{0},{1}----->{2}'.format(pndx.row(), ndx, model.index(pndx.row(),ndx).data(Qt.DisplayRole)))
    self.parent().tbl_View.selectionModel().setCurrentIndex(pndx, QItemSelectionModel.Select)
    self.parent().tbl_View.edit(pndx)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...