Qt中显示复杂列表

来源:互联网 发布:软件项目计划安排 编辑:程序博客网 时间:2024/05/17 03:32

来源:http://www.2cto.com/kf/201412/362329.html



提要

最近想要完成的一个项目需要显示一个列表,可以动态增减,可编辑,有checkbox。类似于这样

/

或者这样

/

 

但网上的例子都是这样

/

和这样

/

 

///...

最后实现的效果:

/

 

 

QListWidget解决方案

在Android实现这样的列表是非常简单的,首先定义布局XML,然后再定义一个Adapter就可以了。

Qt中类似的解决方案就是QListWidget。

 

自定义一个Widget类作为Item,比如

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
classUsersListItem : publicQWidget 
    Q_OBJECT 
public
    explicit UsersListItem(QWidget *parent = 0); 
   
    virtual QSize   sizeHint() const 
    
        returnQSize(100,48); 
    
private
    QLabel * m_labAddress; 
    QLabel * m_labHeaderPic; 
    QLabel * m_labUser; 
   
signals: 
   
publicslots: 
   
};


 

然后用

void QListWidget::setItemWidget ( QListWidgetItem * item, QWidget * widget )

将widget作为item显示。

 

这种方法最为简单,但是仔细看下官网的函数说明....

This function should only be used to display static content in the place of a list widget item. If you want to display custom dynamic content or implement a custom editor widget, use QListView and subclass QItemDelegate instead.

 

只能用来显示静态数据,如果要显示动态数据,请使用QListView和QItemDelegate。

 

自定义Model自定义View 自定义Delegate

首先要明白这几个东西的概念和关系

与MVC模式不同,model/view结构没有用于与用户交互的完全独立的组件。一般来讲, view负责把数据展示给用户,也处理用户的输入。为了获得更多的灵性性,交互通过delegagte执行。它既提供输入功能又负责渲染view中的每个数据项。
使用Delegate的原因 Qt中当用到QTreeView和QTableView等用于显示item的视图时,你要编辑一个item用到的编辑工具可能是除了默认文字编辑lineEdit以外的工具,例如button,spinBox,甚至Slider,ProgressBar,也有可能是自定义的widget。所以Qt提供了一个委托类,用来处理View中的数据展示方式。

Qt提供的标准views都使用QItemDelegate的实例来提供编辑功能。它以普通的风格来为每个标准view渲染数据项。这些标准的views包括:QListView,QTableView,QTreeView。所有标准的角色都通过标准views包含的缺省delegate进行处理。一个view使用的delegate可以用itemDelegate()函数取得,而setItemDelegate() 函数可以安装一个定制delegate。


简单的说就是需要自己实现的东西变多了,但是可以定制的地方也就多了。下面主要是贴代码,慎入!

 

首先是model

layertablemodel.h

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#ifndef LAYERLISTMODEL_H
#define LAYERLISTMODEL_H
 
#include <qabstracttablemodel>
#include <qstringlist>
#include <qlist>
#include <qpixmap>
#include <qimage>
#include <qicon>
#include <qdebug>
#include <qitemselectionmodel>
 
classLayerTableModel : publicQAbstractTableModel
{
    Q_OBJECT
 
public:
    LayerTableModel(QObject *parent = 0);
    ~LayerTableModel();
 
    introwCount(constQModelIndex &parent) const;
    intcolumnCount(constQModelIndex &parent) const;
    QVariant data(constQModelIndex &index, introle) const;
    QVariant headerData(intsection,
        Qt::Orientation orientation,
        introle = Qt::DisplayRole) const;
    Qt::ItemFlags flags(constQModelIndex &index) const;
 
    bool setData(constQModelIndex &index, constQVariant &value, introle);
    voiddeleteItem(intindex);
    voidaddItem(QString &layerName, QImage &thumbnail, bool isShow = true);
    voidrefreshModel();
    QModelIndex& selecttedIndex(introw);
 
    voidsetSelecttedRow(introw);
    intgetSelecttedRow() const;
 
 
publicslots:
    voidchangeLayerVisibility(constQModelIndex&);
 
private:
    struct LayerItem
    {
        QString layerName;
        QImage thumbnail;
        floattransparence;
        bool isShow;
    };
    QList<layeritem> layerList;
     
    intselectedRow;
 
};
 
#endif// LAYERLISTMODEL_H
</layeritem></qitemselectionmodel></qdebug></qicon></qimage></qpixmap></qlist></qstringlist></qabstracttablemodel>

