1. 程式人生 > >QTreeView/QTableView中利用QStandardItem實現復選框三種形態變化

QTreeView/QTableView中利用QStandardItem實現復選框三種形態變化

通知 發生 efi 全部 取消 -i www. stat post

版權聲明:若無來源註明,Techie亮博客文章均為原創。 轉載請以鏈接形式標明本文標題和地址:
本文標題:QTreeView/QTableView中利用QStandardItem實現復選框三種形態變化 本文地址:http://techieliang.com/2017/12/729/ 文章目錄
  • 1. 介紹
  • 2. 源碼
  •  2.1. using_checkbox_item.h
  •  2.2. using_checkbox_item.cpp
  • 3. 說明

1. 介紹

復選框有三種形態:全選對勾、全不選空白、半選黑點

在item中通過:setCheckable(true);可開啟復選框功能,但默認只支持全選對勾、全不選空白,而且自身的狀態變動不會使父/子節點相應,比如子節點全部選中時父節點不會自動勾選

下面你提供一個完整的UsingCheckboxItem類,此類繼承自QStandardItem,實現了復選框三種狀態的使用。類內容很純粹並未增加其他設置,僅為復選框實現。

註意,此方式讓一個item調用了其父節點及子節點的data和setdata兩個方法,若不符合設計要求,可仿照此方式在model中重現

下面直接上源碼:

2. 源碼

2.1. using_checkbox_item.h

  1. /**
  2. * @file using_checkbox_item.h
  3. * @brief 本文件包含支持復選框item類聲明。
  4. * @version 1.0.0.0
  5. * @date 2017.12.18
  6. * @author Techie亮
  7. */
  8. #ifndef _H_USINGCHECKBOXITEM_
  9. #define _H_USINGCHECKBOXITEM_
  10. #include <QStandardItem>
  11. #include <QString>
  12. /**
  13. * @brief 支持復選框item類
  14. * 支持復選框三態轉變-全選對勾、全不選空白、半選黑點
  15. * 子類會自動通知父子節點item,若不符合設計需要可仿照此方式在model中的setDate重現
  16. */
  17. class UsingCheckboxItem : public QStandardItem {
  18. public:
  19. /**
  20. * @brief 構造函數
  21. * @param item顯示內容
  22. */
  23. explicit UsingCheckboxItem(const QString &text);
  24. /**
  25. * @brief setData重寫
  26. * @param value data值
  27. * @param role data類型
  28. */
  29. virtual void setData(const QVariant &value, int role = Qt::UserRole + 1);
  30. };
  31. #endif // _H_USINGCHECKBOXITEM_

2.2. using_checkbox_item.cpp

  1. #include "using_checkbox_item.h"
  2. //構造函數
  3. UsingCheckboxItem::UsingCheckboxItem(const QString &text)
  4. : QStandardItem(text) {
  5. setCheckable(true);
  6. }
  7. //setData重寫
  8. void UsingCheckboxItem::setData(const QVariant &value, int role) {
  9. if(role == Qt::CheckStateRole) {//針對復選框變動做操作
  10. Qt::CheckState check_state = (Qt::CheckState)value.toInt();
  11. QString mtext=text();
  12. switch (check_state) {
  13. case Qt::Unchecked: {//取消
  14. for(int i = 0, num = rowCount(); i < num; i++) {
  15. child(i)->setData(Qt::Unchecked, Qt::CheckStateRole);
  16. }
  17. //修改內容-必須先修改自己再通知父節點
  18. QStandardItem::setData(value,role);
  19. //通知父節點,我取消了選擇,直接告訴父節點半選即可
  20. if(parent())parent()->setData(Qt::PartiallyChecked, role);
  21. }
  22. return;//此事件已完成直接return
  23. case Qt::PartiallyChecked: {//半選
  24. Qt::CheckState current_state = checkState();//當前狀態
  25. int checked_num = 0;//被選擇的數量
  26. int unchecked_num = 0;//未選擇的數量
  27. bool is_partially = false;
  28. Qt::CheckState child_state;
  29. int m_rowCount = rowCount();
  30. //遍歷所有子節點
  31. for(int i = 0; i < m_rowCount; i++) {
  32. child_state = child(i)->checkState();
  33. //子節點半選,則直接半選
  34. switch (child_state) {
  35. case Qt::PartiallyChecked:is_partially = true;break;
  36. case Qt::Unchecked:unchecked_num++;break;
  37. case Qt::Checked:checked_num++;break;
  38. default:checked_num++;break;
  39. }
  40. }
  41. //根據子節點狀態確定當前節點應該設置的狀態
  42. Qt::CheckState now_state;
  43. if(is_partially)
  44. now_state = Qt::PartiallyChecked;
  45. else if(checked_num == m_rowCount)
  46. now_state = Qt::Checked;
  47. else if(unchecked_num == m_rowCount)
  48. now_state = Qt::Unchecked;
  49. else
  50. now_state = Qt::PartiallyChecked;
  51. //修改狀態並通知父節點
  52. if(current_state != now_state) {
  53. //修改內容-必須先修改自己再通知父節點
  54. QStandardItem::setData(now_state,role);
  55. //通知父節點,我的狀態更改,也就是父節點進入半選
  56. if(parent())parent()->setData(Qt::PartiallyChecked, role);
  57. }
  58. }
  59. return;//此事件已完成直接return
  60. case Qt::Checked: {//全選
  61. for(int i = 0, num = rowCount(); i < num; i++) {
  62. child(i)->setData(Qt::Checked, Qt::CheckStateRole);
  63. }
  64. //修改內容-必須先修改自己再通知父節點
  65. QStandardItem::setData(value,role);
  66. //通知父節點,我被選了,也就是父節點進入半選
  67. if(parent()) {
  68. parent()->setData(Qt::PartiallyChecked, role);
  69. }
  70. }
  71. return;//此事件已完成直接return
  72. default://如果出現此情況就是錯了,可以加錯誤處理
  73. break;
  74. }
  75. }
  76. QStandardItem::setData(value,role);
  77. }

3. 說明

  • 重寫了setData方法,但僅對CheckStateRole類型data做了操作,其余類型通過最後的QStandardItem::setData(value,role)直接使用默認方式
  • setData中每個case後均直接return,因為會根據value和父子類情況對實際要使用value做修改,最終賦值給QStandardItem::setData不一定是參數value,所以若不返回,必然會調用最後一樣導致出錯
  • 系統默認只有兩個狀態切換選中和補選中,所以可以借用這個特性,當一個節點狀態修改時都通知其父類為PartiallyChecked部分選中狀態,由父節點自行判斷子節點情況並設置自身狀態
  • 註意一定要先修改自身狀態以後在通知父節點,否則在父節點函數運行過程中自身仍為未修改狀態,會導致判斷錯誤
  • 在PartiallyChecked的case中判斷了一下新舊狀態是否改變,若改變會向上一父節點繼續傳遞消息,不改變則立刻停止減少運算量
  • 若子節點存在PartiallyChecked狀態的,則當前節點一定為PartiallyChecked
  • 註意最頂級item是沒有parent的所以想父節點傳遞消息前一定要判斷parent是否為nullptr
  • 選擇一個節點那麽此節點一定會在全選-不選兩個狀態切換,而部分選擇僅存在於此節點的子節點發生變動,所以全選-不選兩個case直接對所有子節點賦值
轉載請以鏈接形式標明本文標題和地址:Techie亮博客 » QTreeView/QTableView中利用QStandardItem實現復選框三種形態變化

QTreeView/QTableView中利用QStandardItem實現復選框三種形態變化