Использование QTreeWidgetItems setData для хранения QStackedWidget или QVariant

Я пытаюсь сделать QTreeWidget таким, чтобы каждая строка содержала серию полей со списком. В зависимости от того, как пользователь взаимодействует с выпадающими списками, я хотел бы, чтобы некоторые выпадающие списки становились редактированием строк, а некоторые — кнопками.

Было предложено здесь, что QStackedWidget будет обслуживать мои потребности, и он проделал довольно хорошую работу, за исключением того, что теперь мне нужен способ изменить QStackedWidget, который находится рядом с тем, который содержит поле со списком, посылающее мне сигнал indexChanged. (В основном я хочу изменить соседний индекс QStackWidgets)

Я думал, что смогу просто сохранить QStackWidget в дочернем элементе с помощью setData, а затем получить его в слоте indexChanged, но по какой-то причине кажется, что QStackWidget не установлен для данных дочерних элементов.

Любая помощь приветствуется.

Здесь я изначально настраиваю свой QTreeWidget и его элементы.

    QTreeWidgetItem *childItem = new QTreeWidgetItem(itemParent);



    QVariant itemParentVariant,widgetParentVarient;
    widgetParentVarient.setValue(widgetParent);
    itemParentVariant.setValue(itemParent);
    QList<QVariant> stackWidgetList;
    uint cycleSetup;
    for(cycleSetup = 0;cycleSetup < methodBlocks.at(rowType).size()+2;cycleSetup++)
    {

            QComboBox *itemComboBox = new QComboBox;
            itemComboBox->setProperty("rowType", rowType);
            itemComboBox->setProperty("row", 0);
            itemComboBox->setProperty("column",cycleSetup);
            itemComboBox->setProperty("widgetParent",widgetParentVarient);
            itemComboBox->setProperty("itemParent",itemParentVariant);
            itemComboBox->addItems(methodBlocks.at(0).at(cycleSetup));
            QObject::connect(itemComboBox, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(OnComboIndexChanged(const QString&)));
            QLineEdit *itemLineEdit = new QLineEdit;
            QPushButton *itemButton = new QPushButton;
            itemButton->setText("Reset");
            QComboBox *timeComboBox = new QComboBox;
            timeComboBox->setProperty("rowType", rowType);
            timeComboBox->setProperty("row", 0);
            timeComboBox->setProperty("column",cycleSetup);
            timeComboBox->setProperty("widgetParent",widgetParentVarient);
            timeComboBox->setProperty("itemParent",itemParentVariant);
            timeComboBox->addItems(QString("Seconds;MilliSeconds;Reset").split(";"));
            QStackedWidget *masterItemWidget = new QStackedWidget;
            masterItemWidget->addWidget(itemLineEdit);
            masterItemWidget->addWidget(itemComboBox);
            masterItemWidget->addWidget(itemButton);
            masterItemWidget->addWidget(timeComboBox);
            masterItemWidget->setCurrentIndex(1);
            QVariant stackParent;
            stackParent.setValue(masterItemWidget);
            itemComboBox->setProperty("stackParent",stackParent);
            childItem->setData(0,Qt::UserRole,stackParent);
            stackWidgetList.push_back(stackParent);
            widgetParent->setItemWidget(childItem,cycleSetup,masterItemWidget);
            itemParent->addChild(childItem);
    }

И это внутри слота, где я пытаюсь получить данные (QStackWidget)

                QStackedWidget *itemMaster = combo->property("stackParent").value<QStackedWidget*>(); //this works
                itemMaster->setCurrentIndex(0);
                QTreeWidget *widgetParent = combo->property("widgetParent").value<QTreeWidget*>();

                QTreeWidgetItem *parentItem = combo->property("itemParent").value<QTreeWidgetItem*>();
                QTreeWidgetItem *childItem = new QTreeWidgetItem(parentItem);


                QList<QVariant> stackList = childItem->data(0,Qt::UserRole).value<QList<QVariant>>(); //this doesnt
                QStackedWidget *itemsibMaster = childItem->data(0,Qt::UserRole).value<QStackedWidget*>(); //neither does this
                itemsibMaster->setCurrentIndex(2);

