我有一个QTableView如下。我想按下“测试”按钮并插入" a"在光标处 - 例如在" 11"的中间在(行,列)=(2,2)。也就是说,用户双击单元格(2,2)并将光标放在" 11"的中间,然后按下Test。期望的结果:" 1a1"。
这可行吗?如果有,怎么样?非常感谢。
# coding: utf-8
import sys
from PyQt4 import QtGui, QtCore
from PyQt4.QtCore import *
from PyQt4.QtGui import *
MY_ARRAY = [['00', '01', '02'],
['10', '11', '12'],
['20', '21', '22']]
class MyWindow(QTableView):
def __init__(self, *args):
super(MyWindow, self).__init__()
self.tablemodel = MyTableModel(MY_ARRAY)
self.tableview = QTableView()
self.tableview.setModel(self.tablemodel)
self.tableview.setItemDelegate(MyDelegate(self))
self.layout = QVBoxLayout(self)
self.layout.addWidget(self.tableview)
self.button1 = QPushButton("Test")
self.button1.released.connect(self.test)
self.layout.addWidget(self.button1)
self.setLayout(self.layout)
def test(self):
# MY_ARRAY.append([30,31,32])
index = self.tableview.currentIndex()
item = self.tablemodel.data(index, Qt.DisplayRole)
print("item %s " % item)
item_edit = self.tableview.edit(index)
qDebug("qDebug: item_edit %s " % item_edit)
MY_ARRAY.insert(index.row(), ['30', '31', '32'])
self.tablemodel.layoutChanged.emit()
qDebug(" {} " .format(MY_ARRAY))
qcursor = QCursor.pos()
qDebug(" {} ".format(qcursor))
qcursor1 = self.mapFromGlobal(qcursor)
qDebug(" {} ".format(qcursor1))
# qDebug(" self.tableview.indexAt(qcursor) {} ".format(self.tableview(qcursor)))
# qDebug(" self.tableview.indexAt(qcursor1) {} ".format(self.tableview(qcursor1)))
# print(' index.row(): ', index.row())
qDebug(
" tableview.rowViewportPosition %s " %
self.tableview.rowViewportPosition(index.row()))
qDebug(
" tableview.columnViewportPosition %s " %
self.tableview.columnViewportPosition(index.column()))
# qDebug(" tableview.viewport() %s " % self.tableview.viewport(qcursor))
item = self.tableview.setCurrentIndex(index)
qDebug(" tableview.item() %s " % self.tableview)
class MyTableModel(QAbstractTableModel):
def __init__(self, datain, parent=None, *args):
super(MyTableModel, self).__init__(parent, *args)
self.arraydata = datain
def rowCount(self, parent):
return len(self.arraydata)
def columnCount(self, parent):
return len(self.arraydata[0])
def data(self, index, role):
if not index.isValid():
return None
elif not (role == Qt.DisplayRole or role == Qt.EditRole):
return None
return (self.arraydata[index.row()][index.column()])
def setData(self, index, value, role=Qt.EditRole):
self.arraydata[index.row()][index.column()] = value
return True
def flags(self, index):
return Qt.ItemIsEditable | Qt.ItemIsEnabled | Qt.ItemIsSelectable
class MyDelegate(QStyledItemDelegate):
def __init__(self, parent=None):
super(MyDelegate, self).__init__(parent)
def createEditor(self, parent, option, index):
editor = QLineEdit(parent)
self.connect(editor, SIGNAL("returnPressed()"),
self.commitAndCloseEditor)
return editor
def commitAndCloseEditor(self):
editor = self.sender()
if isinstance(editor, (QTextEdit, QLineEdit)):
self.emit(SIGNAL("commitData(QWidget*)"), editor)
self.emit(SIGNAL("closeEditor(QWidget*)"), editor)
def setEditorData(self, editor, index):
text = index.model().data(index, Qt.DisplayRole)
editor.setText(text)
def setModelData(self, editor, model, index):
model.setData(index, editor.text())
def main():
app = QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
答案 0 :(得分:1)
表格单元格没有光标,无法直接编辑。编辑功能由项目代表提供。默认情况下,文本数据的编辑器窗口小部件是QLineEdit
,但其他数据类型可能使用不同的编辑器窗口小部件,例如QSpinBox
表示数字数据,或QComboBox
表示布尔数据。可以通过设置custom item-delegate来控制使用的特定小部件。
使用类似按钮在编辑小部件中插入文本的一个大问题是,只要单击按钮,编辑器就会自动关闭(并销毁)。因此,使用上下文菜单添加自定义操作会更加简单:
class MyWindow(QTableView):
def __init__(self, *args):
...
self.delegate = MyDelegate(self)
self.delegate.contextMenuRequested.connect(self.showContextMenu)
self.tableview.setItemDelegate(self.delegate)
def showContextMenu(self, editor, pos):
pos = editor.mapToGlobal(pos)
menu = editor.createStandardContextMenu()
menu.addSeparator()
action = menu.addAction('Insert Text')
if menu.exec_(pos) is action:
editor.insert(' foo ')
class MyDelegate(QStyledItemDelegate):
contextMenuRequested = pyqtSignal(object, QPoint)
def createEditor(self, parent, option, index):
editor = QLineEdit(parent)
editor.setContextMenuPolicy(Qt.CustomContextMenu)
editor.customContextMenuRequested.connect(
lambda pos: self.contextMenuRequested.emit(editor, pos))
return editor
答案 1 :(得分:1)
经过大量的努力和qDebug的使用后,我终于找到了解决方案。我相信它可以进一步改进。但我对PyQt一无所知。我们的想法是在编辑器关闭之前将光标位置缓存在MyDelegate(QStyledItemDelegate)中。我希望它对遇到同样问题的人有用。
class MyDelegate(QStyledItemDelegate):
...
def createEditor(self, parent, option, index):
self.cursorpos = -1 # unset flag
editor = QLineEdit(parent)
self.connect(editor, SIGNAL("editingFinished()"),
self.commitAndCloseEditor)
return editor
def commitAndCloseEditor(self):
editor = self.sender()
self.cursorpos = editor.cursorPosition()
if isinstance(editor, (QTextEdit, QLineEdit)):
self.emit(SIGNAL("commitData(QWidget*)"), editor)
self.emit(SIGNAL("closeEditor(QWidget*)"), editor)
以下是整个事情。
# coding: utf-8
import sys
from PyQt4 import QtGui, QtCore
from PyQt4.QtCore import *
from PyQt4.QtGui import *
MY_ARRAY = [['00', '01', '02'],
['10', '11', '12'],
['20', '21', '22']]
class MyWindow(QTableView):
def __init__(self, *args):
super(MyWindow, self).__init__()
self.tablemodel = MyTableModel(MY_ARRAY)
self.tableview = QTableView()
self.tableview.setModel(self.tablemodel)
# self.tableview.setItemDelegate(MyDelegate(self))
self.delegate = MyDelegate(self)
self.tableview.setItemDelegate(self.delegate)
self.layout = QVBoxLayout(self)
self.layout.addWidget(self.tableview)
self.button1 = QPushButton("Test")
self.button1.released.connect(self.test)
self.layout.addWidget(self.button1)
self.setLayout(self.layout)
def test(self):
index = self.tableview.currentIndex()
item = self.tablemodel.data(index, Qt.DisplayRole)
qDebug("item %s " % item)
qDebug(" <test><MyDelegateMyDelegate> self.delegate.cursorpos: %s " % self.delegate.cursorpos)
cursorpos = self.delegate.cursorpos
qDebug(" <test> cursor pos %s " % cursorpos)
if cursorpos > -1:
index.model().setData(index, item[:cursorpos] + ' foo ' + item[cursorpos:])
self.tablemodel.layoutChanged.emit()
self.delegate.cursorpos = -1
class MyTableModel(QAbstractTableModel):
def __init__(self, datain, parent=None, *args):
super(MyTableModel, self).__init__(parent, *args)
self.arraydata = datain
def rowCount(self, parent):
return len(self.arraydata)
def columnCount(self, parent):
return len(self.arraydata[0])
def data(self, index, role):
if not index.isValid():
return None
elif not (role == Qt.DisplayRole or role == Qt.EditRole):
return None
return (self.arraydata[index.row()][index.column()])
def setData(self, index, value, role=Qt.EditRole):
self.arraydata[index.row()][index.column()] = value
return True
def flags(self, index):
return Qt.ItemIsEditable | Qt.ItemIsEnabled | Qt.ItemIsSelectable
class MyDelegate(QStyledItemDelegate):
def __init__(self, parent=None):
super(MyDelegate, self).__init__(parent)
self.cursorpos = -1 # unset flag
def createEditor(self, parent, option, index):
self.cursorpos = -1 # unset flag
editor = QLineEdit(parent)
self.connect(editor, SIGNAL("editingFinished()"),
self.commitAndCloseEditor)
return editor
def commitAndCloseEditor(self):
editor = self.sender()
self.cursorpos = editor.cursorPosition()
if isinstance(editor, (QTextEdit, QLineEdit)):
self.emit(SIGNAL("commitData(QWidget*)"), editor)
self.emit(SIGNAL("closeEditor(QWidget*)"), editor)
def setEditorData(self, editor, index):
text = index.model().data(index, Qt.DisplayRole)
editor.setText(text)
def setModelData(self, editor, model, index):
model.setData(index, editor.text())
def main():
app = QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()