QTableview常用几种代理总结

在项目中,我们经常使用到QTableview,由于业务需要,经常需要在QTableview中嵌入很多常用的控件,如:QSpinBox、QComboBox、QProcess、QDateTime、QPushButton、QLabel等。编写了一个小demo,先贴图看效果。


1、QCheckBox和QRadioButton的嵌入:  

QCheckBox可以直接在model中设置setCheckable(true)属性;  

QRadionButton的嵌入可设置QTableview中setIndexWidget(const QModelIndex &, QWidget *)属性

具体代码如下:

 for(QList<CModelData *>::const_iterator iter = m_pModelDataList->begin(); iter != m_pModelDataList->end(); iter++){
        QRadioButton *radioBtn = new QRadioButton("unjoin");
        connect(radioBtn, SIGNAL(toggled(bool)), this, SLOT(OnRadioButton(bool)));

        CModelData *pModel = *iter;
        m_pModel->setRowCount(m_pModel->rowCount() + 1);
        int iNumber = m_pModel->rowCount();
        m_pModel->setData(m_pModel->index(iNumber-1, 0, QModelIndex()),iNumber);
        m_pModel->setData(m_pModel->index(iNumber-1, 1, QModelIndex()),pModel->getAge());
        m_pModel->setData(m_pModel->index(iNumber-1, 2, QModelIndex()),pModel->getSex());
        ui->tableView->setIndexWidget(m_pModel->index(iRow, 3), radioBtn); //添加RadioButton
        m_pModel->setData(m_pModel->index(iNumber-1, 4, QModelIndex()),pModel->getTime().toString());
        m_pModel->setData(m_pModel->index(iNumber-1, 5, QModelIndex()),pModel->getProcess());
        m_pModel->setData(m_pModel->index(iNumber-1, 6, QModelIndex()),pModel->getProcess());
        m_pModel->setData(m_pModel->index(iNumber-1, 7, QModelIndex()),"111");

        m_pModel->item(iNumber-1, 0)->setCheckable(true); //添加CheckBox
        m_pModel->item(iNumber-1, 0)->setTextAlignment(Qt::AlignCenter);
        m_pModel->item(iNumber-1, 1)->setTextAlignment(Qt::AlignCenter);
        m_pModel->item(iNumber-1, 2)->setTextAlignment(Qt::AlignCenter);
        m_pModel->item(iNumber-1, 4)->setTextAlignment(Qt::AlignCenter);
        m_pModel->item(iNumber-1, 5)->setEnabled(false);
        iRow++;
    }

2、QHeadView中嵌入QCheckBox类:

CCheckBoxHeaderView::CCheckBoxHeaderView(int checkBoxColumnId, Qt::Orientation orientation, QWidget * parent)
    : QHeaderView(orientation, parent)
{
    m_checkBoxColumnId = checkBoxColumnId;
    m_checkBoxIsOn = false;
}

CCheckBoxHeaderView::~CCheckBoxHeaderView()
{

}

void CCheckBoxHeaderView::paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const
{
    painter->save();
    QHeaderView::paintSection(painter, rect, logicalIndex);
    painter->restore();
    if (logicalIndex == m_checkBoxColumnId)
    {
        QStyleOptionButton option;
        int width = 3;
        for (int i=0; i<logicalIndex; ++i)
            width += sectionSize( i );
        option.rect = QRect(width, 5, 15, 15);
        if (m_checkBoxIsOn)
            option.state = QStyle::State_On;
        else
            option.state = QStyle::State_Off;
        this->style()->drawControl(QStyle::CE_CheckBox, &option, painter);
    }
}

void CCheckBoxHeaderView::mousePressEvent(QMouseEvent *event)
{
    if (visualIndexAt(event->pos().x()) == m_checkBoxColumnId)
    {
        if (m_checkBoxIsOn)
            m_checkBoxIsOn = false;
        else
            m_checkBoxIsOn = true;
        this->updateSection(m_checkBoxColumnId);
        emit sig_AllChecked(m_checkBoxIsOn);
    }

    QHeaderView::mousePressEvent(event);
}

3、QCombobox的嵌入:

CComboBoxDelegate::CComboBoxDelegate(QObject *parent)
    : QStyledItemDelegate(parent)
{

}

QWidget* CComboBoxDelegate::createEditor(QWidget *parent,  const QStyleOptionViewItem &option,
                                         const  QModelIndex &index)  const
{
    Q_UNUSED(option);
    Q_UNUSED(index);
    QComboBox *editor =  new QComboBox(parent);
    editor->addItem("MAN");
    editor->addItem("WOMAN");
    editor->setCurrentIndex(0);
    //editor->setEditable(true);
    return  editor;
}

void  CComboBoxDelegate::setEditorData(QWidget *editor,  const  QModelIndex &index)  const
{
    QString text = index.model()->data(index, Qt::EditRole).toString();
    QComboBox *comboBox =  static_cast <QComboBox*>(editor);
    int  tindex = comboBox->findText(text);
    comboBox->setCurrentIndex(tindex);
}

void  CComboBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
                                      const  QModelIndex &index)  const
{
    QComboBox *comboBox = static_cast<QComboBox*>(editor);
    QString strData = comboBox->currentText();
    model->setData(index, strData, Qt::EditRole);
}

void  CComboBoxDelegate::updateEditorGeometry(QWidget *editor,
                                              const  QStyleOptionViewItem &option,  const  QModelIndex &index) const
{
    Q_UNUSED(index);
    editor->setGeometry(option.rect);
}

4、 QCombox + QCheckBox类

CComboCheckBoxDelegate::CComboCheckBoxDelegate(QObject *parent)
    : QStyledItemDelegate(parent), m_pComboBox(NULL)
{
    QPair<QString, Qt::CheckState> list;
    list.first = "111"; list.second = Qt::Unchecked;
    QPair<QString, Qt::CheckState> list2;
    list2.first = "222"; list.second = Qt::Unchecked;
    QPair<QString, Qt::CheckState> list3;
    list3.first = "333"; list.second = Qt::Unchecked;
    m_lstComboCheckBoxItems.append(list);
    m_lstComboCheckBoxItems.append(list2);
    m_lstComboCheckBoxItems.append(list3);

    m_strCurrentText.clear();
}

CComboCheckBoxDelegate::~CComboCheckBoxDelegate()
{

}

QWidget* CComboCheckBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option,
                                              const QModelIndex &index) const
{
    Q_UNUSED(option);
    Q_UNUSED(index);
    QListWidget* pListWidget = new QListWidget;
    for (int i = 0; i < m_lstComboCheckBoxItems.size(); i++)
    {
        QListWidgetItem* pItem = new QListWidgetItem(pListWidget);
        pItem->setData(Qt::UserRole, i);
        pListWidget->addItem(pItem);

        QCheckBox* pCheckBox = new QCheckBox;
        pCheckBox->setText(m_lstComboCheckBoxItems.at(i).first);
        pCheckBox->setCheckState(m_lstComboCheckBoxItems.at(i).second);
        connect(pCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnStateChanged(int)));
        pListWidget->setItemWidget(pItem, pCheckBox);
    }

    m_pComboBox = new QComboBox(parent);
    m_pComboBox->setModel(pListWidget->model());
    m_pComboBox->setView(pListWidget);
    m_pComboBox->setEditable(true);

    return m_pComboBox;
}


void CComboCheckBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
    QString strText = index.model()->data(index, Qt::EditRole).toString();
    QComboBox *comboBox = static_cast<QComboBox*>(editor);
    comboBox->setEditText(strText);
}


void CComboCheckBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    QComboBox *comboBox = static_cast<QComboBox*>(editor);
    QString strData = comboBox->currentText();
    model->setData(index, strData, Qt::EditRole);
}


void CComboCheckBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
                                                  const QModelIndex &index) const
{
    Q_UNUSED(index);
    editor->setGeometry(option.rect);
}


void CComboCheckBoxDelegate::OnStateChanged(int iState)
{
    m_strCurrentText.clear();
    QCheckBox* pCheckBox = qobject_cast<QCheckBox*>(sender());
    int iCount = m_lstComboCheckBoxItems.size();
    for (int i = 0; i < iCount; i++)
    {
        if (pCheckBox->text().compare(m_lstComboCheckBoxItems.at(i).first) == 0)
        {
            if (iState == 0)
            {
                m_lstComboCheckBoxItems[i] = qMakePair(m_lstComboCheckBoxItems.at(i).first, Qt::Unchecked);
            }
            else if (iState == 1)
            {
                m_lstComboCheckBoxItems[i] = qMakePair(m_lstComboCheckBoxItems.at(i).first, Qt::PartiallyChecked);
            }
            else if (iState == 2)
            {
                m_lstComboCheckBoxItems[i] = qMakePair(m_lstComboCheckBoxItems.at(i).first, Qt::Checked);
            }
        }

        if (m_lstComboCheckBoxItems.at(i).second == Qt::Checked)
        {
            m_strCurrentText += m_lstComboCheckBoxItems.at(i).first;
            m_strCurrentText += ";";
        }
    }

    if (m_strCurrentText.right(1) == ";")
    {
        m_strCurrentText.chop(1);
    }

    if (m_pComboBox != NULL)
    {
        m_pComboBox->setEditText(m_strCurrentText);
    }
}

5、SpinBox的嵌入类:

/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**   * Redistributions of source code must retain the above copyright
**     notice, this list of conditions and the following disclaimer.
**   * Redistributions in binary form must reproduce the above copyright
**     notice, this list of conditions and the following disclaimer in
**     the documentation and/or other materials provided with the
**     distribution.
**   * Neither the name of The Qt Company Ltd nor the names of its
**     contributors may be used to endorse or promote products derived
**     from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/

/*
    delegate.cpp

    A delegate that allows the user to change integer values from the model
    using a spin box widget.
*/

#include "CSpinBoxDelegate.h"
#include <QSpinBox>

//! [0]
CSpinBoxDelegate::CSpinBoxDelegate(QObject *parent)
    : QStyledItemDelegate(parent)
{
}
//! [0]

//! [1]
QWidget *CSpinBoxDelegate::createEditor(QWidget *parent,
    const QStyleOptionViewItem &/* option */,
    const QModelIndex &/* index */) const
{
    QSpinBox *editor = new QSpinBox(parent);
    editor->setFrame(false);
    editor->setAlignment(Qt::AlignCenter);
    editor->setMinimum(0);
    editor->setMaximum(100);

    return editor;
}
//! [1]

//! [2]
void CSpinBoxDelegate::setEditorData(QWidget *editor,
                                    const QModelIndex &index) const
{
    int value = index.model()->data(index, Qt::EditRole).toInt();

    QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
    spinBox->setValue(value);
}
//! [2]

//! [3]
void CSpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
                                   const QModelIndex &index) const
{
    QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
    spinBox->interpretText();
    int value = spinBox->value();

    model->setData(index, value, Qt::EditRole);
}
//! [3]

//! [4]
void CSpinBoxDelegate::updateEditorGeometry(QWidget *editor,
    const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
{
    editor->setGeometry(option.rect);
}
//! [4]

6、QProcess的嵌入类:

//-------------------
//-------------------
CProcess2Delegate::CProcess2Delegate(QObject *parent) :
    QItemDelegate(parent)
{

}

void CProcess2Delegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    int value = index.model()->data(index).toInt();
    QStyleOptionProgressBarV2 progressBarOption;
    progressBarOption.rect = option.rect.adjusted(4, 4, -4, -4);
    progressBarOption.minimum = 0;
    progressBarOption.maximum = 1000;
    progressBarOption.textAlignment = Qt::AlignRight;
    progressBarOption.textVisible = true;
    progressBarOption.progress = value;
    progressBarOption.text = tr("%1%").arg(progressBarOption.progress / 10);

    painter->save();
    if (option.state & QStyle::State_Selected) {
        painter->fillRect(option.rect, option.palette.highlight());
        painter->setBrush(option.palette.highlightedText());
    }
    QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter);

    painter->restore();
}

7、QProcess绘制版本的嵌入类:

CProcessDelegate::CProcessDelegate(QObject *parent) :
    QItemDelegate(parent)
{

}

CProcessDelegate::~CProcessDelegate()
{

}

void CProcessDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    if( option.state & QStyle::State_Selected )
        painter->fillRect( option.rect, option.palette.highlight() );

    // 数据是存储在QStandardItemModel的QStandardItem,会自动根据当前行进行匹配(我认为)
    int value = index.model()->data( index, Qt::DisplayRole ).toInt(); // 这句,取得当前行的数据
    double factor = double(value)/1000.0; // 计算比例因子

    painter->save(); // 保存旧画板(我认为)
    // 进度条背景色
    if( factor > 0.8 )
    {
        painter->setBrush( Qt::red ); // 超过0.8画纯红色
        factor = 1;
    }
    else
        painter->setBrush( QColor( 0, int(factor*255), 255-int(factor*255) ) ); // 否则颜色依次变淡

    painter->setPen( Qt::black ); // 画笔颜色(这里没用到,我认为)
    // 前面都是准备工作,这里才是真正画进度条
    painter->drawRect( option.rect.x()+2, option.rect.y()+2, int(factor*(option.rect.width()-5)), option.rect.height()-5 );
    painter->restore(); // 恢复新画板(我认为)

}


QWidget *CProcessDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const
{
    Q_UNUSED(option);
    Q_UNUSED(index);
    QSlider *slider = new QSlider( parent );

    slider->setAutoFillBackground( true );
    slider->setOrientation( Qt::Horizontal );
    slider->setRange( 0, 1000 );
    slider->installEventFilter( const_cast<CProcessDelegate*>(this) );

    return slider;
}

void CProcessDelegate::updateEditorGeometry( QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index ) const
{

    editor->setGeometry( option.rect );
}

void CProcessDelegate::setEditorData( QWidget *editor, const QModelIndex &index ) const
{
    int value = index.model()->data( index, Qt::DisplayRole ).toInt();
    static_cast<QSlider*>( editor )->setValue( value );
}

void CProcessDelegate::setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const
{
    model->setData( index, static_cast<QSlider*>( editor )->value() );
}


