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

版權聲明:若無來源註明, Techie亮博客文章均爲原創。 轉載請以連接形式標明本文標題和地址:
本文標題:QTreeView/QTableView中利用QStandardItem實現複選框三種形態變化     本文地址: http://techieliang.com/2017/12/729/

1. 介紹

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

在item中經過:setCheckable(true);可開啓複選框功能,但默認只支持全選對勾、全不選空白,並且自身的狀態變更不會使父/子節點相應,好比子節點所有選中時父節點不會自動勾選函數

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

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

下面直接上源碼:設計

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實現複選框三種形態變化
相關文章
相關標籤/搜索