用委托的方式为QTableView添加选项框combobox

QTableView可以使用QItemDelegate设置整行整列的编辑行为模式。createeditor
在createEditor中返回重新设计的widget就可以在表格进入编辑状态时在单元格中使用该widget。表格编辑状态的进入方式由editTriggers控制。
在这里插入图片描述
想在表格中加入一列可弹出下拉列表的选项框,效果如下图所示。显示多选框,单击单元格弹出下拉选项。
请添加图片描述
直接添加QComboBox作为editor返回的情况是,平常是正常显示表格,不会出现ComboBox,要点击相应的单元格,进入编辑状态,ComboBox才会出现,然后再点击ComboBox才会出现下拉框选项。

要一直显示ComboBox必须在paint函数中绘制出来,显示静态的样式文字信息。
在这里插入图片描述
要实现进入编辑模式就弹出下拉框选项,在updateEditorGeometry函数中手动弹出。在updateEditorGeometry之前,控件并没有关联对应的表格单元格,所以如果在createEditor时就弹出下拉框,其位置是不会跟随单元格的。
在这里插入图片描述

// delegate.h
class itemdelegate_combo : public QItemDelegate
{
    Q_OBJECT
public:
    explicit itemdelegate_combo(QObject *parent = nullptr);
    QWidget *createEditor(QWidget *, const QStyleOptionViewItem &, const QModelIndex &) const;
    void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;
    void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const  QModelIndex &index) const;
    void set_items(QStringList strl){m_sItemList = strl;}


protected:
    virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;

private:
    QStringList m_sItemList;    //下拉框列表项
};
// delegate.cpp
itemdelegate_combo::itemdelegate_combo(QObject *parent):
    QItemDelegate(parent)
{
}

QWidget *itemdelegate_combo::createEditor(QWidget *parent,const QStyleOptionViewItem &/*option*/,const QModelIndex &index) const
{
    QComboBox *item_w = new QComboBox(parent);
    item_w->setStyle(new combo_style());
    item_w->addItems(m_sItemList);
    return item_w;
}

void itemdelegate_combo::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option, const QModelIndex &/*index*/) const
{
    editor->setGeometry(option.rect);
    if (QComboBox *editor_combo = static_cast<QComboBox *>(editor))
    {
        editor_combo->showPopup();
    }

}

void itemdelegate_combo::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    combo_style combostyle;
    QStyleOptionComboBox combooption;
    combooption.rect = option.rect;
    combostyle.drawComplexControl(QStyle::CC_ComboBox,&combooption, painter);
}

ComboBox的样式由QStyle设定。

// combo_style.h
class combo_style : public QProxyStyle
{
    Q_OBJECT
public:
    combo_style(){}
    void drawComplexControl(ComplexControl which,const QStyleOptionComplex *option,QPainter *painter,const QWidget *widget = nullptr) const override;
    QRect subControlRect(ComplexControl whichControl,const QStyleOptionComplex *option,SubControl whichSubControl,const QWidget *widget = nullptr) const override;
    void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = nullptr) const override;
    void drawControl(ControlElement element, const QStyleOption *opt, QPainter *p, const QWidget *widget) const override;

};
// combo_style.cpp
void combo_style::drawComplexControl(ComplexControl which,const QStyleOptionComplex *option,QPainter *painter,const QWidget *widget) const
{
    if (which == CC_ComboBox)
    {
        if(const QStyleOptionComboBox * cbOption = qstyleoption_cast<const QStyleOptionComboBox *>(option))
        {
            painter->save();
            QRect rect = subControlRect(CC_ComboBox, option,SC_ComboBoxFrame).adjusted(+1, +1, -1, -1);
            painter->translate(option->rect.x(),option->rect.y());
//            painter->setBrush(QColor("#128bf1"));
            painter->setPen(Qt::NoPen);
            painter->setBrush(Qt::NoBrush);
            painter->drawRect(rect);

            rect = subControlRect(CC_ComboBox, option,SC_ComboBoxEditField).adjusted(+2, +2, -2, -2);
            painter->setPen(Qt::NoPen);
            painter->setBrush(Qt::white);
            painter->drawRect(rect);

            rect = subControlRect(CC_ComboBox, option,SC_ComboBoxArrow).adjusted(+1, +1, -1, -1);
            QLinearGradient gradient2(rect.topLeft(),rect.bottomRight());
            gradient2.setColorAt(0.0, QColor("#84fab0"));
            gradient2.setColorAt(1.0, QColor("#8fd3f4"));
            painter->setBrush(gradient2);
            painter->setPen(Qt::NoPen);
            painter->drawRect(rect);
            painter->restore();

            QStyleOption arrowOpt(*cbOption);
            arrowOpt.rect = rect.adjusted(+rect.width() * 0.3, +rect.height() * 0.3,
                                          -rect.width() * 0.3, -rect.height() * 0.3);
            arrowOpt.rect = arrowOpt.rect.adjusted(+option->rect.x(), +option->rect.y(),
                                          +option->rect.x(), +option->rect.y());
            drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, painter,widget);

        }
    }
    else
    {
        QProxyStyle::drawComplexControl(which, option, painter,widget);
    }
}

