天天看點

Qt之實作好友清單

    一直都認為,用最通俗的語言,講解最深刻的技術,是每一個技術交流者應該考慮的事情,今天朋友問我,好友清單該怎麼實作。我想起之前上網查閱的時候,發現網上介紹這塊的内容甚少,而且講解的不夠好,于是,本着互相交流的精神,在這裡講解一下我是怎麼實作QQ好友清單的。

1、Q:關于好友清單到底是QTreeWidget/QTreeView還是QListWidget/QListView的問題?

      A:相信大家初次一看,大部分都認為是QTreeWidget,其實是用QListWidget或者QListView均可簡單實作,在資料多的時候,QListWidget性能會降低,不過,對于好友清單來說,QListWidget足以,并且更加簡單。是以,我繼承的是QListWidget來實作。

2、Q:關于如何實作一個Item具有多種資訊,包括頭像、使用者名、個性簽名等?

      A:該Item其實是一個繼承了QWidget的自定義buddy類,把你所想要的資訊全部在該buddy類裡面布局好,甚至可以加進按鈕,自定義的好處就在于,你想到什麼,就能幹什麼,然後在QListWiget裡面裡通過實作

[cpp]  view plain  copy  

Qt之實作好友清單
Qt之實作好友清單
  1. QListWidgetItem *newItem = new QListWidgetItem();       //建立一個newItem  
  2. this->insertItem(row(currentItem)+tem.count(),newItem); //将該newItem插入到後面  
  3. this->setItemWidget(newItem, buddy); //将buddy賦給該newItem  

[cpp]  view plain  copy

  1. QListWidgetItem *newItem = new QListWidgetItem();       //建立一個newItem  
  2. this->insertItem(row(currentItem)+tem.count(),newItem); //将該newItem插入到後面  
  3. this->setItemWidget(newItem, buddy); //将buddy賦給該newItem  

即可。

3、Q:關于如何實作好友的展開與隐藏?

      A:這部分裡我設定了兩個容器:

[cpp]  view plain  copy  

Qt之實作好友清單
Qt之實作好友清單
  1. QMap<QListWidgetItem*,QListWidgetItem*> groupMap;   // 組容器 - key:項 value:組  
  2. QMap<QListWidgetItem*,bool> isHideMap;//用來判斷該組是否隐藏了  

[cpp]  view plain  copy

  1. QMap<QListWidgetItem*,QListWidgetItem*> groupMap;   // 組容器 - key:項 value:組  
  2. QMap<QListWidgetItem*,bool> isHideMap;//用來判斷該組是否隐藏了  

其中,groupMap用來存放key為項,value為組的資料,比如我增加了一個“我的好友”的組,則存進去是key:我的好友,value:我的好友;接着,在isHideMap存放key:我的好友,value:false,表示預設該組是未展開的;緊接着,如果在“我的好友”裡,我增加了一個好友“逍遙聖帝”,則存進去的是:key:逍遙聖帝,value:我的好友,這樣處理的關鍵是為了儲存好組與好友的關系;最後再利用isHideMap來判斷組的狀态,如果是隐藏,則通過周遊groupMap裡面的好友,使之顯示,否則,反之。

4、Q:關于如何實作美化效果?

      A:直接用QSS就可以了。

下面直接貼出源代碼,我已經在源代碼裡面詳細給每一個關鍵步驟進行了說明,是以就不進行闡述了,相信大家看得懂的,如有不懂可以追加評論,第一時間回複你們,下面是實作一個QQ好友清單的簡單功能,對于其他功能大家好好拓展即可~~

一、首先是實作具有各種資訊的Buddy類:

personListBuddy.h

[cpp]  view plain  copy  

Qt之實作好友清單
Qt之實作好友清單
  1. #ifndef PERSONLISTBUDDY_H  
  2. #define PERSONLISTBUDDY_H  
  3. #include <QWidget>  
  4. #include <QLabel>  
  5. #include <QEvent>  
  6. //自定義資訊Item類  
  7. class personListBuddy : public QWidget  
  8. {  
  9.     Q_OBJECT  
  10. public:  
  11.     explicit personListBuddy(QWidget *parent = 0);  
  12.     void initUi();//初始化Ui  
  13.     QWidget *head;  //頭像  
  14.     QLabel *name;  //使用者名  
  15.     QLabel *sign;  //個性簽名  
  16.     QString headPath;//頭像路徑  
  17.     bool eventFilter(QObject *obj, QEvent *event);//事件過濾器  
  18. signals:  
  19. public slots:  
  20. };  
  21. #endif // PERSONLISTBUDDY_H  

