Вызов диалога из ComboBox в QStyledItemDelegate - PullRequest
2 голосов
/ 25 августа 2011

Итак, у меня есть мой код делегата для QAbstractTableModel. 2-й столбец (индекс = 1) всегда равен comboBox. У этого comboBox есть список действий, которые может выполнить данный юнит в моей симуляции. После нажатия определенных действий, таких как «Построить» или «Поезд», я хочу, чтобы всплыло диалоговое окно, предоставляющее пользователю набор вариантов. Сделав выбор, делегат должен обновить данные модели и двигаться дальше.

Вот загвоздка, с которой я столкнулся. Если я попытаюсь вызвать диалог из setModelData(), setEditorData(), эти функции будут const, поэтому я не могу присвоить результаты диалога чему-либо.

Я попытался подключить сигнал indexChanged(QString) от QComboBox, созданного в createEditor(). Это, по крайней мере, позволило мне назначить результат и вызвать диалог только тогда, когда был сделан соответствующий выбор. Однако, я продолжаю получать ошибку seggy, и трассировка в QTCreator не попадет на код C (33 вызова сборки). Я не уверен, почему я получил этот seggy.

Когда я попробовал этот подход, у таблицы больше не было combobox после появления диалога. Он вернулся к своему предыдущему состоянию, и как только программа вышла из слота, который я сделал для QComboBox::indexChanged(QString), произошел seggy.

DelegateAction.h

#ifndef DELEGATEACTION_H
#define DELEGATEACTION_H

#include <QVariant>
#include <QStyledItemDelegate>
#include <QString>

#include <QApplication>
#include <QWidget>
#include <QLabel>
#include <QComboBox>
#include <QProgressBar>
#include <QMouseEvent>

#include <JECMessageTable.h>

#include <UnitBase.h>
#include <ModelListUnit.h>

class DelegateAction : public QStyledItemDelegate
{
    Q_OBJECT
public:
    explicit DelegateAction(QObject *parent = 0);
    ~DelegateAction();

    QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
    void setEditorData(QWidget *editor, const QModelIndex &index) const;
    void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;
    void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const;
    QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;

public slots:
    void setUnits(QList<Unit*>* units);

protected:
    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
    //bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index);
private slots:
    void comboChanged(QString string);
    void comboDestroyed();

private:
    bool comboUpdated;
    const UnitBase* selectedUnit;
    ModelListUnit *model;           // The model for the JECMessageTable.

    QList<Unit*>* units;     // The current list of units.

};

#endif // DELEGATEACTION_H

DelegateAction.cpp

#include "DelegateAction.h"

DelegateAction::DelegateAction(QObject *parent) :
    QStyledItemDelegate(parent),
    selectedUnit(0),
    model(0)
{
}

DelegateAction::~DelegateAction()
{
    delete model;
}

QWidget * DelegateAction::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QWidget* editor = 0;

    switch (index.column())
    {
    case 0:
    default:
    {
        editor = new QLabel();
        break;
    }
    case 1:
    {
        QComboBox* combo = new QComboBox(parent);
        combo->addItem("Idle");
        combo->addItem("Gather");
        combo->addItem("Train");
        combo->addItem("Build");
        combo->addItem("Upgrade");
        editor = combo;
//        connect(combo, SIGNAL(currentIndexChanged(QString)), this, SLOT(comboChanged(QString)));
//        connect(combo, SIGNAL(destroyed()), this, SLOT(comboDestroyed()));
        break;
    }
    case 4:
    {
        editor = new QProgressBar(parent);
        break;
    }
    }

    editor->installEventFilter(const_cast<DelegateAction*>(this));
    return editor;
}

void DelegateAction::setEditorData(QWidget *editor, const QModelIndex &index) const
{
    QVariant value = index.model()->data(index, Qt::DisplayRole);

    switch (index.column())
    {
    case 0:
    default:
    {
        QLabel* label = static_cast<QLabel*>(editor);
        label->setText(value.toString());
        break;
    }
    case 1:
    {
        QComboBox* combo = static_cast<QComboBox*>(editor);
        combo->setCurrentIndex(combo->findText(value.toString()));

        break;
    }
    case 4:
    {
        QProgressBar* progress = static_cast<QProgressBar*>(editor);
        progress->setValue(value.toInt());
        break;
    }
    }

}

