Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/329.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 无法使用pyqt5从表视图中已选择的项中选择单个项_Python_Pyqt_Pyqt5_Tableview - Fatal编程技术网

Python 无法使用pyqt5从表视图中已选择的项中选择单个项

Python 无法使用pyqt5从表视图中已选择的项中选择单个项,python,pyqt,pyqt5,tableview,Python,Pyqt,Pyqt5,Tableview,我正在使用pyqt进行模型/视图编程,试图理解它。 我的问题是,当我尝试从已选择的项目组中选择si select in item时,onSelection changed事件不会触发,并且选择行为变得怪异。(不仅无法从以前选择的项目中选择项目,而且还会进行连续选择…) 如果我对def数据(self,_index,role=Qt.DisplayRole):方法进行注释,我会得到我想要的行为,因此我想我在表中填充数据的方式中遗漏了一些东西。但是如果表中有注释(Hello:),则无法填充该表中的数据

我正在使用pyqt进行模型/视图编程,试图理解它。 我的问题是,当我尝试从已选择的项目组中选择si select in item时,onSelection changed事件不会触发,并且选择行为变得怪异。(不仅无法从以前选择的项目中选择项目,而且还会进行连续选择…)

如果我对def数据(self,_index,role=Qt.DisplayRole):方法进行注释,我会得到我想要的行为,因此我想我在表中填充数据的方式中遗漏了一些东西。但是如果表中有注释(Hello:),则无法填充该表中的数据

我试图用onMouseClick事件和选择行为来处理它,但没有成功。 我想要的选择行为也可以在本例中找到:

下面是我的代码,这可能有点混乱,因为我只是做了一些尝试(为此感到抱歉)。 任何评论都将不胜感激,非常感谢

from PyQt5.QtWidgets import QApplication, QTableView, QAbstractItemView
import sys
from PyQt5.QtCore import QAbstractTableModel, Qt, QModelIndex, QItemSelection, QItemSelectionModel, QAbstractItemModel

class myTableModel(QAbstractTableModel):
    def __init__(self, rows, columns, parent=None, *args):
        QAbstractTableModel.__init__(self, parent, *args)
        self.rowCount = rows
        self.columnCount = columns
        self.table_data = [[None] * columns for _ in range(rows)]
        self.unselectedItems = []

    def rowCount(self, parent):
        return self.rowCount

    def columnCount(self, parent):
        return self.columnCount

    def flags(self, index):
        return Qt.ItemIsEditable | Qt.ItemIsEnabled | Qt.ItemIsSelectable

    def data(self, _index, role=Qt.DisplayRole):
        if role == Qt.DisplayRole and _index.isValid():
            row = _index.row()
            column = _index.column()
            item = _index.internalPointer()
            if item is not None:
                print(item)
            value = self.table_data[row][column]
            # print('value returned: ' + str(value) + ' row: ' + str(row) + ' col: ' + str(column))
            return value
        else:
            return None

    def setData(self, _index, value, role=Qt.EditRole):
        if role == Qt.EditRole and _index.isValid():
            # print(_index.row())
            # self.arraydata[index.row()] = [value]
            # print('Return from rowCount: {0}'.format(self.rowCount(index)))
            row = _index.row()
            column = _index.column()
            self.table_data[row][column] = value
            self.dataChanged.emit(_index, _index)
            return True
        return QAbstractTableModel.setData(self, index, value, role)

    def updateSelection(self, selected, deselected):
        selectedItems = selected.indexes()
        for _index in selectedItems:
            _text = f"({_index.row()}, {_index.column()})"
            self.setData(_index, _text)
        del selectedItems[:]
        self.unselectedItems = deselected.indexes()
        for _index in self.unselectedItems:
            _text = "previous selection"
            self.setData(_index, _text)
            print('unselected item: ' + str(_index))


class myTableView(QTableView):
    def __init__(self, rowCount, columnCount, model):
        super().__init__()
        self.rowCount = rowCount
        self.columnCount = columnCount
        self.model = model
        self.setModel(model)
        self.selectionModel().selectionChanged.connect(tblModel.updateSelection)
        self.setSelectionMode(QAbstractItemView.ContiguousSelection)

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton:
            selectedItems = self.selectedIndexes()
            allIndexes = []
            for i in range(self.rowCount):
                for j in range(self.columnCount):
                    allIndexes.append(self.model.index(i, j))
            # print('all indexes appended')
            indexesToClear = [_index for _index in allIndexes if
                              _index not in selectedItems and _index not in self.model.unselectedItems]
            for _index in indexesToClear:
                valueFromIndex = str(self.model.data(_index, Qt.DisplayRole))
                if valueFromIndex == "previous selection":
                    self.model.setData(_index, "")

    # def mousePressEvent(self, event):
    #     if event.button() == Qt.LeftButton:
    #         self.selectionModel().reset()


app = QApplication(sys.argv)
tblModel = myTableModel(8, 4, app)  # create table model
tblView = myTableView(8, 4, tblModel)
topLeft = tblModel.index(0, 0, QModelIndex())
bottomRight = tblModel.index(5, 2, QModelIndex())

selectionMode = tblView.selectionModel()
selection = QItemSelection(topLeft, bottomRight)
selectionMode.select(selection, QItemSelectionModel.Select)

# set selected indexes text to selection
indexes = selectionMode.selectedIndexes()

for index in indexes:
    text = str(index.row()) + str(index.column())
    tblModel.setData(index, text, role=Qt.EditRole)

tblView.show()
app.exec()

该行为是不稳定的,还因为您没有调用
mouseReleaseEvent
的基类实现,它执行正确更新选择所需的一些操作,包括取消选择除当前/新项目之外的先前选择的项目(但行为可以根据视图的
selectionMode
而改变)。
此外,考虑选择模型的选择更改的信号仅发出更改:如果选择更改时已经选择了项,则将在<代码>选择的信号参数列表中列出<强>>不>强。< / P> 为了访问所选项目的完整列表,您需要调用视图的SelectedIndex()或其选择模型

我还删除了表init的rowCount和columnCount参数,因为它是冗余的(如果更改模型大小,则容易出错):它们的值仅取决于模型本身的大小,您应该仅通过它访问它们


最后,您永远不应该覆盖现有的类属性;除了我在上面注释掉的
self.model
之外,这也适用于您在模型中使用的
self.rowCount
self.columnCount
(这也没什么意义,因为公共方法会返回方法本身,导致递归).

谢谢您的回答。将updateSelection移动到myTableView类并使用模型作为参数似乎是非常正确的。但是这样做,我无法在updateSelection方法中访问模型。我得到:对于范围内的行(self.model.rowCount()):AttributeError:“builtin_function_或_method”对象没有属性“rowCount”@RustyBucketBay与PyQt对象的所有属性和几乎所有变量一样(特殊情况除外,例如QStyleOption变量),不是“python属性”,但必须作为函数访问;只需调用
self.model()
。我试图添加这个model=self.model(),在model()和rowCount()中使用括号的所有选项,同时删除和包含自我。我无法访问模型参数。很抱歉我的无能,你能在答案中提供完整的工作脚本吗?提前谢谢解决。我的错误。感谢答案和所有周围的解释。这非常有用。我借此机会问,我如何知道默认类属性不应该被覆盖的es???(我在文档中查找到,对于多重继承,我不清楚).我的意思是,关于你所说的关于tableView模型的内容,不应该被覆盖,因为这是一个类属性没有问题!关于命名问题,不幸的是,你只能从经验中得到它。从学习基类函数和属性开始(这总是有用的),最重要的是QObject和QWidget,请记住,您始终可以阅读出现在每个Qt类描述顶部的“所有成员列表,包括继承的成员”链接。幸运的是,Qt有一个非常描述性和一致的命名约定,因此,在大多数情况下,如果您最终命名的内容似乎是“很明显,它应该已经存在了”,可能是:-)
class myTableView(QTableView):
    def __init__(self, model):
        super().__init__()
        # no need for these
        # self.rowCount = rowCount
        # self.columnCount = columnCount

        # NEVER overwrite existing class property names!
        # self.model = model

        self.setModel(model)
        self.selectionModel().selectionChanged.connect(self.updateSelection)
        self.setSelectionMode(QAbstractItemView.ContiguousSelection)

    def updateSelection(self, selected, deselected):
        selectedIndexes = self.selectedIndexes()
        for row in range(model.rowCount()):
            for column in range(model.columnCount()):
                _index = model.index(row, column)
                if _index in selectedIndexes:
                    _text = f"({_index.row()}, {_index.column()})"
                elif _index in deselected:
                    _text = "previous selection"
                else:
                    _text = ""
                model.setData(_index, _text)