[cpp]  view plain  copy

  1. #ifndef PERSONLISTBUDDY_H  
  2. #define PERSONLISTBUDDY_H  
  3. #include <QWidget>  
  4. #include <QLabel>  
  5. #include <QEvent>  
  6. //自定義資訊Item類  
  7. class personListBuddy : public QWidget  
  8. {  
  9.     Q_OBJECT  
  10. public:  
  11.     explicit personListBuddy(QWidget *parent = 0);  
  12.     void initUi();//初始化Ui  
  13.     QWidget *head;  //頭像  
  14.     QLabel *name;  //使用者名  
  15.     QLabel *sign;  //個性簽名  
  16.     QString headPath;//頭像路徑  
  17.     bool eventFilter(QObject *obj, QEvent *event);//事件過濾器  
  18. signals:  
  19. public slots:  
  20. };  
  21. #endif // PERSONLISTBUDDY_H  

personListBuddy.cpp

[cpp]  view plain  copy  

Qt之實作好友清單
Qt之實作好友清單
  1. #include "personlistbuddy.h"  
  2. #include <QPainter>  
  3. personListBuddy::personListBuddy(QWidget *parent) :  
  4.     QWidget(parent)  
  5. {  
  6.     initUi();  
  7. }  
  8. //初始化Ui  
  9. void personListBuddy::initUi()  
  10. {  
  11.     //初始化  
  12.     head=new QWidget(this);  
  13.     name=new QLabel(this);  
  14.     sign=new QLabel(this);  
  15.     //設定頭像大小  
  16.     head->setFixedSize(40,40);  
  17.     //設定個性簽名字型為灰色  
  18.     QPalette color;  
  19.     color.setColor(QPalette::Text,Qt::gray);  
  20.     sign->setPalette(color);  
  21.     //布局  
  22.     head->move(7,7);  
  23.     name->move(54,10);  
  24.     sign->move(54,27);  
  25.     //裝載事件過濾器  
  26.     head->installEventFilter(this);  
  27. }  
  28. //事件過濾器,主要是為了讓圖檔能夠全部填充在head裡面  
  29. bool personListBuddy::eventFilter(QObject *obj, QEvent *event)  
  30. {  
  31.     if(obj == head)  
  32.     {  
  33.         if(event->type() == QEvent::Paint)  
  34.         {  
  35.             QPainter painter(head);  
  36.             painter.drawPixmap(head->rect(), QPixmap(headPath));  
  37.         }  
  38.     }  
  39.     return QWidget::eventFilter(obj, event);  
  40. }  

[cpp]  view plain  copy

  1. #include "personlistbuddy.h"  
  2. #include <QPainter>  
  3. personListBuddy::personListBuddy(QWidget *parent) :  
  4.     QWidget(parent)  
  5. {  
  6.     initUi();  
  7. }  
  8. //初始化Ui  
  9. void personListBuddy::initUi()  
  10. {  
  11.     //初始化  
  12.     head=new QWidget(this);  
  13.     name=new QLabel(this);  
  14.     sign=new QLabel(this);  
  15.     //設定頭像大小  
  16.     head->setFixedSize(40,40);  
  17.     //設定個性簽名字型為灰色  
  18.     QPalette color;  
  19.     color.setColor(QPalette::Text,Qt::gray);  
  20.     sign->setPalette(color);  
  21.     //布局  
  22.     head->move(7,7);  
  23.     name->move(54,10);  
  24.     sign->move(54,27);  
  25.     //裝載事件過濾器  
  26.     head->installEventFilter(this);  
  27. }  
  28. //事件過濾器,主要是為了讓圖檔能夠全部填充在head裡面  
  29. bool personListBuddy::eventFilter(QObject *obj, QEvent *event)  
  30. {  
  31.     if(obj == head)  
  32.     {  
  33.         if(event->type() == QEvent::Paint)  
  34.         {  
  35.             QPainter painter(head);  
  36.             painter.drawPixmap(head->rect(), QPixmap(headPath));  
  37.         }  
  38.     }  
  39.     return QWidget::eventFilter(obj, event);  
  40. }  

二、實作好友清單personList類:

personList.h

[cpp]  view plain  copy  