layertablemodel.cpp

 

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#include layertablemodel.h
 
LayerTableModel::LayerTableModel(QObject *parent)
: QAbstractTableModel(parent)
{
    QImage image(images\sample.jpg);
    layerList.reserve(3);
    selectedRow = 0;
    for(inti = 0; i < 3; i++)
    {
        addItem(QString(), image, true);
    }
}
 
LayerTableModel::~LayerTableModel()
{
 
}
 
QVariant LayerTableModel::data(constQModelIndex &index, introle) const
{
    if(!index.isValid())
        returnQVariant();
 
    intcolumn = index.column();
    if(column == 0)
    {
        if(role ==  Qt::CheckStateRole)
        {
            returnlayerList.at(index.row()).isShow ? Qt::Checked : Qt::Unchecked;
        }
        if(role == Qt::SizeHintRole)
        {
            returnQSize(20,50);
        }
    }
    else
    {
        if(role == Qt::EditRole)
        {
            returnQVariant(layerList.at(index.row()).layerName);
        }
        if(role == Qt::DisplayRole)
        {
            returnQVariant(layerList.at(index.row()).layerName);
        }
 
        if(role == Qt::DecorationRole)
        {
            if(layerList.at(index.row()).thumbnail.isNull())
            {
                return layerList.at(index.row()).thumbnail;
            }else
            {
                return layerList.at(index.row()).thumbnail.scaledToHeight(40);
 
            }
        }
        if(role == Qt::SizeHintRole)
        {
            returnQSize(200,50);
        }
        if(role == Qt::TextAlignmentRole)
        {
            returnint(Qt::AlignVCenter);
        }
    }
 
    returnQVariant();
}
 
intLayerTableModel::rowCount(constQModelIndex &parent) const
{
    return(parent.isValid() && parent.column() != 0) ? 0: layerList.size();
}
 
intLayerTableModel::columnCount(constQModelIndex &parent) const
{
    Q_UNUSED(parent);
    return2;
}
 
QVariant LayerTableModel::headerData(intsection, Qt::Orientation orientation, introle) const
{
    if(role == Qt::DisplayRole)
        returnQString::number(section);
    //if (role == Qt::DecorationRole)
        //return QVariant::fromValue(services);
    returnQAbstractItemModel::headerData(section, orientation, role);
}
 
Qt::ItemFlags LayerTableModel::flags(constQModelIndex &index) const
{
 
    if(!index.isValid())
        return0;
 
    if(index.column() == 0)
        returnQt::ItemIsEnabled | Qt::ItemIsUserCheckable;
 
    return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
}
 
bool LayerTableModel::setData(constQModelIndex &index, const
    QVariant &value, introle)
{
    if(!index.isValid())
    {
        returnfalse;
    }
 
    if(role == Qt::CheckStateRole && value.type() == QVariant::Bool)
    {
        layerList[index.row()].isShow = value.toBool();
        emit(dataChanged(index, index));
        returntrue;
    }
    if(role == Qt::EditRole && index.column() == 1)
    {
        layerList[index.row()].layerName = value.toString();
        emit(dataChanged(index, index));
        returntrue;
    }
    returnfalse;;
}
 
voidLayerTableModel::changeLayerVisibility(constQModelIndex& index)
{
    if(index.isValid()&&index.column() == 0)
    {
        setData(index, !(layerList.at(index.row()).isShow), Qt::CheckStateRole);
    }
}
 
voidLayerTableModel::deleteItem(intindex)
{
    QList<layeritem>::iterator it = layerList.begin();
    layerList.erase(it + index);
}
 
voidLayerTableModel::addItem(QString &name, QImage &thumb, bool show)
{
    LayerItem item;
    if(name.size() == 0)
    {
        item.layerName = QString(Layer ) + QString::number(layerList.size());
    }else{
        item.layerName = name;
    }
    item.isShow = show;
     
    item.thumbnail = thumb;
    layerList.append(item);
    //this->insertRow()
    //emit(dataChanged(index, index));
    qDebug()<<layerlist.size(); emit=""this-=""void="">rowCount(QModelIndex()));
}
 
QModelIndex& LayerTableModel::selecttedIndex(introw)
{
    returnthis->createIndex(row,1);
}
 
voidLayerTableModel::setSelecttedRow(introw)
{
    selectedRow = row;
}
 
intLayerTableModel::getSelecttedRow() const
{
    returnselectedRow;
}
</layerlist.size();></layeritem>


 

然后是delegate

