通过QTreeView中的QAbstractItemModel实现的用户可编辑复选框的自定义

时间:2019-07-17 04:33:19

标签: c++ qt

我有带有QAbstractItemModel的QTreeView。某些特定的列应该具有用户定义的复选框。我是通过重写QAbstractItemModel :: data()函数并通过发送Qt :: CheckStateRole角色的检查状态来实现的,如代码中所示。

我正在获得复选框,并且能够成功选中和取消选中它们。 但是要求是自定义其中一些复选框。基本上,我需要通过任何方法将某些复选框与其他复选框区分开,例如:用蓝色填充复选框,使复选框的边界为蓝色或任何其他方法。但是我不确定如何通过模型创建复选框时如何更改复选框样式。

QVariant MyModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();
    if (role == Qt::CheckStateRole && index.column() == COLUMN_WITH_CHECKBOX)
    {
        //return Qt::Checked or Qt::Unchecked here
    }
    //...
}

bool MyModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (!index.isValid())
        return false;
    if (role == Qt::CheckStateRole)
    {
        if ((Qt::CheckState)value.toInt() == Qt::Checked)
        {
            //user has checked item
            return true;
        }
        else
        {
            //user has unchecked item
            return true;
        }
    }
    return false;
}

1 个答案:

答案 0 :(得分:3)

首先,您需要实现自己的ItemDelegate

class CheckedDelegate : public QStyledItemDelegate
{
    Q_OBJECT
public:
    CheckedDelegate(QObject *parent = nullptr);
    ~CheckedDelegate();

    QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
    void setEditorData(QWidget *editor, const QModelIndex& index) const;
    void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex& index) const;
    void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex& index) const;
    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex& index) const;

};

在此委托中,您必须实现自定义编辑器和自定义项目绘画。创建自定义编辑器:

QWidget *CheckedDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QCheckBox *chBox = new QCheckBox(parent);
    //customize editor checkbox
    QString strQss = "QCheckBox::indicator:checked { image: url(:/icons/pic/checkboxChecked.png); } ";
    strQss.append("QCheckBox::indicator:unchecked { image: url(:/icons/pic/checkboxUnchecked.png); }");
    chBox->setStyleSheet(strQss);
    return chBox;
}

void CheckedDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
    QCheckBox *chBox = dynamic_cast<QCheckBox*> (editor);
    if (index.data(Qt::CheckStateRole).toInt() == Qt::Checked)
    {
        chBox->setChecked(true);
    }
    else
    {
        chBox->setChecked(false);
    }
}

void CheckedDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    QCheckBox *chBox = dynamic_cast<QCheckBox*> (editor);
    model->setData(index, chBox->isChecked() ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole);
}

void CheckedDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    editor->setGeometry(GetCheckboxRect(option));
}

要计算复选框的几何形状,请使用

QRect GetCheckboxRect(const QStyleOptionViewItem &option)
{
    QStyleOptionButton opt_button;
    opt_button.QStyleOption::operator=(option);
    QRect sz = QApplication::style()->subElementRect(QStyle::SE_ViewItemCheckIndicator, &opt_button);
    QRect r = option.rect;
    // center 'sz' within 'r'
    double dx = (r.width() - sz.width()) / 2;
    double dy = (r.height()- sz.height()) / 2;
    r.setTopLeft(r.topLeft() + QPoint(qRound(dx),qRound(dy)));
    r.setWidth(sz.width());
    r.setHeight(sz.height());

    return r;
}

然后实现自定义绘画。在此示例中,我使用像素图自定义复选框,因此我也仅绘制像素图。

void CheckedDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QStyleOptionViewItem opt = option;
    QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &opt, painter);
    if (index.data(Qt::CheckStateRole).toInt() == Qt::Checked) {
        QApplication::style()->drawItemPixmap(painter, GetCheckboxRect(option), Qt::AlignLeft | Qt::AlignVCenter, QPixmap(":/icons/pic/checkboxChecked.png"));
    } else {
        QApplication::style()->drawItemPixmap(painter, GetCheckboxRect(option), Qt::AlignLeft | Qt::AlignVCenter, QPixmap(":/icons/pic/checkboxUnchecked.png"));
    }
}

并设置您的代表(在我的示例中,我有TableTiew而不是TreeView

CheckedDelegate *chDel = new CheckedDelegate(this);
ui->tableView->setItemDelegateForColumn(1, chDel);