void DelegateAction::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    QVariant value;
    switch (index.column())
    {
    case 0:
    default:
    {
        value = static_cast<QLabel*>(editor)->text();
        break;
    }
    case 1:
    {
        QString string = static_cast<QComboBox*>(editor)->currentText();

        switch (Action::getType(string))
        {
        case Action::INVALID:
        {
            return;
        }
        case Action::IDLE:
        {
            return;
        }
        case Action::GATHER:
        {
            return;
        }
        case Action::BUILD:
        {
            return;
        }
        case Action::TRAIN:
        {
            // Summon the build choice dialog.
            if (units == 0)
            {
                return;
            }

            JECMessageTable messageBox(this->model, "Test");
            messageBox.exec();

            if (messageBox.result() == QDialog::Accepted)
            {
                //selectedUnit = this->model->getSelectedUnit();
            }
            else
            {
               //selectedUnit = 0;
            }

            return;
        }
        case Action::MORPH:
        {
            return;
        }
        case Action::UPGRADE:
        {

        }
        }

        break;
    }
    case 4:
    {
        value = static_cast<QProgressBar*>(editor)->value();
        break;
    }
    }

    model->setData(index, value);
}

void DelegateAction::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    editor->setGeometry(option.rect);
}

QSize DelegateAction::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    if (index.column() == 4)
    {
        return QSize(option.rect.width(), option.rect.height());
    }
    else
    {
        return QStyledItemDelegate::sizeHint(option, index);
    }
}

void DelegateAction::paint(QPainter *painter, const QStyleOptionViewItem &item, const QModelIndex &index) const
{
    if (index.column() == 4 && index.isValid() == true)
    {
        QStyleOptionProgressBarV2 progress;

        progress.minimum = 0;
        progress.maximum = 100;
        progress.progress = index.data().toInt();
        progress.rect = QRect(item.rect.x(), item.rect.y(), item.rect.width(), item.rect.height());

        QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progress, painter);
    }
    else
    {
        // Painting the cells normally.
        QStyledItemDelegate::paint(painter, item, index);
    }
}

void DelegateAction::setUnits(QList<Unit*> *units)
{
    this->units = units;

    if (units != 0)
    {
        if (units->length() > 0)
        {
            model = new ModelListUnit(&units->at(0)->getUnitBase()->getOptionUnit());
        }
    }
}

void DelegateAction::comboChanged(QString string)
{

//    comboUpdated = true;
//    switch (Action::getType(string))
//    {
//    case Action::INVALID:
//    {
//        return;
//    }
//    case Action::IDLE:
//    {
//        return;
//    }
//    case Action::GATHER:
//    {
//        return;
//    }
//    case Action::BUILD:
//    {
//        return;
//    }
//    case Action::TRAIN:
//    {
//        // Summon the build choice dialog.
//        if (units == 0)
//        {
//            return;
//        }

//        JECMessageTable messageBox(model, "Test");
//        messageBox.exec();

//        if (messageBox.result() == QDialog::Accepted)
//        {
//            selectedUnit = model->getSelectedUnit();
//        }
//        else
//        {
//            selectedUnit = 0;
//        }

//        return;
//    }
//    case Action::MORPH:
//    {
//        return;
//    }
//    case Action::UPGRADE:
//    {

//    }
//    }

}

void DelegateAction::comboDestroyed()
{
    disconnect(this, SLOT(comboChanged(QString)));
    disconnect(this, SLOT(comboDestroyed()));
}

//bool DelegateAction::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
//{
//    QStyledItemDelegate::editorEvent(event, model, option, index);

//    if (comboUpdated == true && index.isValid() == true)
//    {
//        comboUpdated = false;

//        if (selectedUnit != 0)
//        {
//            units->at(index.row());
//        }
//    }
//}

Ответы [ 2 ]

2 голосов
/ 26 августа 2011

Я понял это.Если кого-то интересует что-то подобное, я подклассифицировал QTableView.

Внутри QTableView я использовал QTableView::setIndexWidget(), чтобы использовать QComboBox es и QProgressBar s.В основном мой подкласс имел QList обоих типов виджетов, и они соответствовали определенной строке в таблице.

0 голосов
/ 26 мая 2017
  1. получить ComboBoxEditor из QComboBox
  2. сохранить объект Action в ComboBoxEditor (данные хранятся в модельном индексе)
  3. при вызове делегата comboChanged() вы можете получить доступДействие через отправителя (), то есть ComboBoxEditor.

Пожалуйста, обратитесь к официальному примеру, StarDelegate.

http://doc.qt.io/qt-5/qtwidgets-itemviews-stardelegate-example.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...