РЕДАКТИРОВАТЬ:

Я пытался установить такие данные

            QFrame *stackFrame = new QFrame;
            QStackedWidget *masterItemWidget = new QStackedWidget(stackFrame);
            masterItemWidget->addWidget(itemLineEdit);
            masterItemWidget->addWidget(itemComboBox);
            masterItemWidget->addWidget(itemButton);
            masterItemWidget->addWidget(timeComboBox);
            masterItemWidget->setCurrentIndex(1);
            QVariant stackParent;
            stackParent.setValue(masterItemWidget);
            itemComboBox->setProperty("stackParent",stackParent);
            QVariant frameVariant;
            frameVariant.setValue(stackFrame);
            childItem->setData(0,Qt::UserRole,frameVariant);
            stackWidgetList.push_back(stackParent);
            widgetParent->setItemWidget(childItem,cycleSetup,masterItemWidget);
            itemParent->addChild(childItem);

И получить его вот так

                QStackedWidget *itemMaster = combo->property("stackParent").value<QStackedWidget*>();
                itemMaster->setCurrentIndex(0);
                QTreeWidget *widgetParent = combo->property("widgetParent").value<QTreeWidget*>();

                QTreeWidgetItem *parentItem = combo->property("itemParent").value<QTreeWidgetItem*>();
                QTreeWidgetItem *childItem = new QTreeWidgetItem(parentItem);


                QFrame *frameObject = childItem->data(0,Qt::UserRole).value<QFrame*>();
                //QList<QVariant> stackList = childItem->data(0,Qt::UserRole).value<QList<QVariant>>();
                QStackedWidget *itemFrameMaster = frameObject->findChild<QStackedWidget*>();
                if(itemFrameMaster)
                {
                    qDebug() << "itemFrame Exists";

                }
                else
                {
                    qDebug() << "itemFrame is NULL";//It goes to here
                }

Поэтому я все еще не могу получить желаемую функциональность.


person Reginald Marr    schedule 23.02.2018    source источник
comment
Не используйте QTreeWidget для чего-то такого сложного. Вместо этого используйте QTreeView с делегатом модели и элемента. Это гораздо более гибко и позволяет вам поддерживать управляемость вашего кода.   -  person D Drmmr    schedule 24.02.2018
comment
Честно говоря, я пытался использовать QTreeView, однако немного запутался в примере, в котором не было класса делегата, а вместо этого был класс treeitem и treeview. Я попробую еще раз взломать его, я начинаю думать, что это можно сделать с помощью QTreeView и просто с помощью класса делегата элемента.   -  person Reginald Marr    schedule 24.02.2018


Ответы (2)


Проверьте, работает ли он.

Поскольку составной виджет QStackedWidget является производным от QFrame, создайте объект Frame и добавьте к нему составной виджет. Установите рамку для вашего дочернего элемента.

QFrame *stackFrame = new QFrame(Parent);

QStackedWidget *masterItemWidget  = new QStackedWidget(stackFrame);

При запросе первого запроса для фрейма и получения из него дочернего элемента сложенного виджета.

QStackedWidget *stackedWidget = FrameObject->findChild<QStackedWidget *>();
person Pavan Chandaka    schedule 23.02.2018
comment
Итак, я только что попробовал этот QFrame stackFrame = new QFrame(childItem); QStackedWidget *masterItemWidget = новый QStackedWidget(stackFrame); Но это дало мне несколько ошибок относительно отсутствия функции для вызова (QFrame::QFrame(QTreeWidgetItem&)) Я что-то упустил? - person Reginald Marr; 23.02.2018
comment
Смотрите редактирование, я не уверен, что неправильно истолковываю ваше предложение, но пока не повезло. - person Reginald Marr; 24.02.2018

