qt利用委托:QStyledItemDelegate,实现tableview 的表格项的自定义显示,如插入图片,绘制控件

        在qt数据的显示中经常有用到数据显示的model/view结构,简单说一下就是简单的数据我们可以直接用类似于listwidget之类的已经实现好的类来操作,但是当数据我们想要有比较好的分离控制的时候,会把数据和显示分开来,用model来存储和修改数据,view只是用来显示这些数据,而在两者之间,我们可以通过delegate代理类在两者之间充当一个中间层进行数据的过滤之类的操作,或者是让数据按照我们的想法来显示。

        这个tabelview里面插入插控件的部分可以参考一下这个,举例写的挺细的了:http://qimo601.iteye.com/blog/1539147http://qimo601.iteye.com/blog/1538333

这次举例用的是比较通用的tableview ,tablemodel。首先是数据的model类,那么需要继承一个QAbstractTableModel 需要重写的函数看看文档就知道了,大概就有columnCountrowCount这两个获取行列数量的,还有两个获取数据的,headerData用于view来获取表格的行列的标题,然后data则是获取表格项的数据了。简单的代码例子:

两个函数一起来了:

QVariant xxxModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    //横向的标题
    if(orientation == Qt::Horizontal) {
        if (role == Qt::TextAlignmentRole) {
                return int(Qt::AlignHCenter | Qt::AlignVCenter);
            }
        //section列数小于存储的标题list(HheaderStr) 的长度的时候返回标题字串
        if(role == Qt::DisplayRole && section < HheaderStr.count())
        {
            if(section!=0)
                return HheaderStr.at(section);
            else
                return "";
        }
        //为第一行添加icon的装饰
        if(role==Qt::DecorationRole && section ==0)
            return QIcon(":/image/image/xxx.ico");
    }else
        //纵向的标题
        if(orientation == Qt::Vertical)
        {
            if(role == Qt::DisplayRole ) {
                return section+1;
            }
        }
    return QAbstractTableModel::headerData(section, orientation, role);
}
//表项数据的处理
QVariant xxxModel::data(const QModelIndex &index, int role) const
{
    if(!index.isValid())
    {
        return QVariant();
    }
    if (role == Qt::TextAlignmentRole) {
            return int(Qt::AlignHCenter | Qt::AlignVCenter);
        }
    else if (role == Qt::DisplayRole)
    {
        if(index.column() < HheaderStr.count())
        {   //这里就是你定下的数据的返回
            return xxxList.at(index.row()).at(index.column());
        }
        else
            return QVariant();
    }
    return QVariant();
}

注释都比较清楚了。看一下大概。因为我只是对于数据的显示形式做一个变化,所以基本model类除了保存返回数据,基本不需要在做什么。大部分的操作都是在继承自QStyledItemDelegate的类里面操作。大概的代码就是:

class xxxDelegate : public  QStyledItemDelegate
{
public:
    xxxDelegate(QObject * parent=0);
    virtual ~ xxxDelegate(){}

    void paint(QPainter * painter,
        const QStyleOptionViewItem & option,
        const QModelIndex & index) const;
};

在重写的paint函数里面完成你自己想做的操作就可以了。比如我这里是在第0列,会放一个图标,在第3列会让数据按照百分比来绘制不同的长度最后加上百分号数值:

//重写这个函数来改变表项自定义的显示方式,可以插入控件,绘图等等。
void xxxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    //不需要特许处理的表项,返回
    if(index.column()!=0&&index.column()!=3)
    {
        return QStyledItemDelegate::paint(painter,option,index);
    }
    //保存一下原本的painter便于操作完后恢复,减少影响
    painter->save();
    if(index.column()==0)
    {//第一栏设置图片
        painter->drawImage(option.rect,QImage(":/image/image/icon_14.png"));
    }else
    {//百分比栏
        //按照百分比绘制长条和百分比的文字信息。
        int textW = option.fontMetrics.width("100.00%");
	//取出数据
        QString text = index.model()->data(index, Qt::DisplayRole).toString();
        int maxNum = ( (VideoStatisticsModel*)index.model() )->maxNum;
        double percent = text.toDouble();
        QRect optionRect=option.rect;
        int rectMaxW = optionRect.width()-textW;
        int paintRecWidth = 0;
        if(maxNum>0)
            paintRecWidth = (int)percent*rectMaxW/maxNum;
	//画矩形
        painter->fillRect(optionRect.x(),optionRect.y(),paintRecWidth,optionRect.height(),Qt::gray);
        text +="%";
	//后面附加文字
        painter->drawText(optionRect.x()+paintRecWidth,optionRect.y(),textW,optionRect.height(),Qt::AlignCenter,text);
    }
    painter->restore();
}