QRect combo_style::subControlRect(ComplexControl whichControl,const QStyleOptionComplex *option,SubControl whichSubControl,const QWidget *widget) const
{
    if (whichControl == CC_ComboBox)
    {
        switch (whichSubControl)
        {
            case SC_ComboBoxEditField:
                return QRect(0,0,option->rect.width() * 0.5,option->rect.height()).adjusted(+2, +2, -2, -2);
            case SC_ComboBoxFrame:
                return QRect(0,0,option->rect.width() * 0.5,option->rect.height());
            case SC_ComboBoxArrow:
                return QRect(int(option->rect.width() * 0.5), 0, int(option->rect.width() * 0.5), int(option->rect.height()));
            default:
                return QProxyStyle::subControlRect(whichControl, option,whichSubControl, widget);
        }
    }
    else
    {
        return QProxyStyle::subControlRect(whichControl, option,whichSubControl, widget);
    }
}

void combo_style::drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const
{
    switch (element)
    {
    case PE_IndicatorArrowDown:
    {
        qDebug() << "arrow draw" << option->rect;
        painter->save();
        painter->translate(option->rect.x(),option->rect.y());
        QPainterPath drawtriangle;  //画三角形
        drawtriangle.moveTo(0,0);
        drawtriangle.lineTo(option->rect.width()/2,option->rect.height());
        drawtriangle.lineTo(option->rect.width(),0);
        drawtriangle.lineTo(0,0);
        painter->setPen(QPen(QColor("#128bf1"), 2));
        painter->drawPath(drawtriangle);  //绘制出图形
        painter->restore();
    }
        break;
    default:
        QProxyStyle::drawPrimitive(element, option, painter, widget);
    }

}

ComboBox绘制参考自:
QT风格(QStyle):绘制一个自定义QComboBox

  • 0
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
要在QTableView添加单选和复选,您需要使用QItemDelegate类和setIndexWidget函数。以下是一个简单的示例: ```python from PyQt5.QtWidgets import QTableView, QItemDelegate, QRadioButton, QCheckBox class RadioButtonDelegate(QItemDelegate): def createEditor(self, parent, option, index): editor = QRadioButton(parent) editor.setChecked(index.data() == True) return editor def setEditorData(self, editor, index): editor.setChecked(index.data() == True) def setModelData(self, editor, model, index): model.setData(index, editor.isChecked(), role=QtCore.Qt.EditRole) class CheckBoxDelegate(QItemDelegate): def createEditor(self, parent, option, index): editor = QCheckBox(parent) editor.setChecked(index.data() == True) return editor def setEditorData(self, editor, index): editor.setChecked(index.data() == True) def setModelData(self, editor, model, index): model.setData(index, editor.isChecked(), role=QtCore.Qt.EditRole) ``` 我们创建了两个代理类:一个RadioButtonDelegate用于单选,一个CheckBoxDelegate用于复选。createEditor函数用于创建编辑器,setEditorData用于设置编辑器的当前值,setModelData用于将编辑器的值设置回模型中。 然后,您可以将这些代理分配给特定的列: ```python radio_delegate = RadioButtonDelegate() check_delegate = CheckBoxDelegate() table_view.setItemDelegateForColumn(1, radio_delegate) table_view.setItemDelegateForColumn(2, check_delegate) ``` 这将使第2列显示为单选,第3列显示为复选

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值