通过StyledItemDelegate创建的QComboBox在设置模型数据时未选择正确的值-为什么?

时间:2019-06-07 17:12:02

标签: qt qcombobox qabstractitemmodel qstyleditemdelegate

我必须向继承的复杂面板编辑器中添加功能。基本的VSP编辑器面板类根据标准VMC范例进行初始化。目前,它支持创建QDoubleSpinBox类型的单元格(或项目)编辑器(用于ints,doubles等);用于布尔的QComboBox;还有一个QLineEdit框,用于其他所有内容。我需要添加一种情况,为某些语言QString枚举(例如“英语”,“法语”)创建特定的QComboBox。当我这样做时,我似乎永远无法选择下拉菜单中的任何文本项,并且该文本项会不断恢复为默认值。我在做什么错了,我该如何解决?

// cfgEdVSP.cpp

bool CfgEdVSP::init()
{
    delete m_viewLayout;
    delete m_view;
    delete m_model;

    // Setup GUI Model
    m_model = new VSPTreeModel(m_schemaFile, m_nodes, this);

    // Setup GUI View
    m_view = new QTreeView(this);
    m_view->setSelectionBehavior(QAbstractItemView::SelectRows);
    m_view->setSelectionMode(QAbstractItemView::SingleSelection);

    // Attach the Model to the View
    m_view->setModel(m_model);

    // Setup GUI Model-View Delegate
    m_view->setItemDelegate(new VSPItemDelegate(this));

    m_view->header()->resizeSection(1, 240);
    m_view->header()->setResizeMode(0, QHeaderView::ResizeToContents);
    m_view->header()->setResizeMode(1, QHeaderView::ResizeToContents);
    m_view->header()->resizeSection(1, 140);
    m_view->header()->setResizeMode(2, QHeaderView::ResizeToContents);
    m_view->header()->resizeSection(2, 80);
    m_view->header()->setResizeMode(3, QHeaderView::ResizeToContents);
    m_view->header()->resizeSection(3, 80);
    m_view->header()->setResizeMode(4, QHeaderView::Stretch);
    m_view->header()->resizeSection(4, 80);
    m_view->expandToDepth(0);

    // The view will take the form of a QHBoxLayout (i.e. widgets lined up horizontally)
    m_viewLayout    = new QHBoxLayout();
    m_viewLayout->addWidget(m_view, 1);
    addMainLayout(m_viewLayout);

...

    // setup context menu used for editing (similar to CfgEdADG <R-CLK>, copy/paste, etc )
    createActions();

    // [1] set property Qt:CustomContextMenu so that the view will emit a
    // customContextMenuRequested() signal (see below).
    m_view->setContextMenuPolicy(Qt::CustomContextMenu);

    m_valPopup = new QMenu(m_view);

...

    // [2] Ensure that we have a SLOT to match the customContextMenuRequested signal
    connect(m_view, SIGNAL(customContextMenuRequested(const QPoint &)),
                     SLOT(vspTableContextMenuRequested(const QPoint &)));

    return true;
}

// VSPTreeModel.h

class VSPTreeModel : public QAbstractItemModel
{
    Q_OBJECT

public:
    VSPTreeModel(const QString& schemaFile,
                 const QVector<VSPConfigNode>& nodes,
                 QObject *parent = 0);
    ~VSPTreeModel();

...

    bool setData(const QModelIndex &index, const QVariant &value,
                 int role = Qt::EditRole); 
}

// VSPTreeModel.cpp

bool VSPTreeModel::setData(const QModelIndex &index, const QVariant &value,
                        int role)
{
    QString strValue = value.toString();

    if (role != Qt::EditRole)
        return false;

    VSPTreeItem *item = getItem(index);  //Note if index is invalid will return rootItem
    bool result = item ? item->setData(index.column(), value) : false;

    if (result)
        emit dataChanged(index, index);

    return result;
}

// VSPItemDelegate.h 

class VSPItemDelegate : public QStyledItemDelegate {
   Q_OBJECT

public:

    VSPItemDelegate(QObject* parent = 0) : QStyledItemDelegate(parent){}                                         m_logger(Logger::getInstance("VSP")){} 

    QWidget* createComboBoxEditor(QWidget *parent,
                                  const QStyleOptionViewItem & option,
                                  const QModelIndex & index ) const;


    QWidget* enumEditor(QWidget* parent, const QStyleOptionViewItem 
& option, const QModelIndex & index) const;

private:
    Logger *m_logger;
};

// VSPItemDelegate.cpp

QWidget * VSPItemDelegate::createEditor ( QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index ) const
{
    VSPTreeItem* item = reinterpret_cast<VSPTreeItem*> (index.internalPointer());
    ConfigTableDataset* data = item->getData();

    // We're going to call the PARENT CLASS createEditor method...
    // This returns the widget used for editing the data item specified by
    // the index value given, UNLESS...

    // If data is an ENUM or BOOL then ensure a QComboBox is created

    QWidget *editor = NULL;

// CODE I ADDED START ##########################################
    if ( (data->type() == CfgNode::ENUM) ) 
    {
       editor = ((QComboBox *)enumEditor(parent, option, index));
       return editor;
    } 
// CODE I ADDED END  ###########################################
    else 
    {
       editor = QStyledItemDelegate::createEditor(parent, option, index);
    }

    if (!index.internalPointer())
        return editor;

    if(QDoubleSpinBox* sbox = dynamic_cast<QDoubleSpinBox*>(editor))
    {
...
    }
    else if(QComboBox* cbox = dynamic_cast<QComboBox*>(editor))
    {
        if(data->type() == CfgNode::BOOL) {
            cbox->setItemText(0, cbox->itemText(0).toLower());
            cbox->setItemText(1, cbox->itemText(1).toLower());
        }
    }
    else if (QLineEdit* editBox = dynamic_cast<QLineEdit*>(editor))
    {
...

    }
    else
    {
// UNKNOWN TYPE OF EDITOR
...
    }
    return editor;
}

// CODE I ADDED START ##########################################
QWidget * VSPItemDelegate::enumEditor(QWidget* parent, const QStyleOptionViewItem & option, const QModelIndex & index) const
{
    QComboBox* cbox = new QComboBox(parent);

    QStringList languageList;
    languageList << "english" << "french";
    cbox->insertItems(0, languageList);

    return cbox;
}
// CODE I ADDED END  ###########################################

无论是否进行了更改,数值,布尔值和文本编辑的预期结果都可以正常工作并包含正确的值,然后到了VSPTreeModel :: setData()将新值放入模型的时间。面板屏幕也已正确刷新。请注意,这似乎是QStyledTemDelegate的“默认”行为,因为没有显式的VSPItemDelegate :: SetModelData()方法。但是,对于其他枚举QComboBox情况,在执行VSPTreeModel :: setData()时,该值为INCORRECT(例如,当其应为“ french”且面板始终刷新时,将返回“ english”,并返回到默认值:“ english”) 。此外,我发现VSPItemDelegate :: createEditor()方法被称为AT ALL感到很奇怪,因为我为此找不到任何SIGNAL / SLOT连接链接。我对Qt很陌生,所以不知道这种默认行为吗?!

0 个答案:

没有答案