ChristoF
April 28, 2020, 11:22 a.m.

Отобразить список с вложенным в него еще одним списком

QAbstractListModel, ListView

Доброго времени суток, В QML есть ListView моделью которого является QAbstractListModel в который из интерфейса для обращения к данным передаётся контейнер std::vector(родительский) c полями. Помимо простых типов данных в нем содержится вложенный контейнер std::vector(дочерний). Для того чтобы "показать" в QML элементы родительского контейнера требуется определить методы QAbstractListModel такие как:
rowCount( )
data( )
roleNames( )
А также создать Enum ролей

Для простых типов, таких как string, int, double нет ничего сложного

  1. int DailyModel::rowCount(const QModelIndex &parent) const
  2. {
  3. Q_UNUSED(parent)
  4. return static_cast<int>(m_dailys.size());
  5. }
  6.  
  7. QVariant DailyModel::data(const QModelIndex &index, int role) const
  8. {
  9. if (!index.isValid() || index.row() > rowCount(index)) {
  10. return QVariant();
  11. }
  12. const ns1__dayArc *daily = m_dailys.at(index.row());
  13.  
  14. switch (role) {
  15. case DailyRoles::TimeRole: {
  16. char buffer [80];
  17. struct tm * timeinfo;
  18. timeinfo = localtime (daily->Time);
  19. strftime (buffer,80,"%d/%m/%y %X", timeinfo);
  20. return QString::fromStdString(buffer);
  21. }
  22. case DailyRoles::VbTRole: {
  23. return QVariant::fromValue(*daily->VbT);
  24. }
  25.  
  26. case DailyRoles::StatusRole: {
  27. std::string arr=DailyModel::translator(daily->state);
  28. return QString::fromStdString(arr);
  29. }
  30. case DailyRoles::TRole: {
  31. return QVariant::fromValue(*daily->T);
  32. }
  33. case DailyRoles::K_smtRole: {
  34. return QVariant::fromValue(*daily->K_USCOREsmt);
  35. }
  36. default: {
  37. return {};
  38. }
  39. }
  40. }
  41.  
  42. QHash<int, QByteArray> DailyModel::roleNames() const
  43. {
  44. QHash<int, QByteArray> roles;
  45. roles[DailyRoles::TimeRole] = "time";
  46. roles[DailyRoles::StatusRole] = "status";
  47. roles[DailyRoles::VbTRole] = "VbT";
  48. roles[DailyRoles::TRole] = "T";
  49. roles[DailyRoles::K_smtRole] = "K_smt";
  50.  
  51. return roles;
  52. }
  53.  

Но как мне задать роль для std::vector а также вывести его в делегате?

Хочется реализовать что-то подобное

  1. import QtQuick 2.12
  2. import QtQuick.Window 2.12
  3. import QtQuick.Controls 2.5
  4.  
  5. Window {
  6. ListModel{
  7. id: dataModel;
  8.  
  9. ListElement{
  10. color: "skyblue";
  11. text: "one";
  12. texts:[
  13. ListElement{
  14. text: "one_000";
  15. },
  16. ListElement{
  17. text: "one_001";
  18. },
  19. ListElement{
  20. text: "one_002";
  21. }
  22. ]
  23. }
  24. ListElement{
  25. color: "lightgreen";
  26. text: "two";
  27. texts:[
  28. ListElement{
  29. text: "two_000";
  30. },
  31. ListElement{
  32. text: "two_001";
  33. },
  34. ListElement{
  35. text: "two_002";
  36. }
  37. ]
  38. }
  39. ListElement{
  40. color: "orchid";
  41. text: "three";
  42. texts:[
  43. ListElement{
  44. text: "three_000";
  45. },
  46. ListElement{
  47. text: "three_001";
  48. },
  49. ListElement{
  50. text: "three_002";
  51. }
  52. ]
  53. }
  54. }
  55. visible: true
  56. width: 640
  57. height: 480
  58.  
  59. ListView{
  60. id: view;
  61. anchors.fill: parent;
  62. anchors.margins: 10;
  63. spacing: 10;
  64. clip: true;
  65.  
  66. model: dataModel;
  67.  
  68. delegate: Rectangle{
  69. width: view.width;
  70. height: 50;
  71.  
  72. color: model.color;
  73. Row{
  74. anchors.centerIn: parent;
  75. anchors.margins: 10;
  76. spacing: 10;
  77.  
  78. Text{
  79. renderType: Text.NativeRendering;
  80. font.pointSize: 15;
  81. text: model.text;
  82. }
  83. ComboBox{
  84. model: texts;
  85.  
  86. }
  87. }
  88. }
  89. }
  90. }