8、QPushButton/QLabel/QImage的嵌入类:

CPixBtnDelegate::CPixBtnDelegate(QObject *parent) :
    QItemDelegate(parent)
{
    m_pBtns = new QMap<QModelIndex, QStyleOptionButton *>();
    pixPath = QString("");
}

CPixBtnDelegate::~CPixBtnDelegate()
{
    foreach (QStyleOptionButton *pBtn, m_pBtns->values()) {
        if (NULL != pBtn) {
            delete pBtn;
            pBtn = NULL;
        }
    }
    m_pBtns->clear();
    if (NULL != m_pBtns) {
        delete m_pBtns;
        m_pBtns = NULL;
    }
}

void CPixBtnDelegate::setPixPath(const QString &path)
{
    pixPath = path;
}

void CPixBtnDelegate::paint(QPainter *painter,const QStyleOptionViewItem &option,
                             const QModelIndex &index) const
{
    QStyleOptionButton * pBtn = m_pBtns->value(index);
    if (NULL == pBtn) {
        pBtn = new QStyleOptionButton();
        pBtn->state |= QStyle::State_Enabled;
        (const_cast<CPixBtnDelegate *>(this))->m_pBtns->insert(index, pBtn);
    }
    int dx1 = 46; int dy1 = 4;
    int dx2 = 30-(option.rect.width()/2 + 16); int dy2 = -4;
    pBtn->rect = option.rect.adjusted(dx1, dy1, dx2, dy2); //设置按钮的大小

    const QPixmap &pixmap = QPixmap(pixPath);
    int width=pixmap.width();
    int height=pixmap.height();
    int x=pBtn->rect.x()+pBtn->rect.width()/2-width/2;
    int y=pBtn->rect.y()+pBtn->rect.height()/2-height/2;

    painter->save();
    if (option.state & QStyle::State_Selected) {
        painter->fillRect(option.rect, option.palette.light());
    }
    painter->drawPixmap(x,y,pixmap);  //设置按钮的背景图片
    painter->restore();
    QApplication::style()->drawControl(QStyle::CE_PushButtonLabel, pBtn, painter);

}

bool CPixBtnDelegate::editorEvent(QEvent *event,QAbstractItemModel *model,
                                   const QStyleOptionViewItem &option,const QModelIndex &index)
{
    if (event->type() == QEvent::MouseButtonPress) {
        QMouseEvent * ev = static_cast<QMouseEvent*>(event);
        if (m_pBtns->contains(index)) {
            QStyleOptionButton * pBtn = m_pBtns->value(index);
            if (pBtn->rect.contains(ev->x(), ev->y())) {
                pBtn->state |= QStyle::State_Sunken;
            }
        }
    }
    if (event->type() == QEvent::MouseButtonRelease) {
        QMouseEvent * ev = static_cast<QMouseEvent*>(event);
        if (m_pBtns->contains(index)) {
            QStyleOptionButton * pBtn = m_pBtns->value(index);
            if (pBtn->rect.contains(ev->x(), ev->y())) {
                pBtn->state &= (~QStyle::State_Sunken);
                emit sig_buttonClicked(index);
            }
        }
    }
    return QItemDelegate::editorEvent(event, model, option, index);
}



  • 21
    点赞
  • 145
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
可以使用自定义代理类来实现一个QPushButton代理。 首先,我们需要创建一个继承自QStyledItemDelegate的自定义代理类。在该类中实现sizeHint()、createEditor()、setEditorData()、setModelData()和updateEditorGeometry()等方法。 下面是一个简单的示例代码: ```c++ #include <QStyledItemDelegate> #include <QPushButton> class PushButtonDelegate : public QStyledItemDelegate { public: PushButtonDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent) {} // 返回按钮的大小 QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override { Q_UNUSED(index); return QSize(option.rect.width(), option.rect.height()); } // 创建一个按钮,并将其设置为编辑器 QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override { Q_UNUSED(index); QPushButton *button = new QPushButton(parent); button->setGeometry(option.rect); return button; } // 将模型数据设置到编辑器中 void setEditorData(QWidget *editor, const QModelIndex &index) const override { Q_UNUSED(editor); Q_UNUSED(index); } // 将编辑器中的数据设置回模型中 void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override { Q_UNUSED(editor); Q_UNUSED(model); Q_UNUSED(index); } // 更新编辑器的位置 void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override { Q_UNUSED(index); editor->setGeometry(option.rect); } }; ``` 在主程序中,我们需要将代理设置给QTableView的某一列: ```c++ QTableView *tableView = new QTableView(this); PushButtonDelegate *delegate = new PushButtonDelegate(this); tableView->setItemDelegateForColumn(columnIndex, delegate); ``` 这样,我们就可以在QTableView中的某一列中显示QPushButton了。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值