QColorDialog 和 QItemDelegate
QColorDialog and QItemDelegate
我有一个 QTableView,我在其中使用 QItemDelegate 作为按钮。
我正在尝试更改按钮的颜色,所以当我单击它时,我调用了 QColorDialog。但是后来我无法将颜色发送回按钮。
目前进展情况如下:
按钮和 QColorDialog:
class ButtonDelegate(QItemDelegate):
def __init__(self, parent):
QItemDelegate.__init__(self, parent)
def paint(self, painter, option, index):
widget = QWidget()
layout = QHBoxLayout()
widget.setLayout(layout)
btn = QPushButton('')
btn.setStyleSheet("background-color:rgb(86,12,65)")
ix = QPersistentModelIndex(index)
btn.clicked.connect(lambda ix = ix : self.onClicked(ix))
layout.addWidget(btn)
layout.setContentsMargins(2,2,2,2)
if not self.parent().indexWidget(index):
self.parent().setIndexWidget(index, widget)
def onClicked(self, ix):
colorPicker = QColorDialog.getColor()
#colorPicker.show()
r = str(colorPicker.red())
g = str(colorPicker.red())
b = str(colorPicker.red())
bgcolor = 'background-color:rgb(' + r + ',' + g + ',' + b +')'
下一步是什么?我尝试在委托 init 中将按钮声明为 self.btn = QPushButton()
,然后在 onCLick 方法中重用它,但按钮甚至没有那样绘制。
有所启示?
谢谢!
编辑 1
型号:
class Model(QAbstractTableModel):
def __init__(self, vtxTable, parent = None):
QAbstractTableModel.__init__(self, parent)
#data
self.groups = []
#header
self.header_labels = ['Color', 'Group', 'Done']
self.vtxTable = vtxTable
def rowCount(self, parent):
return len(self.groups)
def columnCount(self, parent):
return 3
def flags(self, index):
if index.column() == 2:
fl = fl = Qt.ItemIsEnabled | Qt.ItemIsSelectable
else:
fl = Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsEditable
return fl
def headerData(self, section, orientation, role):
if role == Qt.DisplayRole and orientation == Qt.Horizontal:
return self.header_labels[section]
def removeRow(self, row, parent = QModelIndex()):
self.beginRemoveRows(parent, row, row)
self.groups.remove(self.groups[row])
self.endRemoveRows()
self.vtxTable.setModel(QStringListModel())
def insertRows(self, position, row, values = [] , parent = QModelIndex()):
lastposition = self.rowCount(0)
self.beginInsertRows(parent, lastposition, lastposition)
self.groups.insert(lastposition, values)
self.endInsertRows()
def setData(self, index, value, role = Qt.EditRole):
setIt = False
value = value
row = index.row()
column = index.column()
if role == Qt.EditRole:
setIt = True
if not len(value) == 0:
if value in self.getGrpNames():
warning("Group must have a unique name.")
setIt = False
else:
setIt = True
else:
warning("New group must have a name.")
setIt = False
if role == Qt.BackgroundRole:
setIt = True
if setIt:
self.groups[row][column] = value
self.dataChanged.emit(row, column)
return False
def data(self, index, role):
if not index.isValid():
return
row = index.row()
column = index.column()
if role == Qt.DisplayRole:
if column == 0:
#value = [self.groups[row][column].redF(), self.groups[row][column].greenF(), self.groups[row][column].blueF()]
value = self.groups[row][column]
else:
value = self.groups[row][column]
return value
elif role == Qt.TextAlignmentRole:
return Qt.AlignCenter;
elif role == Qt.EditRole:
index = index
return index.data()
elif role == Qt.BackgroundRole and column == 0:
value = self.groups[row][column]
def getGrpNames(self):
rows = self.rowCount(1)
grps = []
for row in range(rows):
grp = self.index(row, 1).data()
grps.append(grp)
return grps
def getAllVtx(self):
rows = self.rowCount(1)
allVtxs = []
for row in range(rows):
index = self.createIndex(row, 3)
vtxs = index.data()
for vtx in vtxs:
allVtxs.append(vtx)
return allVtxs
def getData(self):
rows = self.rowCount(1)
data = {}
for row in range(rows):
color = self.index(row, 0).data()
grp = self.index(row, 1).data()
done = self.index(row, 2).data()
vtxs = self.groups[row][3]
#index = self.createIndex(row,0)
data[grp] = [grp, color, done, vtxs]
return data
def queryVtx(self, vtx):
data = self.getData()
for key in data:
vtxs = data[key][3]
if vtx in vtxs:
return data[key][0]
else:
return False
Table 查看:
class Table(QTableView):
def __init__(self, *args, **kwargs):
QTableView.__init__(self, *args, **kwargs)
self.setItemDelegateForColumn(0, colorDelegate(self))
hHeader = self.horizontalHeader()
#hHeader.setSectionResizeMode(QHeaderView.Fixed);
self.setSelectionBehavior(QAbstractItemView.SelectRows)
self.setSelectionMode(QAbstractItemView.SingleSelection)
vHeader = self.verticalHeader()
vHeader.hide()
单击行的第一个单元格时,我希望能够为其选择一种颜色,并将其保存在模型中。
谢谢。
委托的目标是自定义显示在 QAbstractItemView 中的每个项目,另一种方法是使用 indexWidget 方法插入一个小部件。委托的优点是内存消耗最小。建议不要同时使用。
代表有以下方法:
paint()
:是负责绘制正常显示的item的方法
createEditor()
: 是负责创建编辑器的方法。
setEditorData()
:获取模型的值并在编辑器中建立。
setModelData()
: 将编辑器获取的数据保存到模型中
此类委托的示例如下:
from PySide2.QtWidgets import *
from PySide2.QtGui import *
from PySide2.QtCore import *
class Delegate(QStyledItemDelegate):
def createEditor(self, parent, option, index):
dialog = QColorDialog(parent)
return dialog
def setEditorData(self, editor, index):
color = index.data(Qt.BackgroundRole)
editor.setCurrentColor(color)
def setModelData(self, editor, model, index):
color = editor.currentColor()
model.setData(index, color, Qt.BackgroundRole)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
model = QStandardItemModel(4, 4)
for i in range(model.rowCount()):
for j in range(model.columnCount()):
color = QColor(qrand() % 256, qrand() % 256, qrand() % 256)
it = QStandardItem("{}{}".format(i, j))
it.setData(color, Qt.BackgroundRole)
model.setItem(i, j, it)
w = QTableView()
w.setModel(model)
w.setItemDelegate(Delegate())
w.show()
sys.exit(app.exec_())
更新:
我改进了你的代码,因为它有不必要的元素,主要错误是这些 Qt::BackgroundRole
必须 return 一个 QColor
from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import *
import warnings
class Model(QAbstractTableModel):
def __init__(self, parent = None):
QAbstractTableModel.__init__(self, parent)
#data
self.groups = []
#header
self.header_labels = ['Color', 'Group', 'Done']
def rowCount(self, parent=QModelIndex()):
return len(self.groups)
def columnCount(self, parent=QModelIndex()):
return 3
def flags(self, index):
fl = Qt.ItemIsEnabled | Qt.ItemIsSelectable
if not index.column() in (2, ):
fl |= Qt.ItemIsEditable
return fl
def headerData(self, section, orientation, role):
if role == Qt.DisplayRole and orientation == Qt.Horizontal:
return self.header_labels[section]
def removeRow(self, row, parent = QModelIndex()):
self.beginRemoveRows(parent, row, row)
self.groups.remove(self.groups[row])
self.endRemoveRows()
def insertRows(self, values = [], position=-1):
if position == -1:
position = self.rowCount()
self.beginInsertRows(QModelIndex(), position, position)
self.groups.insert(position, values)
self.endInsertRows()
def setData(self, index, value, role = Qt.EditRole):
setIt = False
row = index.row()
column = index.column()
if role == Qt.EditRole:
setIt = True
if len(value) != 0:
if value in self.getGrpNames():
warning("Group must have a unique name.")
setIt = False
else:
setIt = True
else:
warning("New group must have a name.")
setIt = False
if role == Qt.BackgroundRole:
setIt = True
if setIt:
self.groups[row][column] = value
self.dataChanged.emit(index, index)
return False
def data(self, index, role):
if not index.isValid():
return
row = index.row()
column = index.column()
value = None
if role == Qt.DisplayRole:
if column == 0:
value = self.groups[row][column]
else:
value = self.groups[row][column]
elif role == Qt.TextAlignmentRole:
value = Qt.AlignCenter;
elif role == Qt.BackgroundRole and column == 0:
value = QColor(self.groups[row][column])
return value
def getGrpNames(self):
rows = self.rowCount(1)
grps = []
for row in range(rows):
grp = self.index(row, 1).data()
grps.append(grp)
return grps
def getAllVtx(self):
rows = self.rowCount(1)
allVtxs = []
for row in range(rows):
index = self.createIndex(row, 3)
vtxs = index.data()
for vtx in vtxs:
allVtxs.append(vtx)
return allVtxs
def getData(self):
rows = self.rowCount(1)
data = {}
for row in range(rows):
color = self.index(row, 0).data()
grp = self.index(row, 1).data()
done = self.index(row, 2).data()
vtxs = self.groups[row][3]
#index = self.createIndex(row,0)
data[grp] = [grp, color, done, vtxs]
return data
def queryVtx(self, vtx):
data = self.getData()
for key in data:
vtxs = data[key][3]
if vtx in vtxs:
return data[key][0]
else:
return False
class ColorDelegate(QStyledItemDelegate):
def createEditor(self, parent, option, index):
dialog = QColorDialog(parent)
return dialog
def setEditorData(self, editor, index):
color = index.data(Qt.BackgroundRole)
editor.setCurrentColor(color)
def setModelData(self, editor, model, index):
color = editor.currentColor()
model.setData(index, color, Qt.BackgroundRole)
class Table(QTableView):
def __init__(self, *args, **kwargs):
QTableView.__init__(self, *args, **kwargs)
self.setItemDelegateForColumn(0, ColorDelegate(self))
hHeader = self.horizontalHeader()
#hHeader.setSectionResizeMode(QHeaderView.Fixed);
self.setSelectionBehavior(QAbstractItemView.SelectRows)
self.setSelectionMode(QAbstractItemView.SingleSelection)
vHeader = self.verticalHeader()
vHeader.hide()
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
w = Table()
model = Model()
w.setModel(model)
model.insertRows(["red", "group1", "no"])
model.insertRows(["blue", "group1", "no"], 0)
w.show()
sys.exit(app.exec_())
我有一个 QTableView,我在其中使用 QItemDelegate 作为按钮。 我正在尝试更改按钮的颜色,所以当我单击它时,我调用了 QColorDialog。但是后来我无法将颜色发送回按钮。
目前进展情况如下:
按钮和 QColorDialog:
class ButtonDelegate(QItemDelegate):
def __init__(self, parent):
QItemDelegate.__init__(self, parent)
def paint(self, painter, option, index):
widget = QWidget()
layout = QHBoxLayout()
widget.setLayout(layout)
btn = QPushButton('')
btn.setStyleSheet("background-color:rgb(86,12,65)")
ix = QPersistentModelIndex(index)
btn.clicked.connect(lambda ix = ix : self.onClicked(ix))
layout.addWidget(btn)
layout.setContentsMargins(2,2,2,2)
if not self.parent().indexWidget(index):
self.parent().setIndexWidget(index, widget)
def onClicked(self, ix):
colorPicker = QColorDialog.getColor()
#colorPicker.show()
r = str(colorPicker.red())
g = str(colorPicker.red())
b = str(colorPicker.red())
bgcolor = 'background-color:rgb(' + r + ',' + g + ',' + b +')'
下一步是什么?我尝试在委托 init 中将按钮声明为 self.btn = QPushButton()
,然后在 onCLick 方法中重用它,但按钮甚至没有那样绘制。
有所启示?
谢谢!
编辑 1型号:
class Model(QAbstractTableModel):
def __init__(self, vtxTable, parent = None):
QAbstractTableModel.__init__(self, parent)
#data
self.groups = []
#header
self.header_labels = ['Color', 'Group', 'Done']
self.vtxTable = vtxTable
def rowCount(self, parent):
return len(self.groups)
def columnCount(self, parent):
return 3
def flags(self, index):
if index.column() == 2:
fl = fl = Qt.ItemIsEnabled | Qt.ItemIsSelectable
else:
fl = Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsEditable
return fl
def headerData(self, section, orientation, role):
if role == Qt.DisplayRole and orientation == Qt.Horizontal:
return self.header_labels[section]
def removeRow(self, row, parent = QModelIndex()):
self.beginRemoveRows(parent, row, row)
self.groups.remove(self.groups[row])
self.endRemoveRows()
self.vtxTable.setModel(QStringListModel())
def insertRows(self, position, row, values = [] , parent = QModelIndex()):
lastposition = self.rowCount(0)
self.beginInsertRows(parent, lastposition, lastposition)
self.groups.insert(lastposition, values)
self.endInsertRows()
def setData(self, index, value, role = Qt.EditRole):
setIt = False
value = value
row = index.row()
column = index.column()
if role == Qt.EditRole:
setIt = True
if not len(value) == 0:
if value in self.getGrpNames():
warning("Group must have a unique name.")
setIt = False
else:
setIt = True
else:
warning("New group must have a name.")
setIt = False
if role == Qt.BackgroundRole:
setIt = True
if setIt:
self.groups[row][column] = value
self.dataChanged.emit(row, column)
return False
def data(self, index, role):
if not index.isValid():
return
row = index.row()
column = index.column()
if role == Qt.DisplayRole:
if column == 0:
#value = [self.groups[row][column].redF(), self.groups[row][column].greenF(), self.groups[row][column].blueF()]
value = self.groups[row][column]
else:
value = self.groups[row][column]
return value
elif role == Qt.TextAlignmentRole:
return Qt.AlignCenter;
elif role == Qt.EditRole:
index = index
return index.data()
elif role == Qt.BackgroundRole and column == 0:
value = self.groups[row][column]
def getGrpNames(self):
rows = self.rowCount(1)
grps = []
for row in range(rows):
grp = self.index(row, 1).data()
grps.append(grp)
return grps
def getAllVtx(self):
rows = self.rowCount(1)
allVtxs = []
for row in range(rows):
index = self.createIndex(row, 3)
vtxs = index.data()
for vtx in vtxs:
allVtxs.append(vtx)
return allVtxs
def getData(self):
rows = self.rowCount(1)
data = {}
for row in range(rows):
color = self.index(row, 0).data()
grp = self.index(row, 1).data()
done = self.index(row, 2).data()
vtxs = self.groups[row][3]
#index = self.createIndex(row,0)
data[grp] = [grp, color, done, vtxs]
return data
def queryVtx(self, vtx):
data = self.getData()
for key in data:
vtxs = data[key][3]
if vtx in vtxs:
return data[key][0]
else:
return False
Table 查看:
class Table(QTableView):
def __init__(self, *args, **kwargs):
QTableView.__init__(self, *args, **kwargs)
self.setItemDelegateForColumn(0, colorDelegate(self))
hHeader = self.horizontalHeader()
#hHeader.setSectionResizeMode(QHeaderView.Fixed);
self.setSelectionBehavior(QAbstractItemView.SelectRows)
self.setSelectionMode(QAbstractItemView.SingleSelection)
vHeader = self.verticalHeader()
vHeader.hide()
单击行的第一个单元格时,我希望能够为其选择一种颜色,并将其保存在模型中。
谢谢。
委托的目标是自定义显示在 QAbstractItemView 中的每个项目,另一种方法是使用 indexWidget 方法插入一个小部件。委托的优点是内存消耗最小。建议不要同时使用。
代表有以下方法:
paint()
:是负责绘制正常显示的item的方法createEditor()
: 是负责创建编辑器的方法。setEditorData()
:获取模型的值并在编辑器中建立。setModelData()
: 将编辑器获取的数据保存到模型中
此类委托的示例如下:
from PySide2.QtWidgets import *
from PySide2.QtGui import *
from PySide2.QtCore import *
class Delegate(QStyledItemDelegate):
def createEditor(self, parent, option, index):
dialog = QColorDialog(parent)
return dialog
def setEditorData(self, editor, index):
color = index.data(Qt.BackgroundRole)
editor.setCurrentColor(color)
def setModelData(self, editor, model, index):
color = editor.currentColor()
model.setData(index, color, Qt.BackgroundRole)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
model = QStandardItemModel(4, 4)
for i in range(model.rowCount()):
for j in range(model.columnCount()):
color = QColor(qrand() % 256, qrand() % 256, qrand() % 256)
it = QStandardItem("{}{}".format(i, j))
it.setData(color, Qt.BackgroundRole)
model.setItem(i, j, it)
w = QTableView()
w.setModel(model)
w.setItemDelegate(Delegate())
w.show()
sys.exit(app.exec_())
更新:
我改进了你的代码,因为它有不必要的元素,主要错误是这些 Qt::BackgroundRole
必须 return 一个 QColor
from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import *
import warnings
class Model(QAbstractTableModel):
def __init__(self, parent = None):
QAbstractTableModel.__init__(self, parent)
#data
self.groups = []
#header
self.header_labels = ['Color', 'Group', 'Done']
def rowCount(self, parent=QModelIndex()):
return len(self.groups)
def columnCount(self, parent=QModelIndex()):
return 3
def flags(self, index):
fl = Qt.ItemIsEnabled | Qt.ItemIsSelectable
if not index.column() in (2, ):
fl |= Qt.ItemIsEditable
return fl
def headerData(self, section, orientation, role):
if role == Qt.DisplayRole and orientation == Qt.Horizontal:
return self.header_labels[section]
def removeRow(self, row, parent = QModelIndex()):
self.beginRemoveRows(parent, row, row)
self.groups.remove(self.groups[row])
self.endRemoveRows()
def insertRows(self, values = [], position=-1):
if position == -1:
position = self.rowCount()
self.beginInsertRows(QModelIndex(), position, position)
self.groups.insert(position, values)
self.endInsertRows()
def setData(self, index, value, role = Qt.EditRole):
setIt = False
row = index.row()
column = index.column()
if role == Qt.EditRole:
setIt = True
if len(value) != 0:
if value in self.getGrpNames():
warning("Group must have a unique name.")
setIt = False
else:
setIt = True
else:
warning("New group must have a name.")
setIt = False
if role == Qt.BackgroundRole:
setIt = True
if setIt:
self.groups[row][column] = value
self.dataChanged.emit(index, index)
return False
def data(self, index, role):
if not index.isValid():
return
row = index.row()
column = index.column()
value = None
if role == Qt.DisplayRole:
if column == 0:
value = self.groups[row][column]
else:
value = self.groups[row][column]
elif role == Qt.TextAlignmentRole:
value = Qt.AlignCenter;
elif role == Qt.BackgroundRole and column == 0:
value = QColor(self.groups[row][column])
return value
def getGrpNames(self):
rows = self.rowCount(1)
grps = []
for row in range(rows):
grp = self.index(row, 1).data()
grps.append(grp)
return grps
def getAllVtx(self):
rows = self.rowCount(1)
allVtxs = []
for row in range(rows):
index = self.createIndex(row, 3)
vtxs = index.data()
for vtx in vtxs:
allVtxs.append(vtx)
return allVtxs
def getData(self):
rows = self.rowCount(1)
data = {}
for row in range(rows):
color = self.index(row, 0).data()
grp = self.index(row, 1).data()
done = self.index(row, 2).data()
vtxs = self.groups[row][3]
#index = self.createIndex(row,0)
data[grp] = [grp, color, done, vtxs]
return data
def queryVtx(self, vtx):
data = self.getData()
for key in data:
vtxs = data[key][3]
if vtx in vtxs:
return data[key][0]
else:
return False
class ColorDelegate(QStyledItemDelegate):
def createEditor(self, parent, option, index):
dialog = QColorDialog(parent)
return dialog
def setEditorData(self, editor, index):
color = index.data(Qt.BackgroundRole)
editor.setCurrentColor(color)
def setModelData(self, editor, model, index):
color = editor.currentColor()
model.setData(index, color, Qt.BackgroundRole)
class Table(QTableView):
def __init__(self, *args, **kwargs):
QTableView.__init__(self, *args, **kwargs)
self.setItemDelegateForColumn(0, ColorDelegate(self))
hHeader = self.horizontalHeader()
#hHeader.setSectionResizeMode(QHeaderView.Fixed);
self.setSelectionBehavior(QAbstractItemView.SelectRows)
self.setSelectionMode(QAbstractItemView.SingleSelection)
vHeader = self.verticalHeader()
vHeader.hide()
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
w = Table()
model = Model()
w.setModel(model)
model.insertRows(["red", "group1", "no"])
model.insertRows(["blue", "group1", "no"], 0)
w.show()
sys.exit(app.exec_())