qt利用委托实现tableview 的表格项的自定义显示

qt利用委托QStyledItemDelegate,实现tableview 的表格项的自定义显示。

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

这个tabelview里面插入插控件的部分可以参考一下这个,举例写的挺细的了:http://qimo601.iteye.com/blog/1539147,http://qimo601.iteye.com/blog/1538333
这次举例用的是比较通用的tableview ,tablemodel。首先是数据的model类,那么需要继承一个QAbstractTableModel 需要重写的函数看看文档就知道了,大概就有columnCount,rowCount这两个获取行列数量的,还有两个获取数据的,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();  


效果就是上面图这样子,灵活性真的很大,能够实现很完全的自定的显示的界面的东西。

你可能感兴趣的:(qt)