Qt之實作好友清單
Qt之實作好友清單
  1. #ifndef PERSONLIST_H  
  2. #define PERSONLIST_H  
  3. #include <QListWidget>  
  4. #include <QMenu>  
  5. #include <QMouseEvent>  
  6. #include <QLineEdit>  
  7. //自定義QListWidget  
  8. class personList : public QListWidget //繼承QListWidget,可以使用它本身自帶的函數,更友善  
  9. {  
  10.     Q_OBJECT  
  11. public:  
  12.     explicit personList(QListWidget *parent = 0);  
  13.     void mousePressEvent(QMouseEvent *event);//滑鼠點選事件  
  14.     void contextMenuEvent(QContextMenuEvent*);//菜單事件,為了顯示菜單  
  15.     void initMenu();//初始化菜單  
  16.     QMenu *blankMenu;//點選空白上的菜單  
  17.     QMenu *groupMenu;//點選組上的菜單  
  18.     QMenu *personMenu;//點選人上的菜單  
  19.     QMap<QListWidgetItem*,QListWidgetItem*> groupMap;   // 組容器 - key:項 value:組  
  20.     QMap<QListWidgetItem*,bool> isHideMap;//用來判斷該組是否隐藏了  
  21.     QLineEdit *groupNameEdit;//組的名字,重命名的時候需要用到  
  22.     QListWidgetItem *currentItem;//目前的項  
  23. signals:  
  24. public slots:  
  25.     void slotAddGroup();   //添加組  
  26.     void slotDelGroup();   //删除組  
  27.     void slotAddBuddy();   //添加好友  
  28.     void slotDelBuddy();   //删除好友  
  29.     void slotRename();     //重命名組  
  30.     void slotRenameEditFshed();//命名完成  
  31. };  
  32. #endif // PERSONLIST_H  

[cpp]  view plain  copy

  1. #ifndef PERSONLIST_H  
  2. #define PERSONLIST_H  
  3. #include <QListWidget>  
  4. #include <QMenu>  
  5. #include <QMouseEvent>  
  6. #include <QLineEdit>  
  7. //自定義QListWidget  
  8. class personList : public QListWidget //繼承QListWidget,可以使用它本身自帶的函數,更友善  
  9. {  
  10.     Q_OBJECT  
  11. public:  
  12.     explicit personList(QListWidget *parent = 0);  
  13.     void mousePressEvent(QMouseEvent *event);//滑鼠點選事件  
  14.     void contextMenuEvent(QContextMenuEvent*);//菜單事件,為了顯示菜單  
  15.     void initMenu();//初始化菜單  
  16.     QMenu *blankMenu;//點選空白上的菜單  
  17.     QMenu *groupMenu;//點選組上的菜單  
  18.     QMenu *personMenu;//點選人上的菜單  
  19.     QMap<QListWidgetItem*,QListWidgetItem*> groupMap;   // 組容器 - key:項 value:組  
  20.     QMap<QListWidgetItem*,bool> isHideMap;//用來判斷該組是否隐藏了  
  21.     QLineEdit *groupNameEdit;//組的名字,重命名的時候需要用到  
  22.     QListWidgetItem *currentItem;//目前的項  
  23. signals:  
  24. public slots:  
  25.     void slotAddGroup();   //添加組  
  26.     void slotDelGroup();   //删除組  
  27.     void slotAddBuddy();   //添加好友  
  28.     void slotDelBuddy();   //删除好友  
  29.     void slotRename();     //重命名組  
  30.     void slotRenameEditFshed();//命名完成  
  31. };  
  32. #endif // PERSONLIST_H  

personList.cpp

[cpp]  view plain  copy  