Буду благодарен за помощь

2

Do you like it? Share on social networks!

5
Evgenii Legotckoi
  • April 28, 2020, 12:55 p.m.

Добрый день

В этом случае самым адекватным решением, которое напрашивается само по себе, это попробовать возвращать вложенную модель вместо вектора, а в делегате ListElement родительской модели уже отображать вложенную модель ListModel

    ChristoF
    • April 28, 2020, 3:10 p.m.
    • (edited)

    На данный момент придумал полумеру решения данного вопроса, сделать делегаты RadioDelegate внутри котороых вложенный Reapiter,
    при checked отправляю во вложенную модель currentIndex. В результате вложенная модель при каждом клике переопределяется и выводит список соответсвующий данному делегату. Минусом данного подхода является, то что я не могу основываясь на вложеном списке выводить в главный список какую либо информацию (Например количество строк списка), так как при изменении модели вложенного списка он меняется во всех делегатах

    Говоря "возвращать вложенную модель вместо вектора" вы имеете ввиду в методе data() установить роль возвращающую модель?

    1. QVariant DailyModel::data(const QModelIndex &index, int role) const
    2. {
    3. if (!index.isValid() || index.row() > rowCount(index)) {
    4. return QVariant();
    5. }
    6. const ns1__dayArc *daily = m_dailys.at(index.row());
    7.  
    8. switch (role) {
    9. case DailyRoles::VectorRole: {
    10. return QVariant::fromValue(/* MyModel */); // либо другая реализация
    11. }
    12. default: {
    13. return {};
    14. }
    15. }
    16. }
      Evgenii Legotckoi
      • April 28, 2020, 3:12 p.m.

      Да, я думаю, что стоит попробовать такое сделать. Были бы это классические виджеты, то именно это я бы и посоветовал, как наиболее адекватное решение, а с QML, наверное, будет посложнее из-за необходимости регистрации мета-типов... интересный вопрос сам по себе.

        ChristoF
        • April 28, 2020, 3:19 p.m.

        Если возможно, можете подсказать "правильный синтаксис" присвоения ролям значения модели? Мой вариант меня не до конца устраивает и я все же хотел бы выводить вложенный каждый список для всех делегатов одновреммено, так как значения Reapiter-ов я хотел бы использовать в главной моделе

          Evgenii Legotckoi
          • April 28, 2020, 3:21 p.m.

          Самому нужно подумать, с наскоку это не сделать, да из головы даже не знаю...

            Comments

            Only authorized users can post comments.
            Please, Log in or Sign up
            • Last comments
            • AK
              April 1, 2025, 11:41 a.m.
              Добрый день. В данный момент работаю над проектом, где необходимо выводить звук из программы в определенное аудиоустройство (колонки, наушники, виртуальный кабель и т.д). Пишу на Qt5.12.12 поско…
            • Evgenii Legotckoi
              March 9, 2025, 9:02 p.m.
              К сожалению, я этого подсказать не могу, поскольку у меня нет необходимости в обходе блокировок и т.д. Поэтому я и не задавался решением этой проблемы. Ну выглядит так, что вам действитель…
            • VP
              March 9, 2025, 4:14 p.m.
              Здравствуйте! Я устанавливал Qt6 из исходников а также Qt Creator по отдельности. Все компоненты, связанные с разработкой для Android, установлены. Кроме одного... Когда пытаюсь скомпилиров…
            • ИМ
              Nov. 22, 2024, 9:51 p.m.
              Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
            • Evgenii Legotckoi
              Oct. 31, 2024, 11:37 p.m.
              Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup