首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >QColorDialog和QItemDelegate

QColorDialog和QItemDelegate
EN

Stack Overflow用户
提问于 2018-02-01 23:58:43
回答 1查看 1K关注 0票数 0

我有一个QTableView,我在其中使用一个QItemDelegate作为按钮。我试图改变按钮的颜色,所以当我点击它时,我就调用一个QColorDialog。但我很难把颜色放回按钮上。

以下是目前的进展情况:

按钮和QColorDialog:

代码语言:javascript
复制
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

型号:

代码语言:javascript
复制
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

表视图:

代码语言:javascript
复制
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()

当单击行的第一个单元格时,我希望能够在顶部为其选择颜色,并将其保存在模型中。

谢谢。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-02-02 01:15:22

委托的目标是自定义QAbstractItemView中显示的每一项,另一种方法是使用indexWidget方法插入小部件。委托的优点是内存消耗最小。最好不要同时使用它们。

代表们有以下方法:

  • paint():是负责绘制通常显示的项的方法
  • createEditor():是该方法负责创建编辑器。
  • setEditorData():获取模型的值并在编辑器中建立它。
  • setModelData():将从编辑器获得的数据保存到模型中。

这类委托的一个例子是:

代码语言:javascript
复制
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必须返回一个QColor。

代码语言:javascript
复制
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_())
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48573717

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档