Итак, мне удалось получить ту функциональность, которая мне была нужна, поэтому, если кто-то еще пытается это сделать, вот исправление.

По сути, все, что я делал раньше, было правильно, за исключением одной ошибки.

При извлечении данных, хранящихся в дочернем поле со списком, я изначально получил этот дочерний элемент здесь.

            QTreeWidgetItem *parentItem = combo->property("itemParent").value<QTreeWidgetItem*>();
            QTreeWidgetItem *childItem = new QTreeWidgetItem(parentItem);

Проблема заключалась в том, что, поскольку у parentItem было более одного дочернего элемента (я полагаю, в этом случае минимум — два дочерних элемента), я не ссылался на правильный дочерний элемент. Эта проблема была решена путем создания пользовательского свойства поля со списком, которое содержало дочерний элемент, а не родительский (родительский элемент может быть получен из родителя более точно, чем наоборот).

Теперь, когда я заполняю QTreeWidget элементами списка, это выглядит так.

    QTreeWidgetItem *childItem = new QTreeWidgetItem(itemParent);

    QVariant childItemVariant,widgetParentVarient;
    widgetParentVarient.setValue(widgetParent);
    childItemVariant.setValue(childItem);
    uint cycleSetup;
    for(cycleSetup = 0;cycleSetup < methodBlocks.at(rowType).size();cycleSetup++)
    {
        if(cycleSetup < methodBlocks.at(rowType).size())
        {
            QComboBox *itemComboBox = new QComboBox;
            itemComboBox->setProperty("rowType", rowType);
            itemComboBox->setProperty("row", 0);
            itemComboBox->setProperty("column",cycleSetup);
            itemComboBox->setProperty("widgetParent",widgetParentVarient);
            itemComboBox->setProperty("childItem",childItemVariant);
            itemComboBox->addItems(methodBlocks.at(0).at(cycleSetup));
            QObject::connect(itemComboBox, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(OnComboIndexChanged(const QString&)));
            QLineEdit *itemLineEdit = new QLineEdit;

            QFrame *stackFrame = new QFrame;
            QStackedWidget *masterItemWidget = new QStackedWidget(stackFrame);
            masterItemWidget->addWidget(itemLineEdit);
            masterItemWidget->addWidget(itemComboBox);
            //masterItemWidget->addWidget(timeComboBox);
            masterItemWidget->setCurrentIndex(1);
            QVariant stackParent;
            stackParent.setValue(masterItemWidget);
            itemComboBox->setProperty("stackParent",stackParent);
            itemComboBox->setProperty("cycleSetupIT",cycleSetup);
            QVariant frameVariant;
            frameVariant.setValue(stackFrame);
            childItem->setData(cycleSetup,Qt::UserRole,stackParent);
            widgetParent->setItemWidget(childItem,cycleSetup,masterItemWidget);
            itemParent->addChild(childItem);
        }

    }

}

И код в слоте, где я получаю данные из дочернего элемента (который содержит поле со списком), выглядит так.

                QTreeWidget *widgetParent = combo->property("widgetParent").value<QTreeWidget*>();
                widgetParent->setColumnCount(6);
                QTreeWidgetItem *childItem = combo->property("childItem").value<QTreeWidgetItem*>();
                QTreeWidgetItem *parentItem = childItem->parent();

                int rowType = combo->property("rowType").toInt();
                int cycleIT = combo->property("cycleSetupIT").toInt();
                int offset = 0;

                QStackedWidget *itemFrameMaster = childItem->data(cycleIT+1,Qt::UserRole).value<QStackedWidget*>();
                itemFrameMaster->setCurrentIndex(0);

Надеюсь это поможет. Также, если кто-нибудь знает, как получить количество элементов данных в QStandardItem::data(), это было бы здорово, хотя и не очень критично.

Ваше здоровье!

person Reginald Marr    schedule 25.02.2018