效果就是上面图这样子,灵活性真的很大,能够实现很完全的自定的显示的界面的东西。看下上面说的两个参考的地址,也举了很多种方案的例子了。

  • 2
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,下面是用Qt自定义表头实现表头下拉框的步骤: 1.创建一个自定义的表头类,继承自QHeaderView。 2.在自定义表头类的构造函数中,创建一个QComboBox控件,并将其添加到表头中。例如,可以使用以下代码实现: ``` MyHeaderView::MyHeaderView(Qt::Orientation orientation, QWidget *parent) : QHeaderView(orientation, parent) { m_comboBox = new QComboBox(this); m_comboBox->setEditable(true); m_comboBox->setMinimumWidth(100); connect(m_comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onComboBoxIndexChanged(int))); } void MyHeaderView::paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const { painter->save(); QHeaderView::paintSection(painter, rect, logicalIndex); if (logicalIndex == m_index) { QRect comboBoxRect = rect.adjusted(4, 4, -4, -4); m_comboBox->setGeometry(comboBoxRect); } painter->restore(); } ``` 其中,m_comboBox是QComboBox的指针成员变量,m_index是当前列的索引号。在paintSection()函数中,先调用父类的paintSection()函数,绘制表头。然后根据当前列的索引号,调整QComboBox的位置和大小。 3.重写mousePressEvent()函数,用于判断用户是否点击了QComboBox控件。例如,可以使用以下代码实现: ``` void MyHeaderView::mousePressEvent(QMouseEvent *event) { QHeaderView::mousePressEvent(event); int index = logicalIndexAt(event->pos()); if (index == m_index) { QRect comboBoxRect = sectionViewportPosition(index).adjusted(4, 4, -4, -4); if (comboBoxRect.contains(event->pos())) { m_comboBox->setGeometry(comboBoxRect); m_comboBox->showPopup(); } } } ``` 其中,logicalIndexAt()函数用于获取用户点击的列索引号,sectionViewportPosition()函数用于获取该列的可视位置。 4.在自定义表头类中添加一个设置下拉框选的函数,例如: ``` void MyHeaderView::setComboBoxItems(const QStringList &items) { m_comboBox->clear(); m_comboBox->addItems(items); } ``` 在该函数中,使用QComboBox的clear()函数清空选,然后使用addItems()函数添加新的选。 5.在自定义表头类中添加一个槽函数,用于处理QComboBox的currentIndexChanged()信号。例如: ``` void MyHeaderView::onComboBoxIndexChanged(int index) { emit comboBoxIndexChanged(m_index, m_comboBox->currentText()); } ``` 在该函数中,使用emit关键字发送comboBoxIndexChanged()信号,该信号包含当前列的索引号和QComboBox的文本内容。 6.在主程序中,创建自定义表头对象,并将其设置为QTableView控件的表头。例如: ``` MyHeaderView *headerView = new MyHeaderView(Qt::Horizontal, ui->tableView); headerView->setComboBoxItems(QStringList() << "Option 1" << "Option 2" << "Option 3"); ui->tableView->setHorizontalHeader(headerView); connect(headerView, SIGNAL(comboBoxIndexChanged(int,QString)), this, SLOT(onComboBoxIndexChanged(int,QString))); ``` 其中,创建自定义表头对象,并设置其下拉框选。然后,将自定义表头对象设置为QTableView控件的水平表头。最后,将comboBoxIndexChanged()信号连接到主程序中的槽函数,用于处理用户在下拉框中选择的选。 以上就是使用Qt自定义表头实现表头下拉框的基本步骤,希望能对您有所帮助。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值