从QStyledItemDelegate中的ComboBox调用对话框

时间:2011-08-25 18:00:14

标签: qt delegates

所以我在这里的是QAbstractTableModel的委托代码。第二列(index = 1)始终为comboBoxcomboBox有一个模拟中给定单位可以执行的操作列表。单击Build或Train等某些操作后,我希望弹出一个Dialog,为用户提供一组选项。做出选择之后,代表应该更新模型的数据并继续前进。

这是我遇到的障碍。如果我尝试从setModelData()setEditorData()调用对话框,则这些功能为const,因此我无法将对话框的结果分配。< / p>

我尝试做的是连接indexChanged(QString)中创建的QComboBox信号createEditor()。这至少允许我分配结果并仅在做出适当选择时调用对话框。但是我一直遇到一个seggy错误,QTCreator中的跟踪不会落在C代码上(33个程序集调用)。我不确定为什么我会有这种偏见。

当我尝试这种方法时,一旦对话框出现,表格就不再有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 个答案:

答案 0 :(得分:2)

我想出来了。如果有人对类似的东西感兴趣,我会对QTableView进行分类。

QTableView内,我使用QTableView::setIndexWidget()来使用QComboBox es和QProgressBar s。基本上我的子类有两种类型小部件的QList,它们对应于表中的特定行。

答案 1 :(得分:0)

  1. ComboBoxEditor
  2. 派生QComboBox
  3. 在ComboBoxEditor中保存一个Action对象(数据存储在模型索引中)
  4. 调用代理comboChanged()时,您可以通过发件人()ComboBoxEditor访问操作。
  5. 请参阅官方示例StarDelegate

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