Qt之實作好友清單
Qt之實作好友清單
  1. #include "personlist.h"  
  2. #include <QAction>  
  3. #include <QIcon>  
  4. #include "personlistbuddy.h"  
  5. personList::personList(QListWidget *parent) :  
  6.     QListWidget(parent)  
  7. {  
  8.     setFocusPolicy(Qt::NoFocus);       // 去除item選中時的虛線邊框  
  9.     setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);//水準滾動條關閉  
  10.     initMenu();  
  11. }  
  12. //初始化菜單  
  13. void personList::initMenu()  
  14. {  
  15.     //初始化:  
  16.     blankMenu = new QMenu();  
  17.     groupMenu = new QMenu();  
  18.     personMenu = new QMenu();  
  19.     groupNameEdit=new QLineEdit();  
  20.     QAction *addGroup = new QAction("添加分組", this);  
  21.     QAction *delGroup = new QAction("删除該組", this);  
  22.     QAction *rename = new QAction("重命名", this);  
  23.     QAction *addBuddy = new QAction("添加好友",this);  
  24.     QAction *delBuddy = new QAction("删除好友", this);  
  25.     //設定:  
  26.     groupNameEdit->setParent(this);  //設定父類  
  27.     groupNameEdit->hide(); //設定初始時隐藏  
  28.     groupNameEdit->setPlaceholderText("未命名");//設定初始時的内容  
  29.     //布局:  
  30.     blankMenu->addAction(addGroup);  
  31.     groupMenu->addAction(delGroup);  
  32.     groupMenu->addAction(rename);  
  33.     groupMenu->addAction(addBuddy);  
  34.     personMenu->addAction(delBuddy);  
  35.     //資訊槽:  
  36.     connect(groupNameEdit,SIGNAL(editingFinished()),this,SLOT(slotRenameEditFshed()));  
  37.     connect(addGroup,SIGNAL(triggered()),this,SLOT(slotAddGroup()));  
  38.     connect(delGroup,SIGNAL(triggered()),this,SLOT(slotDelGroup()));  
  39.     connect(rename,SIGNAL(triggered()),this,SLOT(slotRename()));  
  40.     connect(addBuddy,SIGNAL(triggered()),this,SLOT(slotAddBuddy()));  
  41.     connect(delBuddy,SIGNAL(triggered()),this,SLOT(slotDelBuddy()));  
  42. }  
  43. //滑鼠點選事件  
  44. void personList::mousePressEvent(QMouseEvent *event)  
  45. {  
  46.     QListWidget::mousePressEvent(event); // 如果不調用基類mousePressEvent,item被select會半天不響應,調用父類,讓QSS起效,因為QSS基于父類QListWidget,子類就是子視窗,就是最上層視窗,是覆寫在父視窗上的,是以先于父視窗捕獲消息  
  47.     //防止一種特殊情況:給新item命名、點選其他item或空白處時,指向新item的currentItem被賦予其他item  
  48.     if(groupNameEdit->isVisible() && !(groupNameEdit->rect().contains(event->pos())))  
  49.     {  
  50.         if(groupNameEdit->text()!=NULL)  
  51.             currentItem->setText(groupNameEdit->text());  
  52.         groupNameEdit->setText("");  
  53.         groupNameEdit->hide();  
  54.     }  
  55.     currentItem = this->itemAt(mapFromGlobal(QCursor::pos()));//滑鼠位置的Item,不管右鍵左鍵都擷取  
  56.     if(event->button()==Qt::LeftButton && currentItem!=NULL && currentItem==groupMap.value(currentItem))//如果點選的左鍵并且是點選的是組  
  57.     {  
  58.         if(isHideMap.value(currentItem))                                  //如果先前是隐藏,則顯示  
  59.         {  
  60.             foreach(QListWidgetItem* subItem, groupMap.keys(currentItem))//周遊組的對應的項(包括自身和好友)  
  61.                 if(subItem!=currentItem)                                 //如果是組的話不進行處理  
  62.                 {  
  63.                     subItem->setHidden(false);                            //好友全部顯示  
  64.                 }  
  65.             isHideMap.insert(currentItem,false);                          //設定該組為顯示狀态  
  66.             currentItem->setIcon(QIcon(":/arrowDown"));  
  67.         }  
  68.         else                                                             //否則,先前是顯示,則隐藏  
  69.         {  
  70.             foreach(QListWidgetItem* subItem, groupMap.keys(currentItem))//周遊組的對應的項(包括自身和好友)  
  71.                 if(subItem!=currentItem)                                 //如果是組的話不進行處理  
  72.                 {  
  73.                     subItem->setHidden(true);                            //好友全部隐藏  
  74.                 }  
  75.              isHideMap.insert(currentItem,true);                          //設定該組為隐藏狀态  
  76.              currentItem->setIcon(QIcon(":/arrowRight"));  
  77.         }  
  78.     }  
  79. }  
  80. //菜單事件,為了顯示菜單,點選滑鼠右鍵響應,滑鼠點選事件mousePressEvent優先于contextMenuEvent  
  81. void personList::contextMenuEvent(QContextMenuEvent *event)  
  82. {  
  83.     QListWidget::contextMenuEvent(event);           //調用基類事件  
  84.     if(currentItem==NULL)                           //如果點選到的是空白處  
  85.     {  
  86.         blankMenu->exec(QCursor::pos());  
  87.         return;  
  88.     }  
  89.     if(currentItem==groupMap.value(currentItem))    // 如果點選到的是組  
  90.         groupMenu->exec(QCursor::pos());  
  91.     else                                            //否則點選到的是好友  
  92.         personMenu->exec(QCursor::pos());  
  93. }  
  94. //添加組  
  95. void personList::slotAddGroup()  
  96. {  
  97.     QListWidgetItem *newItem=new QListWidgetItem(QIcon(":/arrowRight"),"未命名");    //建立一個Item  
  98.     newItem->setSizeHint(QSize(this->width(),25));//設定寬度、高度  
  99.     this->addItem(newItem);         //加到QListWidget中  
  100.     groupMap.insert(newItem,newItem);//加到容器groupMap裡,key和value都為組  
  101.     isHideMap.insert(newItem,true);  //設定該組隐藏狀态  
  102.     groupNameEdit->raise();  
  103.     groupNameEdit->setText(tr("未命名")); //設定預設内容  
  104.     groupNameEdit->selectAll();        //設定全選  
  105.     groupNameEdit->setGeometry(this->visualItemRect(newItem).left()+15,this->visualItemRect(newItem).top()+1,this->visualItemRect(newItem).width(),this->visualItemRect(newItem).height()-2);//出現的位置  
  106.     groupNameEdit->show();              //顯示  
  107.     groupNameEdit->setFocus();          //擷取焦點  
  108.     currentItem = newItem;     // 因為要給group命名,是以目前的currentItem設為該group  
  109. }  
  110. //删除組  
  111. void personList::slotDelGroup()  
  112. {  
  113.     foreach(QListWidgetItem* item, groupMap.keys(currentItem))  //周遊該組的所有好友和自身的組  
  114.     {  
  115.         groupMap.remove(item);   //移除  
  116.         delete item;   //删除  
  117.     }  
  118.     isHideMap.remove(currentItem); //移除  
  119. }  
  120. //重命名  
  121. void personList::slotRename()  
  122. {  
  123.     groupNameEdit->raise();  
  124.     groupNameEdit->setGeometry(this->visualItemRect(currentItem).left()+15,this->visualItemRect(currentItem).top()+1,this->visualItemRect(currentItem).width(),this->visualItemRect(currentItem).height()-2);//出現的位置  
  125.     groupNameEdit->setText(currentItem->text());   //擷取該組名内容  
  126.     groupNameEdit->show();                        //顯示  
  127.     groupNameEdit->selectAll();                   //全選  
  128.     groupNameEdit->setFocus();                        //擷取焦點  
  129. }  
  130. //添加好友,主要是為了測試功能,實際工程裡可以改成動态讀取資料庫進行添加好友  
  131. void personList::slotAddBuddy()  
  132. {  
  133.     personListBuddy *buddy=new personListBuddy();   //建立一個自己定義的資訊類  
  134.     buddy->headPath=":/head";                          //設定頭像路徑  
  135.     buddy->name->setText("逍遙聖帝");                  //設定使用者名  
  136.     buddy->sign->setText("用通俗的語言,講深刻的技術。");   //設定個性簽名  
  137.     QList<QListWidgetItem*> tem = groupMap.keys(currentItem);//目前組對應的項(包括組本身和好友)複制給tem  
  138.     //關鍵代碼  
  139.     QListWidgetItem *newItem = new QListWidgetItem();       //建立一個newItem  
  140.     this->insertItem(row(currentItem)+tem.count(),newItem); //将該newItem插入到後面  
  141.     this->setItemWidget(newItem, buddy); //将buddy賦給該newItem  
  142.     groupMap.insert(newItem,currentItem);   //加進容器,key為好友,value為組  
  143.     if(isHideMap.value(currentItem))          //如果該組是隐藏,則加進去的好友設定為隐藏  
  144.         newItem->setHidden(true);  
  145.     else                                      //否則,該好友設定為顯示  
  146.         newItem->setHidden(false);  
  147. }  
  148. //删除好友  
  149. void personList::slotDelBuddy()  
  150. {  
  151.     groupMap.remove(currentItem);  //移除該好友  
  152.     delete currentItem;            //删除  
  153. }  
  154. //重命名完成  
  155. void personList::slotRenameEditFshed()  
  156. {  
  157.     if(groupNameEdit->text()!=NULL)      //如果重命名編輯框不為空  
  158.         currentItem->setText(groupNameEdit->text());  //更新組名  
  159.     groupNameEdit->setText("");  
  160.     groupNameEdit->hide();  //隐藏重命名編輯框  
  161. }  

