【问题标题】:Cant get a custom ItemDelegate to work无法让自定义 ItemDelegate 工作
【发布时间】:2010-09-28 10:39:30
【问题描述】:

首先,我是 python 和 pyqt 的新手,所以请多多包涵。

我使用带有 QSqlTableModel 的 QTableView 一切都按预期工作。 视图的最后一列仅包含 0 和 1 作为我想要显示为复选框的值,并且该列应该是可编辑的。

我读到你应该继承我所做的 QItemDelegate。不幸的是,我的表格不会将最后一列显示为复选框。

我尝试使用 setItemDelegateForColumn() 仅为最后一列(我希望的方式)设置委托,但没有成功。所以我修改它并使用 setItemDelegate() 为整个 QTableView 设置它,只对最后一列的请求做出反应。它仍然无法正常工作。不起作用意味着没有错误消息,它只是不会按照我说的去做;) 似乎除了 init() 之外,我重新实现的方法都没有被调用过。所以我想我错过了一些基本的东西。

我提取了相关的代码行,KSCheckBoxDelegate 是我的子类。这是为整个 QTableView 设置委托的版本。


-- code from applications main class --
self.taglist = QTableView()
self.tagmodel = QSqlTableModel()
self.tagmodel.setTable("data")
self.tagmodel.select()
self.taglist.setModel(self.tagmodel)
print self.taglist.itemDelegate()
myDel = KSCheckBoxDelegate(self)
myDel.colnumber = 3
self.taglist.setItemDelegate(myDel)


-- KSCheckBoxDelegate.py --
from PyQt4.QtGui import *

class KSCheckBoxDelegate(QStyledItemDelegate):

    colnumber = None

    def __init__ (self, parent = None):
        print "KSCheckBoxDelegate::init"
        QStyledItemDelegate.__init__(self, parent)

    def createEditor(self, parent, option, index):
        print "KSCheckBoxDelegate::createEditor"
        if index.column()==self.colnumber:
            return QCheckBox(self)
        else:
            return QStyledItemDelegate.createEditor(self, parent, option, index)

    def setEditorData (self, editor, index):
        print "KSCheckBoxDelegate::setEditorData"
        if index.column() == self.colnumber:
            cont = index.model().data(index, Qt.DisplayRole).toString()
            if cont == "1":
                editor.setCheckState(Qt.Checked)
            else:
                editor.setCheckState(Qt.UnChecked)
        else:
            QStyledItemDelegate.setEditorData(self,editor, index)

    def setModelData (self, editor, model, index):
        print "KSCheckBoxDelegate::setModelData"
        if index.column() == self.colnumber:
            if editor.checkBox.checkState() == Qt.Checked:
                model.setData(index, 1)
            else:
                model.setData(index, 0)
        else:
            QStyledItemDelegate.setModelData(self, editor, model, index)

在这个问题上对我有什么提示吗?

此外,我对 QTableViews selectionModel 的 currentChanged() 信号有困难。我打印选择的右上角坐标。用鼠标左键单击时,我不断得到错误的索引(不是无效的)。使用光标键可以获得正确的索引。使用 selectionChanged() 具有相同的行为。我实际上得到了 QTableView 的倒数第二个选定单元格的坐标。例如,我点击坐标 ,第二次点击会显示坐标 。


selInd = self.taglist.selectionModel().selectedIndexes()
if(len(selInd) > 0):
    self.xPosData=selInd[0].column()
    self.yPosData=selInd[0].row()

我自己解决了这个问题,使用 QTableView.currentIndex() 而不是 selectionModel.selectedIndexes() :)

最后使用 OnManualSubmit 作为 editStrategy 在调用 submitAll() 时不会抛出错误(返回 false),但也不会保存数据。它适用于选择 OnFieldChange 作为 editStrategy。我可以忍受,但不是我打算这样做的。

感谢您的宝贵时间。

霍斯特

【问题讨论】:

  • 这里只是一个评论,不要混淆选定的和当前的索引,并使用你真正想要的。根据您的选择模型,当前索引可能很容易不被选择,并且(如您所见)所选索引可能不包括当前索引。

标签: python qt qt4 pyqt pyqt4


【解决方案1】:

我认为创建自己的基于 QSqlTableModel 的模型会更简单,并且对于您的 0/1 列,为 QDisplayRole 返回 QVariant() 并根据值返回 Qt::Checked/Qt::Unchecked 为 Qt::CheckStateRole。对于所有其他情况,返回 QSqlTableModel::data

class MySqlTableModel: public QSqlTableModel
{
public:
// contructors
    QVariant data(const QModelIndex & index, int role = Qt::DisplayRole)
    {
        if(index.column() == 3 /* your 0/1 column */)
        {
            if(role == Qt::DisplayRole)
            {
                return QVariant();
            }
            else if(role == Qt::CheckStateRole)
            {
                QString value = QSqlTableModel::data(index, Qt::DisplayRole).toString();
                return value == "1" ? Qt::Checked : Qt::Unchecked;
            }
        }

        return QSqlTableModel::data(index, role);
    }
};

我知道是 C++ 代码,但逻辑还是一样的,所以只为 Python 重新调整它

【讨论】:

  • 只是一个简短的更新和另一个问题,我实际上回到仅将委托应用于列,在启动我的应用程序后,此列仍然显示 0 和 1 但是如果我双击一个单元格,我得到一个正确表示值的复选框。不幸的是,我无法编辑复选框(它不可点击)。我需要派生自己的模型并重载 flags() 方法吗?我做了无济于事:/此外,我现在认为我需要重新实现我的委托的 paint() 方法以使其显示复选框,对吗?
  • 我试过了,Kamil,谢谢你的努力。不幸的是,我没有让它进入工作状态:/ - 我实际上使用 QSQLTableModel 运行,QItemDelegate 分配给第 3 列并且它可以工作:) 我只是缺少编辑复选框 atm 的能力。
【解决方案2】:

至少我设法让我的代表在显示和编辑模式下显示具有正确状态的复选框。因为我找不到关于如何做到这一点的完整描述,所以分享它。也许其他人试图做类似的事情而没有使用过 qt。

只缺少一件事,那就是可编辑的项目,我想这与我在开篇文章中提出的标志问题有关。

-- KSCheckBoxDelegate.py--


class KSCheckBoxDelegate(QStyledItemDelegate):
    def __init__ (self, parent = None):
        print "KSCheckBoxDelegate::init"
        QStyledItemDelegate.__init__(self, parent)

    def createEditor(self, parent, option, index):
        print "KSCheckBoxDelegate::createEditor"
        return QCheckBox(parent)

    def setEditorData (self, editor, index):
        print "KSCheckBoxDelegate::setEditorData"
        cont = index.model().data(index, Qt.DisplayRole).toString()
        if cont == "1":
            editor.setCheckState(Qt.Checked)
        else:
            editor.setCheckState(Qt.Unchecked)

    def setModelData (self, editor, model, index):
        print "KSCheckBoxDelegate::setModelData"
        if editor.checkState() == Qt.Checked:
            model.setData(index, 1)
        else:
            model.setData(index, 0)

    def paint (self, painter, option, index):
        myopt = QStyleOptionViewItemV4(option)
        newopt = QStyleOptionButton()
        newopt.rect = myopt.rect
        newopt.palette = myopt.palette
        if index.data().toBool():
            newopt.state |= QStyle.State_On
        QApplication.style().drawControl(QStyle.CE_CheckBox, newopt, painter)

    def sizeHint (self, option, index):
        return 18

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-22
    相关资源
    最近更新 更多