layeritemdelegate.h

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#ifndef LAYERITEMDELEGATE_H
#define LAYERITEMDELEGATE_H
 
#include <qstyleditemdelegate>
#include <qlineedit>
#include <qdebug>
#include <qpainter>
 
classLayerItemDelegate : publicQStyledItemDelegate
{
    Q_OBJECT
 
public:
    LayerItemDelegate(QObject *parent=0);
    ~LayerItemDelegate();
 
 
    voidpaint(QPainter * painter, constQStyleOptionViewItem & option, constQModelIndex & index) const;
    QWidget *createEditor(QWidget *parent, constQStyleOptionViewItem &option,
        constQModelIndex &index) const;
    bool editorEvent(QEvent * event,
        QAbstractItemModel * model,
        constQStyleOptionViewItem & option,
        constQModelIndex & index);
    voidsetEditorData(QWidget *editor, constQModelIndex &index) const;
    voidsetModelData(QWidget *editor, QAbstractItemModel *model,
        constQModelIndex &index) const;
    voidupdateEditorGeometry(QWidget *editor,
        constQStyleOptionViewItem &option, constQModelIndex &index) const;
 
private:
    QPixmap m_gridPixmap;
};
 
#endif// LAYERITEMDELEGATE_H
</qpainter></qdebug></qlineedit></qstyleditemdelegate>


 

layeritemdelegate.cpp

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include layeritemdelegate.h
 
LayerItemDelegate::LayerItemDelegate(QObject *parent)
    : QStyledItemDelegate(parent)
{
    QImage gridImage(200,200, QImage::Format_RGB32);
    QRgb grey = QColor(204,204,204).rgb();
    QRgb white = QColor(255,255,255).rgb();
    for(inti = 0; i < 200; i++)
    for(intj = 0; j < 200; j++)
    {
        inttmpX = i % 10;
        inttmpY = j % 10;
        if(tmpX < 5)
        {
            gridImage.setPixel(i, j, tmpY < 5? grey : white);
        }
        else
        {
            gridImage.setPixel(i, j, tmpY < 5? white : grey);
        }
    }
 
    m_gridPixmap = QPixmap::fromImage(gridImage);
}
 
LayerItemDelegate::~LayerItemDelegate()
{
 
}
 
 
 
voidLayerItemDelegate::paint(QPainter * painter, constQStyleOptionViewItem & option, constQModelIndex & index) const
{
 
 
    if(index.column() == 1)// value column
    {
        if(option.state & QStyle::State_Selected)
            painter->fillRect(option.rect, option.palette.highlight());
 
        QImage image = qvariant_cast<qimage>(index.data(Qt::DecorationRole));
        //QImage image = index.model()->data(index, Qt::DecorationRole).toString();
        QRect rect = option.rect;
        intx = rect.x() + 10;
        inty = rect.y() + 5;
 
        QBrush brush;
        //Draw grid background
        brush.setTexture(m_gridPixmap);
        painter->fillRect(x, y, 40,40, brush);
 
        //Draw image
        painter->drawImage(x, y, image);
 
        QRect textRect(rect.x() + 60, rect.y(), rect.width() - 60, rect.height());
 
        QString layerName = index.model()->data(index, Qt::DisplayRole).toString();
        QTextOption textOption = Qt::AlignLeft | Qt::AlignVCenter;
        painter->drawText(textRect, layerName, textOption);
 
    }
    else
    {
        QStyledItemDelegate::paint(painter, option, index);
    }
}
 
 
bool LayerItemDelegate::editorEvent(QEvent * event,
    QAbstractItemModel * model,
    constQStyleOptionViewItem & option,
    constQModelIndex & index)
{
    returnfalse;
}
 
QWidget *LayerItemDelegate::createEditor(QWidget *parent,
    constQStyleOptionViewItem &option,
    constQModelIndex &index) const
{
    qDebug() << createEditor;
    if(index.column() == 1)// value column
    {
        QLineEdit* edit = newQLineEdit(parent);
        edit->setFixedHeight(33);
        edit->setContentsMargins(48,15,50,0);
        returnedit;
    }
    elsereturn 0// no editor attached
}
 
voidLayerItemDelegate::setEditorData(QWidget *editor, constQModelIndex &index) const
{
    QString value = index.model()->data(index, Qt::EditRole).toString();
 
    QLineEdit *edit = static_cast<qlineedit*>(editor);
    edit->setText(value);
    qDebug() << setEditorData;
}
 