[cpp]  view plain  copy

  1. #include "personlist.h"  
  2. #include <QAction>  
  3. #include <QIcon>  
  4. #include "personlistbuddy.h"  
  5. personList::personList(QListWidget *parent) :  
  6.     QListWidget(parent)  
  7. {  
  8.     setFocusPolicy(Qt::NoFocus);       // 去除item選中時的虛線邊框  
  9.     setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);//水準滾動條關閉  
  10.     initMenu();  
  11. }  
  12. //初始化菜單  
  13. void personList::initMenu()  
  14. {  
  15.     //初始化:  
  16.     blankMenu = new QMenu();  
  17.     groupMenu = new QMenu();  
  18.     personMenu = new QMenu();  
  19.     groupNameEdit=new QLineEdit();  
  20.     QAction *addGroup = new QAction("添加分組", this);  
  21.     QAction *delGroup = new QAction("删除該組", this);  
  22.     QAction *rename = new QAction("重命名", this);  
  23.     QAction *addBuddy = new QAction("添加好友",this);  
  24.     QAction *delBuddy = new QAction("删除好友", this);  
  25.     //設定:  
  26.     groupNameEdit->setParent(this);  //設定父類  
  27.     groupNameEdit->hide(); //設定初始時隐藏  
  28.     groupNameEdit->setPlaceholderText("未命名");//設定初始時的内容  
  29.     //布局:  
  30.     blankMenu->addAction(addGroup);  
  31.     groupMenu->addAction(delGroup);  
  32.     groupMenu->addAction(rename);  
  33.     groupMenu->addAction(addBuddy);  
  34.     personMenu->addAction(delBuddy);  
  35.     //資訊槽:  
  36.     connect(groupNameEdit,SIGNAL(editingFinished()),this,SLOT(slotRenameEditFshed()));  
  37.     connect(addGroup,SIGNAL(triggered()),this,SLOT(slotAddGroup()));  
  38.     connect(delGroup,SIGNAL(triggered()),this,SLOT(slotDelGroup()));  
  39.     connect(rename,SIGNAL(triggered()),this,SLOT(slotRename()));  
  40.     connect(addBuddy,SIGNAL(triggered()),this,SLOT(slotAddBuddy()));  
  41.     connect(delBuddy,SIGNAL(triggered()),this,SLOT(slotDelBuddy()));  
  42. }  
  43. //滑鼠點選事件  
  44. void personList::mousePressEvent(QMouseEvent *event)  
  45. {  
  46.     QListWidget::mousePressEvent(event); // 如果不調用基類mousePressEvent,item被select會半天不響應,調用父類,讓QSS起效,因為QSS基于父類QListWidget,子類就是子視窗,就是最上層視窗,是覆寫在父視窗上的,是以先于父視窗捕獲消息  
  47.     //防止一種特殊情況:給新item命名、點選其他item或空白處時,指向新item的currentItem被賦予其他item  
  48.     if(groupNameEdit->isVisible() && !(groupNameEdit->rect().contains(event->pos())))  
  49.     {  
  50.         if(groupNameEdit->text()!=NULL)  
  51.             currentItem->setText(groupNameEdit->text());  
  52.         groupNameEdit->setText("");  
  53.         groupNameEdit->hide();  
  54.     }  
  55.     currentItem = this->itemAt(mapFromGlobal(QCursor::pos()));//滑鼠位置的Item,不管右鍵左鍵都擷取  
  56.     if(event->button()==Qt::LeftButton && currentItem!=NULL && currentItem==groupMap.value(currentItem))//如果點選的左鍵并且是點選的是組  
  57.     {  
  58.         if(isHideMap.value(currentItem))                                  //如果先前是隐藏,則顯示  
  59.         {  
  60.             foreach(QListWidgetItem* subItem, groupMap.keys(currentItem))//周遊組的對應的項(包括自身和好友)  
  61.                 if(subItem!=currentItem)                                 //如果是組的話不進行處理  
  62.                 {  
  63.                     subItem->setHidden(false);                            //好友全部顯示  
  64.                 }  
  65.             isHideMap.insert(currentItem,false);                          //設定該組為顯示狀态  
  66.             currentItem->setIcon(QIcon(":/arrowDown"));  
  67.         }  
  68.         else                                                             //否則,先前是顯示,則隐藏  
  69.         {  
  70.             foreach(QListWidgetItem* subItem, groupMap.keys(currentItem))//周遊組的對應的項(包括自身和好友)  
  71.                 if(subItem!=currentItem)                                 //如果是組的話不進行處理  
  72.                 {  
  73.                     subItem->setHidden(true);                            //好友全部隐藏  
  74.                 }  
  75.              isHideMap.insert(currentItem,true);                          //設定該組為隐藏狀态  
  76.              currentItem->setIcon(QIcon(":/arrowRight"));  
  77.         }  
  78.     }  
  79. }  
  80. //菜單事件,為了顯示菜單,點選滑鼠右鍵響應,滑鼠點選事件mousePressEvent優先于contextMenuEvent  
  81. void personList::contextMenuEvent(QContextMenuEvent *event)  
  82. {  
  83.     QListWidget::contextMenuEvent(event);           //調用基類事件  
  84.     if(currentItem==NULL)                           //如果點選到的是空白處  
  85.     {  
  86.         blankMenu->exec(QCursor::pos());  
  87.         return;  
  88.     }  
  89.     if(currentItem==groupMap.value(currentItem))    // 如果點選到的是組  
  90.         groupMenu->exec(QCursor::pos());  
  91.     else                                            //否則點選到的是好友  
  92.         personMenu->exec(QCursor::pos());  
  93. }  
  94. //添加組  
  95. void personList::slotAddGroup()  
  96. {  
  97.     QListWidgetItem *newItem=new QListWidgetItem(QIcon(":/arrowRight"),"未命名");    //建立一個Item  
  98.     newItem->setSizeHint(QSize(this->width(),25));//設定寬度、高度  
  99.     this->addItem(newItem);         //加到QListWidget中  
  100.     groupMap.insert(newItem,newItem);//加到容器groupMap裡,key和value都為組  
  101.     isHideMap.insert(newItem,true);  //設定該組隐藏狀态  
  102.     groupNameEdit->raise();  
  103.     groupNameEdit->setText(tr("未命名")); //設定預設内容  
  104.     groupNameEdit->selectAll();        //設定全選  
  105.     groupNameEdit->setGeometry(this->visualItemRect(newItem).left()+15,this->visualItemRect(newItem).top()+1,this->visualItemRect(newItem).width(),this->visualItemRect(newItem).height()-2);//出現的位置  
  106.     groupNameEdit->show();              //顯示  
  107.     groupNameEdit->setFocus();          //擷取焦點  
  108.     currentItem = newItem;     // 因為要給group命名,是以目前的currentItem設為該group  
  109. }  
  110. //删除組  
  111. void personList::slotDelGroup()  
  112. {  
  113.     foreach(QListWidgetItem* item, groupMap.keys(currentItem))  //周遊該組的所有好友和自身的組  
  114.     {  
  115.         groupMap.remove(item);   //移除  
  116.         delete item;   //删除  
  117.     }  
  118.     isHideMap.remove(currentItem); //移除  
  119. }  
  120. //重命名  
  121. void personList::slotRename()  
  122. {  
  123.     groupNameEdit->raise();  
  124.     groupNameEdit->setGeometry(this->visualItemRect(currentItem).left()+15,this->visualItemRect(currentItem).top()+1,this->visualItemRect(currentItem).width(),this->visualItemRect(currentItem).height()-2);//出現的位置  
  125.     groupNameEdit->setText(currentItem->text());   //擷取該組名内容  
  126.     groupNameEdit->show();                        //顯示  
  127.     groupNameEdit->selectAll();                   //全選  
  128.     groupNameEdit->setFocus();                        //擷取焦點  
  129. }  
  130. //添加好友,主要是為了測試功能,實際工程裡可以改成動态讀取資料庫進行添加好友  
  131. void personList::slotAddBuddy()  
  132. {  
  133.     personListBuddy *buddy=new personListBuddy();   //建立一個自己定義的資訊類  
  134.     buddy->headPath=":/head";                          //設定頭像路徑  
  135.     buddy->name->setText("逍遙聖帝");                  //設定使用者名  
  136.     buddy->sign->setText("用通俗的語言,講深刻的技術。");   //設定個性簽名  
  137.     QList<QListWidgetItem*> tem = groupMap.keys(currentItem);//目前組對應的項(包括組本身和好友)複制給tem  
  138.     //關鍵代碼  
  139.     QListWidgetItem *newItem = new QListWidgetItem();       //建立一個newItem  
  140.     this->insertItem(row(currentItem)+tem.count(),newItem); //将該newItem插入到後面  
  141.     this->setItemWidget(newItem, buddy); //将buddy賦給該newItem  
  142.     groupMap.insert(newItem,currentItem);   //加進容器,key為好友,value為組  
  143.     if(isHideMap.value(currentItem))          //如果該組是隐藏,則加進去的好友設定為隐藏  
  144.         newItem->setHidden(true);  
  145.     else                                      //否則,該好友設定為顯示  
  146.         newItem->setHidden(false);  
  147. }  
  148. //删除好友  
  149. void personList::slotDelBuddy()  
  150. {  
  151.     groupMap.remove(currentItem);  //移除該好友  
  152.     delete currentItem;            //删除  
  153. }  
  154. //重命名完成  
  155. void personList::slotRenameEditFshed()  
  156. {  
  157.     if(groupNameEdit->text()!=NULL)      //如果重命名編輯框不為空  
  158.         currentItem->setText(groupNameEdit->text());  //更新組名  
  159.     groupNameEdit->setText("");  
  160.     groupNameEdit->hide();  //隐藏重命名編輯框  
  161. }  

