Qt实现QQ好友下拉列表(用QListView实现,所以还得定义它的Model)
偶然发现Qt有个控件可以实现下拉列表,所以就试着实现一下类似QQ面板的下拉列表,这里主要实现几个功能:
1.可以删除列表中图标
2.可以像qq一样的,把某个分组下的图标转移到另外的分组
3.添加分组
代码里写了注释了,这里就不重复了,下面直接看代码吧。
自定义的数据模型
- struct ListItemData
- {
- QString iconPath;
- QString Name;
- };
- class ListModel:public QAbstractListModel
- {
- Q_OBJECT
- public:
- ListModel(QObject *parent = NULL);
- ~ListModel();
- void init();
- void addItem(ListItemData *pItem);
- QVariant data ( const QModelIndex & index, int role = Qt::DisplayRole ) const ;
- int rowCount ( const QModelIndex & parent = QModelIndex() ) const;
- void deleteItem(int index);
- ListItemData* getItem(int index );
- protected:
- private:
- vector<ListItemData*> m_ItemDataVec;
- };
- <pre name="code" class="cpp">ListModel::ListModel( QObject *parent /*= NULL*/ ):QAbstractListModel(parent)
- {
- init();
- }
- ListModel::~ListModel()
- {
- }
- QVariant ListModel::data( const QModelIndex & index, int role /*= Qt::DisplayRole */ ) const
- {
- if (index.row() > m_ItemDataVec.size())
- {
- return QVariant();
- }
- else
- {
- switch (role)
- {
- case Qt::DisplayRole:
- {
- return m_ItemDataVec[index.row()]->Name;
- }
- break;
- case Qt::DecorationRole:
- {
- return QIcon(m_ItemDataVec[index.row()]->iconPath);
- }
- break;
- case Qt::SizeHintRole:
- {
- return QSize(10,50);
- }
- }
- }
- return QVariant();
- }
- int ListModel::rowCount( const QModelIndex & parent /*= QModelIndex() */ ) const
- {
- return m_ItemDataVec.size();
- }
- void ListModel::init()
- {
- for (int i = 1; i < 26; ++i)
- {
- ListItemData *pItem = new ListItemData;
- pItem->Name = QString::number(i);
- pItem->iconPath = QString(":/QQPanel/Resources/%1.jpg").arg(i);
- QFile Iconfile(pItem->iconPath);
- if (Iconfile.exists())
- {
- m_ItemDataVec.push_back(pItem);
- }
- }
- }
- void ListModel::deleteItem( int index )
- {
- vector<ListItemData*>::iterator it = m_ItemDataVec.begin();
- m_ItemDataVec.erase(it + index);
- }
- void ListModel::addItem( ListItemData *pItem )
- {
- if (pItem)
- {
- this->beginInsertRows(QModelIndex(),m_ItemDataVec.size(),m_ItemDataVec.size() + 1);
- <span style="white-space:pre"> </span>m_ItemDataVec.push_back(pItem);
- <span style="white-space:pre"> </span>this->endInsertRows();
- }
- }
- ListItemData* ListModel::getItem( int index )
- {
- if (index > -1 && index < m_ItemDataVec.size())
- {
- return m_ItemDataVec[index];
- }
- }
- </pre><br>
- <br>
- <pre></pre>
- <h1><a name="t1"></a><br>
- </h1>
- <h1><a name="t2"></a>自定义的列表</h1>
- <div>这个类才是重点,因为这里实现了删除和转移图标的几个重要的函数。</div>
- <pre name="code" class="cpp">class MyListView:public QListView
- {
- Q_OBJECT
- public:
- MyListView(QWidget *parent = NULL);
- ~MyListView();
- void setListMap(map<MyListView*,QString> *pListMap);
- void addItem(ListItemData *pItem);
- protected:
- void contextMenuEvent ( QContextMenuEvent * event );
- private slots:
- void deleteItemSlot(bool bDelete);
- void moveSlot(bool bMove);
- private:
- int m_hitIndex;
- ListModel *m_pModel;
- ////记录分组和分组名字的映射关系,这个值跟QQPanel类中的映射组的值保持一致
- //这里还有一个用处就是在弹出的菜单需要分组的名称
- map<MyListView*,QString> *m_pListMap;
- //记录每个菜单项对应的列表,才能知道要转移到那个分组
- map<QAction*,MyListView*> m_ActionMap;
- };</pre><br>
- <pre name="code" class="cpp">MyListView::MyListView( QWidget *parent /*= NULL*/ ):QListView(parent)
- {
- m_hitIndex = -1;
- m_pModel = new ListModel;
- this->setModel(m_pModel);
- m_pListMap = NULL;
- }
- MyListView::~MyListView()
- {
- }
- void MyListView::contextMenuEvent( QContextMenuEvent * event )
- {
- int hitIndex = this->indexAt(event->pos()).column();
- if (hitIndex > -1)
- {
- QMenu *pMenu = new QMenu(this);
- QAction *pDeleteAct = new QAction(tr("删除"),pMenu);
- pMenu->addAction(pDeleteAct);
- connect(pDeleteAct,SIGNAL(triggered (bool)),this,SLOT(deleteItemSlot(bool)));
- QMenu *pSubMenu = NULL;
- map<MyListView*,QString>::iterator it = m_pListMap->begin();
- for (it;it != m_pListMap->end();++it)
- {
- if (!pSubMenu)
- {
- pSubMenu = new QMenu(tr("转移联系人至") ,pMenu);
- pMenu->addMenu(pSubMenu);
- }
- if (it->first != this)
- {
- QAction *pMoveAct = new QAction( it->second ,pMenu);
- //记录菜单与分组的映射,在moveSlot()响应时需要用到。
- m_ActionMap.insert(pair<QAction*,MyListView*>(pMoveAct,it->first));
- pSubMenu->addAction(pMoveAct);
- connect(pMoveAct,SIGNAL(triggered (bool)),this,SLOT(moveSlot(bool)));
- }
- }
- pMenu->popup(mapToGlobal(event->pos()));
- }
- }
- void MyListView::deleteItemSlot( bool bDelete )
- {
- int index = this->currentIndex().row();
- if (index > -1)
- {
- m_pModel->deleteItem(index);
- }
- }
- void MyListView::setListMap( map<MyListView*,QString> *pListMap )
- {
- m_pListMap = pListMap;
- }
- void MyListView::addItem( ListItemData *pItem )
- {
- m_pModel->addItem(pItem);
- }
- void MyListView::moveSlot( bool bMove )
- {
- QAction *pSender = qobject_cast<QAction*>(sender());
- if (pSender)
- {
- //根据点击的菜单,找到相应的列表,然后才能把图标转移过去
- MyListView *pList = m_ActionMap.find(pSender)->second;
- if (pList)
- {
- int index = this->currentIndex().row();
- ListItemData *pItem = m_pModel->getItem(index);
- pList->addItem(pItem);
- //添加到别的分组,就在原来的分组中删除掉了
- m_pModel->deleteItem(index);
- }
- }
- //操作完了要把这个临时的映射清空
- m_ActionMap.clear();
- }
- </pre><br>
- <h1><a name="t3"></a>自定义的主控件</h1>
- class QQPanel : public QWidget
- {
- Q_OBJECT
- public:
- QQPanel(QWidget *parent = 0, Qt::WFlags flags = 0);
- ~QQPanel();
- protected:
- void contextMenuEvent ( QContextMenuEvent * event );
- protected slots:
- void addGroupSlot(bool addgroup);
- private:
- QToolBox *m_pBox;
- map<MyListView*,QString> *m_pListMap; //记录分组和分组名字的映射关系,好在转移图标时知道转移到那个分组
- };
- QQPanel::QQPanel(QWidget *parent, Qt::WFlags flags)
- : QWidget(parent, flags)
- {
- m_pBox = new QToolBox(this);
- m_pListMap = new map<MyListView*,QString>();
- MyListView *pListView = new MyListView(this);
- pListView->setViewMode(QListView::ListMode);
- pListView->setStyleSheet("QListView{icon-size:40px}");
- m_pBox->addItem(pListView,tr("我的好友"));
- m_pListMap->insert(pair<MyListView*,QString>(pListView,tr("我的好友")));
- MyListView *pListView1 = new MyListView(this);
- pListView1->setViewMode(QListView::ListMode);
- pListView1->setStyleSheet("QListView{icon-size:40px}");
- m_pBox->addItem(pListView1,tr("陌生人"));
- m_pListMap->insert(pair<MyListView*,QString>(pListView1,tr("陌生人")));
- pListView->setListMap(m_pListMap);
- pListView1->setListMap(m_pListMap);
- m_pBox->setFixedWidth(150);
- m_pBox->setMinimumHeight(500);
- this->setMinimumSize(200,500);
- //ui.setupUi(this);
- }
- QQPanel::~QQPanel()
- {
- }
- void QQPanel::contextMenuEvent( QContextMenuEvent * event )
- {
- QMenu *pMenu = new QMenu(this);
- QAction *pAddGroupAct = new QAction(tr("添加分组"),pMenu);
- pMenu->addAction(pAddGroupAct);
- connect(pAddGroupAct,SIGNAL(triggered (bool)),this,SLOT(addGroupSlot(bool)));
- pMenu->popup(mapToGlobal(event->pos()));
- }
- void QQPanel::addGroupSlot( bool addgroup )
- {
- QString name = QInputDialog::getText(this,tr("输入分组名"),tr(""));
- if (!name.isEmpty())
- {
- MyListView *pListView1 = new MyListView(this);
- pListView1->setViewMode(QListView::ListMode);
- pListView1->setStyleSheet("QListView{icon-size:40px}");
- m_pBox->addItem(pListView1,name);
- m_pListMap->insert(pair<MyListView*,QString>(pListView1,name));
- }
- //要确保每个MyListView钟的m_pListMap都是一致的,不然就会有错了。
- //因为弹出的菜单进行转移的时候需要用到
- map<MyListView*,QString>::iterator it = m_pListMap->begin();
- for (it; it != m_pListMap->end(); ++it)
- {
- MyListView* pList = it->first;
- pList->setListMap(m_pListMap);
- }
- }
运行结果
以上三个截图显示了把黑名单里的图标5转移到了我的好友分组里了
当然这个程序算是比较简单的。还不能真正的跟QQ的面板相比,还不能把所有的分组都收起来。以后再慢慢研究怎么实现了,
http://blog.csdn.net/hai200501019/article/details/10283553
Qt实现QQ好友下拉列表(用QListView实现,所以还得定义它的Model)的更多相关文章
- Qt实现 QQ好友列表QToolBox
简述 QToolBox类提供了一个列(选项卡式的)部件条目. QToolBox可以在一个tab列上显示另外一个,并且当前的item显示在当前的tab下面.每个tab都在tab列中有一个索引位置.tab ...
- 基于Qt的相似QQ好友列表抽屉效果的实现
版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/shuideyidi/article/details/30619167 前段时间在忙毕业设计, ...
- Qt实现QQ界面
1.Qt实现QQ界面是通过QToolBox类来实现的,基本结构是:QToolBox里面装QGroupBox,然后QGroupBox里面装QToolButton,设置好相关属性即可 2.定义类继承QTo ...
- js实现打开网页自动弹出添加QQ好友邀请窗口
我们有时进一些网面或专题页面会自动弹出一个加为好友的对话框了,在研究了很久之后发现可以直接使用js来实现,下面我们一起来看js实现打开网页自动弹出添加QQ好友邀请窗口的方法. 第一步.JS脚本 这个是 ...
- 微信sdk分享,苹果手机分享到qq好友和qq空间没有反应
最近线上程序苹果手机进行微信分享时,分享到qq好友和qq空间,无法调用分享程序,从微信跳转到qq后就没有反应了,但是安卓手机分享就没事? 解决:调用微信sdk分享时,分享的url(link)的参数不能 ...
- iOS开发UI篇—使用UItableview完成一个简单的QQ好友列表(一)
iOS开发UI篇—使用UItableview完成一个简单的QQ好友列表(一) 一.项目结构和plist文件 二.实现代码 1.说明: 主控制器直接继承UITableViewController // ...
- java模仿qq好友面板的布局(BoxLayout问题)
.............. JLabel ll = new JLabel(dlg.getNameText() + ":" + dlg.getIPText(), ii[index] ...
- 使用Javascript无限添加QQ好友原理解析
做QQ营销的朋友都知道,QQ加好友是有诸多限制的,IP限制,次数限制,二维码限制,人数限制,使用软件自动加好友会遇到各种各样的问题,很多软件通过模拟人工添加QQ号码,在添加几个之后就会遇到腾讯规则限制 ...
- [iOS基础控件 - 6.9.3] QQ好友列表Demo TableView
A.需求 1.使用plist数据,展示类似QQ好友列表的分组.组内成员显示缩进功能 2.组名使用Header,展示箭头图标.组名.组内人数和上线人数 3.点击组名,伸展.缩回好友组 code so ...
随机推荐
- ExtJS中form提交之后获取返回的json值
simpleForm.form.doAction('submit', { url : 'editUserType', method : 'post', params : '', // 提交成功后执行s ...
- 关闭Outlook的时候使之最小化
Outlook很搓的一点就是只有按‘最小化’按钮的时候才会最小化到托盘,而按‘关闭’按钮Outlook直接被关闭退出.然后经常发现没邮件,结果是因为客户端关掉了. 下面通过插件方式实现关闭后最小化到托 ...
- Oracle游标-循环查询表中数据(表名),并执行
Oralce 表中存有一个字段,该字段存储表名,要把该表中的所有表名查询出来(即表名结果集),且执行结果集from 表名结果集: declare v_ccount ); --定义一个游标变量 curs ...
- AnsiString 在 Delphi 中虽然不可用,但是,在 C++ 中可以用
[C++] C++ Builder 中 Ansi 编码的字符串在Android/iOS程序中显示的问题 呃,这个问题说起来,其实也不麻烦,C++ Builder 本身在 TEncoding 做了处理, ...
- IT第七天 - 类及其属性、方法的理解,断点调试初识,代码优化总结,编程逻辑培养
IT第七天 上午 类 1.对象:是多个实体抽象出来的共同点集合,对象包括:属性(即实体的特征).方法(即尸体的功能作用) 2.程序中,用类来模拟对象 3.类是抽象的,是对象的类型,是将多个拥有相同属性 ...
- ACM高精度加减乘除模板
[转]#include <iostream> #include <string> using namespace std; inline int compare(string ...
- Courses(最大匹配)
Courses Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total S ...
- error: property's synthesized getter follows Cocoa naming convention for returning 'owned' objects
出现这样的情况,主要是属性名中包括 keyword. You can solve this by: Renaming that property: @property (strong, nonato ...
- 【Android 多媒体开发】 MediaPlayer 状态机 接口 方法 解析
作者 : 韩曙亮 转载请著名出处 : http://blog.csdn.net/shulianghan/article/details/38487967 一. MediaPlayer 状态机 介绍 ...
- android FragmentPagerAdapter的“标准”配置
private class ImagePagerAdapter extends FragmentPagerAdapter { public List<ImageItem> ...