Qt中显示复杂列表

转载地址: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
class UsersListItem : public QWidget 
     Q_OBJECT 
public
     explicit UsersListItem(QWidget *parent = 0 ); 
   
     virtual QSize   sizeHint() const 
    
         return QSize( 100 , 48 ); 
    
private
     QLabel * m_labAddress; 
     QLabel * m_labHeaderPic; 
     QLabel * m_labUser; 
   
signals: 
   
public slots: 
   
};


 

然后用

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>
 
class LayerTableModel : public QAbstractTableModel
{
     Q_OBJECT
 
public :
     LayerTableModel(QObject *parent = 0 );
     ~LayerTableModel();
 
     int rowCount( const QModelIndex &parent) const ;
     int columnCount( const QModelIndex &parent) const ;
     QVariant data( const QModelIndex &index, int role) const ;
     QVariant headerData( int section,
         Qt::Orientation orientation,
         int role = Qt::DisplayRole) const ;
     Qt::ItemFlags flags( const QModelIndex &index) const ;
 
     bool setData( const QModelIndex &index, const QVariant &value, int role);
     void deleteItem( int index);
     void addItem(QString &layerName, QImage &thumbnail, bool isShow = true );
     void refreshModel();
     QModelIndex& selecttedIndex( int row);
 
     void setSelecttedRow( int row);
     int getSelecttedRow() const ;
 
 
public slots:
     void changeLayerVisibility( const QModelIndex&);
 
private :
     struct LayerItem
     {
         QString layerName;
         QImage thumbnail;
         float transparence;
         bool isShow;
     };
     QList<layeritem> layerList;
     
     int selectedRow;
 
};
 
#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 ( int i = 0 ; i < 3 ; i++)
     {
         addItem(QString(), image, true );
     }
}
 
LayerTableModel::~LayerTableModel()
{
 
}
 