三、美化用到的QSS:

[cpp]  view plain  copy  

Qt之實作好友清單
Qt之實作好友清單
  1. QListWidget{  
  2.     background:white;  
  3.     color:black;  
  4.     border:none;  
  5. }  
  6. QListWidget::item{  
  7.     border:none;  
  8.         height: 54px;  
  9. }  
  10. QListWidget::item:hover{  
  11.     background:rgb(252,240,193)  
  12. }  
  13. QListWidget::item:selected{  
  14.     background:rgb(252,233,161);  
  15.     color:black;  
  16. }  
  17. QScrollBar:vertical {                 
  18.     background:transparent;  
  19.     width:9px;  
  20.     margin: 0px 0px 2px 0px;  
  21. }  
  22. QScrollBar::handle:vertical {  
  23.     background: rgb(195, 195, 195);  
  24.     min-height: 20px;  
  25.     border-radius: 3px;  
  26. }  
  27. QScrollBar::handle:vertical:hover{  
  28.     background:rgba(0,0,0,30%);  
  29. }  
  30. QScrollBar::add-line:vertical {  
  31.     height: 0px;  
  32.     subcontrol-position: bottom;  
  33.     subcontrol-origin: margin;  
  34. }  
  35. QScrollBar::sub-line:vertical {  
  36.     height: 0px;  
  37.     subcontrol-position: top;  
  38.     subcontrol-origin: margin;  
  39. }  

