Qt中显示复杂列表
来源:互联网 发布:剑灵伪娘数据 编辑:程序博客网 时间:2024/05/17 03:29
提要
最近想要完成的一个项目需要显示一个列表,可以动态增减,可编辑,有checkbox。类似于这样
或者这样
但网上的例子都是这样
和这样
...
最后实现的效果:
QListWidget解决方案
在Android实现这样的列表是非常简单的,首先定义布局XML,然后再定义一个Adapter就可以了。
Qt中类似的解决方案就是QListWidget。
自定义一个Widget类作为Item,比如
- 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
- #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
layertablemodel.cpp
- #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();
- }
- void LayerTableModel::refreshModel()
- {
- beginResetModel();
- endResetModel();
- //emit updateCount(this->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;
- }
然后是delegate
layeritemdelegate.h
- #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
layeritemdelegate.cpp
- #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);
- }
最后是view
layertableview.h
- #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
layertableview.cpp
- #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;
- }
参考
Qt Delgate的使用 简单说明 - http://qimo601.iteye.com/blog/1536444
Qt Model/View 学习笔记 - http://www.cppblog.com/yuanyajie/archive/2007/06/19/26641.html
Model/View Programming - https://qt-project.org/doc/qt-4.7/model-view-programming.html#an-editable-model
Qt实现QQ好友下拉列表 - http://blog.csdn.net/hai200501019/article/details/10283553
QTableView使用自定义委托 - http://www.haogongju.net/art/2811045
- Qt中显示复杂列表
- Qt中显示复杂列表
- Qt中显示复杂列表
- Qt中显示复杂列表
- Qt实现复杂的列表控件
- Qt实现复杂的列表控件
- Qt实现复杂的列表控件
- Qt实现复杂的列表控件
- AlertDilog 显示简单 和 复杂列表
- VUE javascript 复杂列表显示值
- Adnroid开发中ListView使用SimpleAdapter显示复杂列表的问题
- Qt中显示中文
- Qt中显示中文
- Qt 中显示中文
- Qt 中显示中文
- qt中显示中文
- Qt显示笔记本wifi列表 windows
- 【Qt OpenGL教程】12:显示列表
- 解决接口汉字乱码问题
- SQLHlper的认识
- java一些基础面试题总结(转自黑马论坛)
- go语言编译环境安装
- 12.20 沙牛家书 《不负牛市不负沙》
- Qt中显示复杂列表
- IOS中用UIStoryBoard类初始化/跳转控制器
- 博客搬家了
- ruby学习笔记
- Java基础——面向对象
- C++编码规范(1):代码注释
- Leetcode题解--18_Fraction to Recurring Decimal
- ASP.NET后台JS弹框使前台页面样式丢失 解决办法
- 5天学会jaxws-webservice编程第一天