voidLayerItemDelegate::updateEditorGeometry(QWidget *editor,
    constQStyleOptionViewItem &option, constQModelIndex & index ) const
{
    editor->setGeometry(option.rect);
}
 
voidLayerItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
    constQModelIndex &index) const
{
    qDebug() << setModelData;
    QLineEdit *edit = static_cast<qlineedit*>(editor);
    model->setData(index, edit->text(), Qt::EditRole);
}
 
</qlineedit*></qlineedit*></qimage>


 

最后是view

layertableview.h

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#ifndef LAYERLISTVIEW_H
#define LAYERLISTVIEW_H
 
#include <qtableview>
#include <qmouseevent>
#include <qdebug>
#include <qheaderview>
#include <qstandarditemmodel>
#include <qcontextmenuevent>
#include <qmenu>
#include layertablemodel.h
#include layeritemdelegate.h
 
classLayerTableView : publicQTableView
{
    Q_OBJECT
 
public:
    LayerTableView(QWidget *parent = 0);
    ~LayerTableView();
    voidsetLayerSize(QSize s);
 
publicslots:
    voidaddNewLayer();
    voiddeleteLayer();
 
protected:
    voidmouseMoveEvent(QMouseEvent * event);
    voidcontextMenuEvent(QContextMenuEvent * event);
 
private:
    LayerItemDelegate *delegate;
    LayerTableModel *model;
    QSize layerSize;
 
privateslots:
    voiditemClicked(constQModelIndex&);
 
};
 
#endif// LAYERLISTVIEW_H
</qmenu></qcontextmenuevent></qstandarditemmodel></qheaderview></qdebug></qmouseevent></qtableview>


 

layertableview.cpp

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include layertableview.h
 
LayerTableView::LayerTableView(QWidget *parent)
: QTableView(parent)
{
    delegate = newLayerItemDelegate();
    model = newLayerTableModel();
     
    this->setContentsMargins(0,0,0,0);
    this->setModel(model);
    this->setItemDelegate(delegate);
 
    this->horizontalHeader()->setStretchLastSection(true);
    this->horizontalHeader()->setHighlightSections(false);
    this->setFrameShape(QFrame::NoFrame);
    this->setColumnWidth(0,30);
    this->setColumnWidth(1,170);
    this->verticalHeader()->setVisible(false);
    this->horizontalHeader()->setVisible(false);
    this->resizeColumnsToContents();
    this->resizeRowsToContents();
    /*this->setEditTriggers(QAbstractItemView::NoEditTriggers);
    this->setSelectionBehavior(QAbstractItemView::SelectRows);*/
    this->setMouseTracking(true);//important
 
    //When click on the checkbox it will emit signal twice.Click on the cell emit only once.
    connect(this, SIGNAL(clicked(constQModelIndex&)), this, SLOT(itemClicked(constQModelIndex&)));
}
 
LayerTableView::~LayerTableView()
{
 
}
 
voidLayerTableView::mouseMoveEvent(QMouseEvent * event)
{
 
}
 
 
 
voidLayerTableView::contextMenuEvent(QContextMenuEvent * event)
{
 
    QMenu *pMenu = newQMenu(this);
    QAction *pAddGroupAct = newQAction(tr(Delete), pMenu);
    pMenu->addAction(pAddGroupAct);
    pMenu->popup(mapToGlobal(event->pos()));
 
}
 
voidLayerTableView::addNewLayer()
{
    model->addItem(QString(), QImage(layerSize, QImage::Format_RGB32), true);
    //model->addItem(QString(), QImage(images\sample.jpg), true);
    model->refreshModel();
    this->resizeRowsToContents();
}
 
voidLayerTableView::itemClicked(constQModelIndex& index)
{
    if(index.isValid() )
    {
        //When click in column 0.
        if(index.column() == 0)
        {
            model->changeLayerVisibility(index);
            QModelIndex tmp = model->selecttedIndex(model->getSelecttedRow());
            this->selectionModel()->select(tmp, QItemSelectionModel::Select);
        }
        //When click in column 1.
        elseif (index.column() == 1)
        {
            model->setSelecttedRow(index.row());
        }
    }
}
 
voidLayerTableView::deleteLayer()
{
    model->deleteItem(model->getSelecttedRow());
    model->refreshModel();
 
    QModelIndex tmp = model->selecttedIndex(0);
    this->selectionModel()->select(tmp, QItemSelectionModel::Select);
}
 
voidLayerTableView::setLayerSize(QSize s)
{
    layerSize = s;
}




0 0
原创粉丝点击