如何解决为什么我的 QStyleItemDelegate 会在新窗口中而不是在我的 TableView 中弹出?
我正在尝试使用 pyside2 创建一个非常简单的应用程序,该应用程序在用户可以编辑的表中显示一些数据。我希望表格的单元格根据表格中的其他值自动完成,因此我在 this tutorial 之后实现了一个自定义委托。这非常简单,并且委托按预期工作除了出于某种原因委托在新窗口中弹出而不是附加到表格中的单元格,如下所示示例(自定义委托在最后定义):
import pandas as pd
from pyside2 import QtWidgets,QtCore
from pyside2.QtCore import Qt
class TableView(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.setobjectName(u"TableView")
self.centralwidget = QtWidgets.QWidget(self)
self.centralwidget.setobjectName(u"centralwidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout.setobjectName(u"verticalLayout")
self.frame = QtWidgets.qframe(self.centralwidget)
self.frame.setobjectName(u"frame")
self.frame.setFrameShape(QtWidgets.qframe.StyledPanel)
self.frame.setFrameShadow(QtWidgets.qframe.Raised)
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.frame)
self.verticalLayout_2.setobjectName(u"verticalLayout_2")
self.tableView = QtWidgets.QTableView(self.frame)
self.tableView.setobjectName(u"tableView")
delegate = QAutoCompleteDelegate(self.tableView)
self.tableView.setItemDelegate(delegate)
self.tableModel = TableModel(self.tableView)
self.tableView.setModel(self.tableModel)
self.verticalLayout_2.addWidget(self.tableView)
self.verticalLayout.addWidget(self.frame)
self.setCentralWidget(self.centralwidget)
self.statusbar = QtWidgets.QStatusBar(self)
self.statusbar.setobjectName(u"statusbar")
self.setStatusBar(self.statusbar)
QtCore.QMetaObject.connectSlotsByName(self)
class TableModel(QtCore.QAbstractTableModel):
def __init__(self,parent=None):
super(TableModel,self).__init__(parent=parent)
self._data = pd.DataFrame([["A0","B0","C0"],["A1","B1","C1"],["A2","B2","C2"]],columns=["A","B","C"])
def data(self,index,role):
# Should only ever refer to the data by iloc in this method,unless you
# go specifically fetch the correct loc based on the iloc
row = index.row()
col = index.column()
if role == Qt.displayRole or role == Qt.EditRole:
return self._data.iloc[row,col]
def rowCount(self,index):
return len(self._data)
def columnCount(self,index):
return len(self._data.columns)
def headerData(self,col,orientation,role):
if orientation == Qt.Horizontal and role == Qt.displayRole:
return self._data.columns[col]
return None
def unique_vals(self,index):
""" Identify the values to include in an autocompletion delegate for the given index """
column = index.column()
col_name = self._data.columns[column]
return list(self._data[col_name].unique())
def setData(self,value,role):
if role != Qt.EditRole:
return False
row = self._data.index[index.row()]
column = self._data.columns[index.column()]
self._data.loc[row,column] = value
self.dataChanged.emit(index,index)
return True
def flags(self,index):
flags = super(self.__class__,self).flags(index)
flags |= Qt.ItemIsEditable
flags |= Qt.ItemIsSelectable
flags |= Qt.ItemIsEnabled
flags |= Qt.ItemIsDragEnabled
flags |= Qt.ItemIsDropEnabled
return flags
class QAutoCompleteDelegate(QtWidgets.qstyledItemDelegate):
def createEditor(self,parent: QtWidgets.QWidget,option: QtWidgets.qstyleOptionViewItem,index: QtCore.QModelIndex) -> QtWidgets.QWidget:
le = QtWidgets.QLineEdit()
test = ["option1","option2","option3"]
complete = QtWidgets.QCompleter(test)
le.setCompleter(complete)
return le
def setEditorData(self,editor:QtWidgets.QLineEdit,index:QtCore.QModelIndex):
val = index.model().data(index,Qt.EditRole)
options = index.model().unique_vals(index)
editor.setText(val)
completer = QtWidgets.QCompleter(options)
editor.setCompleter(completer)
def updateEditorGeometry(self,editor: QtWidgets.QWidget,index: QtCore.QModelIndex):
editor.setGeometry(option.rect)
app = QtWidgets.QApplication()
tv = TableView()
tv.show()
app.exec_()
显示单元格处于活动状态时表格行为的图像
从我读过的所有内容来看,自定义委托上的 updateEditorGeometry
方法应该将其锚定到活动单元格,但在我的情况下,某些事情显然没有按预期工作。而且我仍在学习 Qt,所以我不能声称了解它在做什么。有没有人可以解释这里发生的事情?非常感谢。
- 操作系统:Ubuntu 20.04
- Python 3.8.5
- pyside2 5.15.0
- Qt 5.12.9
解决方法
任何没有父级的小部件都将是一个窗口,并且由于 QLineEdit 没有父级,因此您可以观察 OP 指示的行为,因此 createEditor 方法将“父级”作为参数。
另一方面,最好创建一个自定义的 QLineEdit,它可以轻松实现通过模型向 QCompleter 添加建议的处理。
class AutoCompleteLineEdit(QtWidgets.QLineEdit):
def __init__(self,parent=None):
super().__init__(parent)
self._completer_model = QtGui.QStandardItemModel()
completer = QtWidgets.QCompleter()
completer.setModel(self._completer_model)
self.setCompleter(completer)
@property
def suggestions(self):
return [
self._completer_model.item(i).text()
for i in range(self._completer_model.rowCount())
]
@suggestions.setter
def suggestions(self,suggestions):
self._completer_model.clear()
for suggestion in suggestions:
item = QtGui.QStandardItem(suggestion)
self._completer_model.appendRow(item)
class QAutoCompleteDelegate(QtWidgets.QStyledItemDelegate):
def createEditor(
self,parent: QtWidgets.QWidget,option: QtWidgets.QStyleOptionViewItem,index: QtCore.QModelIndex,) -> QtWidgets.QWidget:
le = AutoCompleteLineEdit(parent)
return le
def setEditorData(self,editor: QtWidgets.QWidget,index: QtCore.QModelIndex):
val = index.model().data(index,Qt.EditRole)
options = index.model().unique_vals(index)
editor.setText(val)
editor.suggestions = options
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。