如何在 QTableView 中添加/删除行时禁用选择行行为



我有一个带有插入/删除行方法的子类化QAbstractTableModel

在主窗口中,我有一个方法insert_data该方法在当前选择单元格时插入字符串 (我打开了单曲选择(
以下是我要更改的行为:
当我使用子类化QAbstractTableModelsetData方法在单元格中插入值时 或带insert_data
并删除该行--->上面的行被选中(该行将其颜色更改为灰色(,
所以该方法会自动插入字符串
结论是 add/del 方法在执行时将添加/删除的行更改为被选中
我尝试过什么:
添加/DEL 行方法通过两个按钮连接

self.addrow_button.clicked.connect(
lambda: self.datamodel.insertRows(-1, 1))
self.deleaterow_button.clicked.connect(
lambda: self.datamodel.removeRows(-1, 1))

所以我将它们连接到selectionModel().clearSelection())以在添加/删除一行时清除该行的选择

self.addrow_button.clicked.connect(lambda: self.mytable_view.selectionModel().clearSelection())
self.deleaterow_button.clicked.connect(lambda: self.mytable_view.selectionModel().clearSelection())

但这只会删除单元格的灰色--->单元格仍处于选中状态,行为仍在继续

有没有办法在执行添加/删除行方法时选择上方/下方行?


代码示例


"""
Testing Template for throw away experiment
"""

import sys
import os
import re
from PyQt5 import QtWidgets as qtw
from PyQt5 import QtCore as qtc
from PyQt5 import QtGui as qtg

class DataModel(qtc.QAbstractTableModel):

def __init__(self, input_data=None):
super().__init__()
self.input_data = input_data or [[None], [None], [None], [None], [None]]

def data(self, index, role):
if role == qtc.Qt.DisplayRole:
try:
text = self.input_data[index.row()][index.column()]
# self.scaledatachanged_signal.emit() dont need it
except IndexError:
text = None
return text
def rowCount(self, index=qtc.QModelIndex()):
return 0 if index.isValid() else len(self.input_data)

def columnCount(self, index):
return len(self.input_data[0])
def headerData(self, section, orientation, role):
if role == qtc.Qt.DisplayRole:
if orientation == qtc.Qt.Vertical:
return "row  " + str(section + 1)

def flags(self, index):
return qtc.Qt.ItemIsEditable | qtc.Qt.ItemIsSelectable | qtc.Qt.ItemIsEnabled
def setData(self, index, value, role=qtc.Qt.EditRole):
if role == qtc.Qt.EditRole:  # The data in a form suitable for editing in an editor. returns string
try:
row = index.row()
column = index.column()
# filter floats and digits and comma stuff
pattern = '^[d]+(?:[,.][d]+)?$'  # execepts "," and "."
if re.fullmatch(pattern, value, flags=0):
pattern = '^.*[,].*$'
if re.fullmatch(pattern, value, flags=0):
value = value.replace(',', '.')
self.input_data[row][column] = float(value)
print(type(value))
else:
self.input_data[row][column] = float(value)  # float
print(type(value))
else:
pass
return True
except ValueError:
return False
def insertRows(self, position, rows, parent=qtc.QModelIndex()):
position = (position + self.rowCount()) if position < 0 else position
start = position
end = position + rows - 1
if end <= 8:
self.beginInsertRows(parent, start, end)
self.input_data.append([None])
self.endInsertRows()
return True
else:
return False
def removeRows(self, position, rows, parent=qtc.QModelIndex()):
position = (position + self.rowCount()) if position < 0 else position
start = position
end = position + rows - 1
if end >= 1:
self.beginRemoveRows(parent, start, end)
del self.input_data[start:end + 1]
self.endRemoveRows()
return True
else:
return False
class MainWindow(qtw.QWidget):
def __init__(self):
super().__init__()

self.mytable_view = qtw.QTableView()
self.mytable_view.setSelectionMode(qtw.QAbstractItemView.SingleSelection)

self.datamodel = DataModel()
self.mytable_view.setModel(self.datamodel)
# widget
self.addrow_button = qtw.QPushButton("add row")
self.deleaterow_button = qtw.QPushButton("deleate row")

# set the layout
layout = qtw.QVBoxLayout()
layout.addWidget(self.mytable_view)
layout.addWidget(self.addrow_button)
layout.addWidget(self.deleaterow_button)
self.setLayout(layout)

# -------------------------------- #
self.addrow_button.clicked.connect(
lambda: self.datamodel.insertRows(-1, 1))
self.deleaterow_button.clicked.connect(
lambda: self.datamodel.removeRows(-1, 1))
self.mytable_view.selectionModel().selectionChanged.connect(self.insert_data)

self.addrow_button.clicked.connect(lambda: self.mytable_view.selectionModel().clearSelection())
self.deleaterow_button.clicked.connect(lambda: self.mytable_view.selectionModel().clearSelection())

def insert_data(self):
x = self.mytable_view.selectionModel().currentIndex().row()
y = self.mytable_view.selectionModel().currentIndex().column()

self.datamodel.input_data[x][y] = "insert this string if cell is selected"
self.datamodel.layoutChanged.emit()
self.mytable_view.selectionModel().clearSelection()


if __name__ == '__main__':
app = qtw.QApplication(sys.argv)
main = MainWindow()
main.show()
sys.exit(app.exec_())


每当删除当前索引项时,始终会自动选择前一个项。请注意,当前索引无法与项目选择匹配:如果选择一个索引,然后清除该选择,则该索引仍将是当前索引。

最简单的解决方案是在删除行之前,使用新的QModelIndex实例(这是一个无效索引(将当前索引设置为无效索引。

# ...
self.deleaterow_button.clicked.connect(self.delete_row)
# ...
def delete_row(self):
self.mytable_view.setCurrentIndex(qtc.QModelIndex())
self.datamodel.removeRows(-1, 1)

最新更新