• Qt model/view 理解 2


    这是我对 Qt 的 model/view 内容理解的第二篇 blog,在第一篇文章中,介绍 QTableView 和 QAbstractTableModel,实现显示了对数据源的显示,但是显示的格式和修改的模式都是按照 View 控件的自显示方式。在此,使用 Qt 自带的 QStyledItemDelegate 类实现对特定行 / 列的显示 / 修改模式实现,实现过程中不出现对 item 的代码生成,对 item 的生成由程序自动完成。

    在此同样以《c++ gui programming with Qt4》中的 trackEditor 例子作一讲解。

    在此,我们首先应当考虑以下几个问题:

    1)有一个代理类加到 View 中,处理特定的 View 内容。

    2)代理类要完成以下几项工作:a)当用户修改数据时生成用户要求的控件(用户每次修改数据时在相应的位置都会生成控件,所以当控件用完后,应 del 释放资源)。b)设置在生成的修改控件中显示的内容。c)设置要写到 model 中的数据内容。d)设置当结束修改数据后,View 显示的内容。

    在此我们需要实现以下 4 个类。

    1. /**
    2. @brief 保存显示数据的类。
    3. */
    4. class Track
    5. /**
    6. @brief 继承的委托类。
    7. */
    8. class TrackDelegate : public QStyledItemDelegate
    9. /**
    10. @brief 继承的模型类。
    11. */
    12. class TrackModel : public QAbstractTableModel
    13. /**
    14. @brief 用于组装显示的控件类。
    15. */
    16. class TrackEditor : public QDialog

    在此,Track TrackModel TrackEditor 的功能在 Qt model/view 理解 1 中做过介绍,在此只列出 code,不再过多介绍。在此主要介绍 TrackDelegate。

    Track h 文件

    1. #ifndef TRACK_H
    2. #define TRACK_H
    3. #include
    4. /**
    5. @projectName ItemView
    6. @author qiaowei
    7. @date 2018-12-22
    8. @version 1.0
    9. @description 保存的音频数据,包括音频名称和时长
    10. **/
    11. class Track
    12. {
    13. public:
    14. explicit Track(const QString& title = "", int duration = 0);
    15. QString getTitle() const;
    16. void setTitle(const QString& title);
    17. int getDuration() const;
    18. void setDuration(int duration);
    19. private:
    20. /**
    21. @author qioawei
    22. @date 2018-12-22
    23. @description 音频名称
    24. **/
    25. QString title_;
    26. /**
    27. @author qioawei
    28. @date 2018-12-22
    29. @description 音频时长(单位:秒)
    30. **/
    31. int duration_;
    32. };
    33. #endif // TRACK_H

    Track.cpp

    1. #include "track.h"
    2. Track::Track(const QString &title, int duration) :
    3. title_(title),
    4. duration_(duration)
    5. {
    6. }
    7. QString Track::getTitle() const
    8. {
    9. return title_;
    10. }
    11. void Track::setTitle(const QString &title)
    12. {
    13. title_ = title;
    14. }
    15. int Track::getDuration() const
    16. {
    17. return duration_;
    18. }
    19. void Track::setDuration(int duration)
    20. {
    21. duration_ = duration;
    22. }

    TrackModel.h

    1. #ifndef TRACKMODEL_H#define TRACKMODEL_H
    2. #include
    3. #include
    4. #include
    5. #include "track.h"
    6. #include
    7. /**
    8. @brief 继承的模型类。
    9. */
    10. class TrackModel : public QAbstractTableModel
    11. {
    12. Q_OBJECT
    13. public:
    14. explicit TrackModel(QList* tracks, QObject* parent = 0);
    15. ~TrackModel();
    16. virtual int rowCount(const QModelIndex &parent) const;
    17. virtual int columnCount(const QModelIndex &parent) const;
    18. virtual QVariant data(const QModelIndex &index, int role) const;
    19. virtual bool setData(const QModelIndex &index,
    20. const QVariant &value,
    21. int role);
    22. virtual Qt::ItemFlags flags(const QModelIndex &index) const;
    23. private:
    24. QList* tracks;
    25. };
    26. #endif // TRACKMODEL_H

    TrackEditor h 文件

    1. #ifndef TRACKEDITOR_H#define TRACKEDITOR_H
    2. #include
    3. #include "track.h"
    4. QT_BEGIN_NAMESPACE
    5. class QTableView;
    6. class TrackModel;
    7. class QAbstractTableModel;
    8. QT_END_NAMESPACE
    9. namespace Ui {
    10. class TrackEditor;
    11. }
    12. /**
    13. @brief 用于组装显示的控件类。
    14. */
    15. class TrackEditor : public QDialog
    16. {
    17. Q_OBJECT
    18. public:
    19. explicit TrackEditor(QList* tracks, QWidget *parent = 0);
    20. ~TrackEditor();
    21. private:
    22. Ui::TrackEditor *ui;
    23. QTableView* tableView;
    24. TrackModel* model;
    25. //QAbstractTableModel* model;
    26. };
    27. #endif // TRACKEDITOR_H

    TrackDelegate h 文件

    1. #ifndef TRACKDELEGATE_H#define TRACKDELEGATE_H
    2. #include
    3. #include
    4. QT_BEGIN_NAMESPACE
    5. class QPainter;
    6. QT_END_NAMESPACE
    7. /**
    8. @brief 继承的委托类。
    9. */
    10. class TrackDelegate : public QStyledItemDelegate
    11. {
    12. public:
    13. explicit TrackDelegate(QObject* parent = 0);
    14. ~TrackDelegate();
    15. virtual QWidget* createEditor(QWidget *parent,
    16. const QStyleOptionViewItem &option,
    17. const QModelIndex &index) const;
    18. virtual void setEditorData(QWidget* parent,
    19. const QModelIndex& index) const;
    20. virtual void setModelData(QWidget* editor,
    21. QAbstractItemModel* model,
    22. const QModelIndex& index) const;
    23. virtual void updateEditorGeometry(QWidget* editor,
    24. const QStyleOptionViewItem& option,
    25. const QModelIndex& index) const;
    26. virtual void paint(QPainter* painter,
    27. const QStyleOptionViewItem &option,
    28. const QModelIndex &index) const;
    29. virtual QSize sizeHint(const QStyleOptionViewItem &option,
    30. const QModelIndex &index) const;
    31. private:
    32. bool isRightColumn(const QModelIndex& index, const int column) const;
    33. private slots:
    34. void commitAndCloseEditor();
    35. private:
    36. static const int columnNumber;
    37. };
    38. #endif // TRACKDELEGATE_H

    TrackDelegate cpp 文件

    1. #include "trackdelegate.h"
    2. #include
    3. #include
    4. #include
    5. #include "trackmodel.h"
    6. const int TrackDelegate::columnNumber = 1;
    7. TrackDelegate::TrackDelegate(QObject* parent) :
    8. QStyledItemDelegate(parent)
    9. {
    10. }
    11. TrackDelegate::~TrackDelegate()
    12. {
    13. }
    14. QWidget* TrackDelegate::createEditor(QWidget *parent,
    15. const QStyleOptionViewItem &option,
    16. const QModelIndex &index) const
    17. {
    18. if (isRightColumn(index, TrackDelegate::columnNumber)) {
    19. QTimeEdit *timeEdit = new QTimeEdit(parent);
    20. timeEdit->setDisplayFormat("hh:mm");
    21. //当控件结束编辑内容时,触发释放资源
    22. connect(timeEdit, &QTimeEdit::editingFinished,
    23. this, &TrackDelegate::commitAndCloseEditor);
    24. //int secs = index.model()->data(index, Qt::DisplayRole).toInt();
    25. int secs = index.model()->data(index, Qt::EditRole).toInt();
    26. QTime time(secs / 60, secs % 60);
    27. timeEdit->setTime(time);
    28. return timeEdit;
    29. } else {
    30. return QStyledItemDelegate::createEditor(parent,
    31. option,
    32. index);
    33. }
    34. }
    35. void TrackDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
    36. {
    37. if ( !index.isValid()) {
    38. return;
    39. }
    40. QTimeEdit* timeEditor = qobject_cast(editor);
    41. if ( !timeEditor) {
    42. return;
    43. }
    44. if (isRightColumn(index, TrackDelegate::columnNumber)) {
    45. int secs = index.model()->data(index, Qt::EditRole).toInt();
    46. QTime time(secs / 60, secs % 60);
    47. timeEditor->setTime(time);
    48. } else {
    49. QStyledItemDelegate::setEditorData(editor, index);
    50. }
    51. }
    52. void TrackDelegate::setModelData(QWidget *editor,
    53. QAbstractItemModel *model,
    54. const QModelIndex &index) const
    55. {
    56. if ( !index.isValid()) {
    57. return;
    58. }
    59. QTimeEdit* timeEditor = qobject_cast(editor);
    60. if ( !timeEditor) {
    61. return;
    62. }
    63. if (isRightColumn(index, TrackDelegate::columnNumber)) {
    64. QTime time = timeEditor->time();
    65. int secs = time.hour() * 60 + time.minute();
    66. model->setData(index, secs, Qt::EditRole);
    67. } else {
    68. QStyledItemDelegate::setModelData(editor,
    69. model,
    70. index);
    71. }
    72. }
    73. void TrackDelegate::updateEditorGeometry(QWidget *editor,
    74. const QStyleOptionViewItem &option,
    75. const QModelIndex &index) const
    76. {
    77. Q_UNUSED(index);
    78. editor->setGeometry(option.rect);
    79. }
    80. void TrackDelegate::paint(QPainter *painter,
    81. const QStyleOptionViewItem &option,
    82. const QModelIndex &index) const
    83. {
    84. if (isRightColumn(index, TrackDelegate::columnNumber)) {
    85. int secs = index.model()->data(index, Qt::EditRole).toInt();
    86. QString text = QString("%1:%2")
    87. .arg(secs / 60, 2, 10, QChar('0'))
    88. .arg(secs % 60, 2, 10, QChar('0'));
    89. //获取项风格设置
    90. QStyleOptionViewItem myOption = option;
    91. myOption.displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
    92. painter->drawText(option.rect, text);
    93. } else {
    94. QStyledItemDelegate::paint(painter, option, index);
    95. }
    96. }
    97. QSize TrackDelegate::sizeHint(const QStyleOptionViewItem &option,
    98. const QModelIndex &index) const
    99. {
    100. return option.rect.size();
    101. }
    102. void TrackDelegate::commitAndCloseEditor()
    103. {
    104. QTimeEdit* editor = qobject_cast(sender());
    105. emit commitData(editor);
    106. emit closeEditor(editor);
    107. }
    108. bool TrackDelegate::isRightColumn(const QModelIndex &index,
    109. const int column) const
    110. {
    111. if ( !index.isValid()) {
    112. return false;
    113. }
    114. if (index.column() == column) {
    115. return true;
    116. } else {
    117. return false;
    118. }
    119. }

    createEditor 用于创建用户自己需要的显示数据控件。

    setEditorData 用于设置显示控件中显示的具体数据信息。

    setModelData 用户设置模型的数据,也可理解为当显示的数据发生变化后,用户 update 模型数据,保持显示 / 储存内容一致。

    paint 由用户自己绘制要显示的内容信息(很重要,当你点击时间框修改时间,要改的内容为原显示内容并允许你修改,而不是数据变为 00:00,让你修改)。

    commitAndCloseEditor 创建关于 commitData 和 closeEditor 的信号槽链接,保证当代理控件的数据修改完成后,释放信号,保存数据(保存数据步骤由系统自动完成)。

    在此要求注意内容:

    在 TrackModel 类中的 setData 方法应当注意,data 的值应从 value 得出而不是通过 model 的 data 得出,model 得出的数据是原来保存的,而不是用户修改的。

     

  • 相关阅读:
    Nanoprobes Nanogold标签:助力显示SAP-1 的分布和功能
    [论文阅读笔记15]GNN在多目标跟踪中的应用
    分布式数据库难题(一):数据分区
    [LeetCode84双周赛] [模拟] 6174. 任务调度器 II,[贪心&数学] 6144. 将数组排序的最少替换次数
    人工智能基础第一次作业
    微服务-sentinel详解
    06-vue-routers.js的基本使用,路由从定向,router-link代替a标签及样式,路由嵌套,路由动画
    【RAG 论文】面向知识库检索进行大模型增强的框架 —— KnowledGPT
    【Linux内核性能优化】ulimit(nproc、nofile)
    分布式一致性协议 之 Paxos协议
  • 原文地址:https://blog.csdn.net/weiweiqiao/article/details/133574733