在检查更复杂的setting中项目委托编辑器的生命周期问题的不同问题的过程中,当从QStyledItemDelegate子类调用时,我偶然发现了QColorDialog的奇怪行为。
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QColor,QStandardItem, QStandardItemModel
from PyQt5.QtWidgets import (
QAbstractItemView, QApplication, QColorDialog,
QGridLayout, QStyledItemDelegate, QTableView, QWidget
)
class ItemDelegate(QStyledItemDelegate):
def createEditor(self, parent, option, index):
if index.column() == 1:
return QColorDialog(parent)
#return QColorDialog(parent.parent())
#return QColorDialog()
else:
return super(ItemDelegate, self).createEditor(parent, option, index)
def setEditorData(self, editor, index):
if index.column() == 1:
value = index.model().data(index, Qt.EditRole)
color = QColor(value)
editor.setCurrentColor(color)
editor.show()
else:
super(ItemDelegate, self).setEditorData(editor, index)
def setModelData(self, editor, model, index):
if index.column() == 1:
color = editor.currentColor()
model.setData(index, color, Qt.EditRole)
else:
super(ItemDelegate, self).setModelData(editor, model, index)
def updateEditorGeometry(self, editor, option, index):
if index.column() == 1:
pass
else:
super(ItemDelegate, self).updateEditorGeometry(editor, option, index)
class ColorItem(QStandardItem):
def __init__(self, color):
super(ColorItem, self).__init__()
self.setData(color)
def setData(self, value, role = Qt.EditRole):
if role == Qt.EditRole and isinstance(value, QColor):
super(ColorItem, self).setData(value, Qt.DecorationRole)
super(ColorItem, self).setData(value, role)
def type(self):
return QStandardItem.UserType + 234
class Window(QWidget):
def __init__(self, parent = None):
super(Window, self).__init__(parent)
self.setWindowTitle("Item Delegate")
data = [
# label, rgb
[ 'color', (0, 139, 139)],
[ 'color', (255, 215, 0)],
]
# create model, view, and delegate
self.model = model = QStandardItemModel(len(data), 2)
tableView = QTableView()
tableView.setModel(model)
delegate = ItemDelegate()
tableView.setItemDelegate(delegate)
tableView.horizontalHeader().setStretchLastSection(True)
tableView.setEditTriggers(
QAbstractItemView.EditKeyPressed |
QAbstractItemView.DoubleClicked |
QAbstractItemView.SelectedClicked)
# fill model with data
for row, (label, rgb) in enumerate(data):
# column 0
model.setItem(row, 0, QStandardItem(label))
# column 1
model.setItem(row, 1, ColorItem(QColor(*rgb)))
#index = model.index(row, 1, QModelIndex())
#tableView.openPersistentEditor(index)
# finalize window
layout = QGridLayout()
layout.addWidget(tableView, 0, 0)
self.setLayout(layout)
self.resize(400, 200)
def result(self):
model = self.model
for row in range(model.rowCount()):
label = model.item(row, 0).data(Qt.EditRole)
value = model.item(row, 1).data(Qt.EditRole)
print('[%s] %s: %s' % (row, label, value.getRgb()[:3]))
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
window = Window()
window.show()
ret = app.exec_()
window.result()
sys.exit(ret)
执行此脚本时,双击颜色项会显示标准QColorDialog。如果移动,对话框将立即关闭。 OTOH,如果事先选择任意颜色,则对话框是可移动的。
需要对此行为进行解释。
此生命周期问题与底层QStyledItemDelegate小部件有关。表视图上的焦点更改可能会导致创建的编辑器窗口小部件被破坏,但为什么选择颜色会有所不同呢?我已经为QColorDialog尝试了不同的父母,但行为仍然存在,所以它闻起来就像一个问题,在对话框本身内部。
Environment:
Python: 3.4.5
Sip: 4.19.2
Qt5: 5.8.0
PyQt5: 5.8.2
Linux: openSUSE/KDE4