从 QStyledItemDelegate 中的 ComboBox 调用对话框

发布于 2024-12-01 08:06:19 字数 8808 浏览 1 评论 0原文

所以我这里有的是 QAbstractTableModel 的委托代码。第二列(索引 = 1)始终是一个组合框。该组合框具有我的模拟中给定单元可以执行的操作列表。单击“构建”或“训练”等某些操作后,我希望弹出一个对话框,为用户提供一组选择。做出选择后,代表应该更新模型的数据并继续。

这是我遇到的障碍。如果我尝试从 setModelData()setEditorData() 调用对话框,这些函数是 const,因此我无法分配 对话框的结果可以是任何内容。

我试图做的是从 createEditor() 创建的 QComboBox 连接信号 indexChanged(QString) 。这至少允许我分配结果并仅在做出适当的选择时调用对话框。然而,我不断遇到段错误,QTCreator 中的跟踪不会落在 C 代码上(33 次汇编调用)。我不确定为什么我会这样。

当我尝试这种方法时,一旦对话框出现,表格就不再有组合框。它恢复到之前的状态,一旦程序离开我为 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());
//        }
//    }
//}

So what I have here is my delegate code for a QAbstractTableModel. The 2nd column (index = 1), is always a comboBox. That comboBox has a list of actions that a given Unit in my simulation can perform. Upon clicking certain actions like Build or Train, I want a Dialog to pop up giving the user a set of choices. After making there choice, the delegate is supposed to update the model's data and move on.

Here is the snag I've run into. If I try to call a dialog from setModelData(), setEditorData(), those functions are const so I can't assign the results of the dialog to anything.

What I have tried to do is to connect the signal indexChanged(QString) from the QComboBox created in createEditor(). This at least allowed me to assign the result and call the dialog only when the appropriate choice was made. However I keep getting a seggy fault and the trace in QTCreator will not land on C code (33 calls of assembly). I'm unsure as to why I got that seggy.

When I tried that approach, the table no longer had the combobox once the dialog appeared. It reverted to its previous state and as soon as the program left the slot I made for QComboBox::indexChanged(QString), the seggy happened.

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());
//        }
//    }
//}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

拥抱没勇气 2024-12-08 08:06:19

我明白了这一点。如果有人对类似的东西感兴趣,我将QTableView子类化。

QTableView内部,我使用QTableView::setIndexWidget()来使用QComboBoxes和QProgressBars。基本上,我的子类有一个包含两种类型小部件的 QList,它们对应于表中的特定行。

I figured this out. If anyone is interested in something similar, I sub classed QTableView.

Inside QTableView i used QTableView::setIndexWidget() to use QComboBoxes and QProgressBars. Basically my subclass had a QList of both types of widgets and they corresponded to a particular row in the table.

双手揣兜 2024-12-08 08:06:19
  1. QComboBox 派生 ComboBoxEditor
  2. 在 ComboBoxEditor 中保留一个 Action 对象(数据存储在模型索引中),
  3. 当调用 delegate 的 comboChanged() 时,您可以访问通过 sender() 执行操作,即 ComboBoxEditor

请参考官方示例StarDelegate

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

  1. derive ComboBoxEditor from QComboBox
  2. keep a Action object in ComboBoxEditor (data stored in model index)
  3. when delegate's comboChanged() is called, you can access the Action via sender(), that is ComboBoxEditor.

Please refer to the official example, StarDelegate.

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文