[cpp]  view plain  copy

  1. QListWidget{  
  2.     background:white;  
  3.     color:black;  
  4.     border:none;  
  5. }  
  6. QListWidget::item{  
  7.     border:none;  
  8.         height: 54px;  
  9. }  
  10. QListWidget::item:hover{  
  11.     background:rgb(252,240,193)  
  12. }  
  13. QListWidget::item:selected{  
  14.     background:rgb(252,233,161);  
  15.     color:black;  
  16. }  
  17. QScrollBar:vertical {                 
  18.     background:transparent;  
  19.     width:9px;  
  20.     margin: 0px 0px 2px 0px;  
  21. }  
  22. QScrollBar::handle:vertical {  
  23.     background: rgb(195, 195, 195);  
  24.     min-height: 20px;  
  25.     border-radius: 3px;  
  26. }  
  27. QScrollBar::handle:vertical:hover{  
  28.     background:rgba(0,0,0,30%);  
  29. }  
  30. QScrollBar::add-line:vertical {  
  31.     height: 0px;  
  32.     subcontrol-position: bottom;  
  33.     subcontrol-origin: margin;  
  34. }  
  35. QScrollBar::sub-line:vertical {  
  36.     height: 0px;  
  37.     subcontrol-position: top;  
  38.     subcontrol-origin: margin;  
  39. }  

四、用到的素材:

Qt之實作好友清單
Qt之實作好友清單
Qt之實作好友清單

五、效果圖:

Qt之實作好友清單

繼續閱讀