QVariant LayerTableModel::data( const QModelIndex &index, int role) const
{
     if (!index.isValid())
         return QVariant();
 
     int column = index.column();
     if (column == 0 )
     {
         if (role ==  Qt::CheckStateRole)
         {
             return layerList.at(index.row()).isShow ? Qt::Checked : Qt::Unchecked;
         }
         if (role == Qt::SizeHintRole)
         {
             return QSize( 20 , 50 );
         }
     }
     else
     {
         if (role == Qt::EditRole)
         {
             return QVariant(layerList.at(index.row()).layerName);
         }
         if (role == Qt::DisplayRole)
         {
             return QVariant(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)
         {
             return QSize( 200 , 50 );
         }
         if (role == Qt::TextAlignmentRole)
         {
             return int (Qt::AlignVCenter);
         }
     }
 
     return QVariant();
}
 
int LayerTableModel::rowCount( const QModelIndex &parent) const
{
     return (parent.isValid() && parent.column() != 0 ) ? 0 : layerList.size();
}
 
int LayerTableModel::columnCount( const QModelIndex &parent) const
{
     Q_UNUSED(parent);
     return 2 ;
}
 
QVariant LayerTableModel::headerData( int section, Qt::Orientation orientation, int role) const
{
     if (role == Qt::DisplayRole)
         return QString::number(section);
     //if (role == Qt::DecorationRole)
         //return QVariant::fromValue(services);
     return QAbstractItemModel::headerData(section, orientation, role);
}
 
Qt::ItemFlags LayerTableModel::flags( const QModelIndex &index) const
{
 
     if (!index.isValid())
         return 0 ;
 
     if (index.column() == 0 )
         return Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
 
     return  Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
}
 
bool LayerTableModel::setData( const QModelIndex &index, const
     QVariant &value, int role)
{
     if (!index.isValid())
     {
         return false ;
     }
 
     if (role == Qt::CheckStateRole && value.type() == QVariant::Bool)
     {
         layerList[index.row()].isShow = value.toBool();
         emit(dataChanged(index, index));
         return true ;
     }
     if (role == Qt::EditRole && index.column() == 1 )
     {
         layerList[index.row()].layerName = value.toString();
         emit(dataChanged(index, index));
         return true ;
     }
     return false ;;
}
 
void LayerTableModel::changeLayerVisibility( const QModelIndex& index)
{
     if (index.isValid()&&index.column() == 0 )
     {
         setData(index, !(layerList.at(index.row()).isShow), Qt::CheckStateRole);
     }
}
 
void LayerTableModel::deleteItem( int index)
{
     QList<layeritem>::iterator it = layerList.begin();
     layerList.erase(it + index);
}
 
void LayerTableModel::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( int row)
{
     return this ->createIndex(row, 1 );
}
 
void LayerTableModel::setSelecttedRow( int row)
{
     selectedRow = row;
}
 
int LayerTableModel::getSelecttedRow() const
{
     return selectedRow;
}
</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>
 
class LayerItemDelegate : public QStyledItemDelegate
{
     Q_OBJECT
 
public :
     LayerItemDelegate(QObject *parent= 0 );
     ~LayerItemDelegate();
 
 
     void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const ;
     QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
         const QModelIndex &index) const ;
     bool editorEvent(QEvent * event,
         QAbstractItemModel * model,
         const QStyleOptionViewItem & option,
         const QModelIndex & index);
     void setEditorData(QWidget *editor, const QModelIndex &index) const ;
     void setModelData(QWidget *editor, QAbstractItemModel *model,
         const QModelIndex &index) const ;
     void updateEditorGeometry(QWidget *editor,
         const QStyleOptionViewItem &option, const QModelIndex &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 ( int i = 0 ; i < 200 ; i++)
     for ( int j = 0 ; j < 200 ; j++)
     {
         int tmpX = i % 10 ;
         int tmpY = 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()
{
 
}
 
 
 
void LayerItemDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & 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;
         int x = rect.x() + 10 ;
         int y = 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,
     const QStyleOptionViewItem & option,
     const QModelIndex & index)
{
     return false ;
}
 
QWidget *LayerItemDelegate::createEditor(QWidget *parent,
     const QStyleOptionViewItem &option,
     const QModelIndex &index) const
{
     qDebug() << createEditor;
     if (index.column() == 1 ) // value column
     {
         QLineEdit* edit = new QLineEdit(parent);
         edit->setFixedHeight( 33 );
         edit->setContentsMargins( 48 , 15 , 50 , 0 );
         return edit;
     }
     else return 0 // no editor attached
}
 
void LayerItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
     QString value = index.model()->data(index, Qt::EditRole).toString();
 
     QLineEdit *edit = static_cast<qlineedit*>(editor);
     edit->setText(value);
     qDebug() << setEditorData;
}
 
void LayerItemDelegate::updateEditorGeometry(QWidget *editor,
     const QStyleOptionViewItem &option, const QModelIndex & index ) const
{
     editor->setGeometry(option.rect);
}
 
void LayerItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
     const QModelIndex &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
 
class LayerTableView : public QTableView
{
     Q_OBJECT
 
public :
     LayerTableView(QWidget *parent = 0 );
     ~LayerTableView();
     void setLayerSize(QSize s);
 
public slots:
     void addNewLayer();
     void deleteLayer();
 
protected :
     void mouseMoveEvent(QMouseEvent * event);
     void contextMenuEvent(QContextMenuEvent * event);
 
private :
     LayerItemDelegate *delegate;
     LayerTableModel *model;
     QSize layerSize;
 
private slots:
     void itemClicked( const QModelIndex&);
 
};
 
#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 = new LayerItemDelegate();
     model = new LayerTableModel();
     
     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( const QModelIndex&)), this , SLOT(itemClicked( const QModelIndex&)));
}
 
LayerTableView::~LayerTableView()
{
 
}
 
void LayerTableView::mouseMoveEvent(QMouseEvent * event)
{
 
}
 
 
 
void LayerTableView::contextMenuEvent(QContextMenuEvent * event)
{
 
     QMenu *pMenu = new QMenu( this );
     QAction *pAddGroupAct = new QAction(tr(Delete), pMenu);
     pMenu->addAction(pAddGroupAct);
     pMenu->popup(mapToGlobal(event->pos()));
 
}
 
void LayerTableView::addNewLayer()
{
     model->addItem(QString(), QImage(layerSize, QImage::Format_RGB32), true );
     //model->addItem(QString(), QImage(images\sample.jpg), true);
     model->refreshModel();
     this ->resizeRowsToContents();
}
 
void LayerTableView::itemClicked( const QModelIndex& 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.
         else if (index.column() == 1 )
         {
             model->setSelecttedRow(index.row());
         }
     }
}
 
void LayerTableView::deleteLayer()
{
     model->deleteItem(model->getSelecttedRow());
     model->refreshModel();
 
     QModelIndex tmp = model->selecttedIndex( 0 );
     this ->selectionModel()->select(tmp, QItemSelectionModel::Select);
}
 
void LayerTableView::setLayerSize(QSize s)
{
     layerSize = s;
}


 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值