QComboBox in the QTableView



  • Hello everybody! I have some problem with setting QComboBox into QTableView

    I want to use in my test app MVC model. In my code i have my custom Model class - TableModel, it inherits from QAbstractTableModel, View class - it is a standard QTableView, and custom Delegate - SimpleDelegate, It inherits from QStyledItemDelegate.

    But after compilation i can't see any QComboBox on QTableView! After doubleclick I see only QLine Edit.

    This is code of my app:

    main.cpp

    #include <QtWidgets>
    #include <QObject>
    #include "simpledelegate.h"
    #include "tablemodel.h"
     
    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
        TableModel model(200, 200);
     
        QTableView tableView;
        tableView.setModel(&model);
        tableView.setItemDelegate(new SimpleDelegate(&tableView));
        tableView.viewport()->setAttribute(Qt::WA_Hover);
        tableView.show();
        return app.exec();
    }
    

    simple.h

    #ifndef SIMPLEDELEGATE
    #define SIMPLEDELEGATE
     
    #include <QWidget>
    #include <QStyledItemDelegate>
    #include <QComboBox>
    #include <QObject>
     
    class SimpleDelegate : public QStyledItemDelegate
    {
        Q_OBJECT
    public:
        SimpleDelegate(QObject* pobj = 0);
        QWidget* createEditor(QWidget *parent,
                                    const QStyleOptionViewItem &option,
                                    const QModelIndex &index);
     
        void setModelData(QWidget *editor, QAbstractItemModel *model,
                                                 const QModelIndex &index);
        void setEditorData(QWidget *editor, const QModelIndex &index);
    };
    #endif // SIMPLEDELEGATE
    

    simple.cpp

    #include "simpledelegate.h"
     
    SimpleDelegate::SimpleDelegate(QObject* pobj) : QStyledItemDelegate(pobj)
    {
    }
    QWidget*  SimpleDelegate::createEditor(QWidget *parent,
                                const QStyleOptionViewItem &option,
                                const QModelIndex &index)
    {
     
        QStringList values;
        values << "Enabled" << "Disabled";
     
        QComboBox* comboBox = new QComboBox(parent);
        comboBox->addItems(values);
        return comboBox;
     
    }
     
    void  SimpleDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
                                             const QModelIndex &index)
    {
        QComboBox* comboBox = qobject_cast<QComboBox*>(editor);
        QString value = comboBox->currentText();
        model->setData(index, value, Qt::EditRole);
    }
     
    void  SimpleDelegate::setEditorData(QWidget *editor, const QModelIndex &index)
    {
        QString value = index.model()->data(index, Qt::EditRole).toString();
        //qDebug() << "Value:" << value;
        QComboBox* comboBox = qobject_cast<QComboBox*>(editor);
        comboBox->setCurrentIndex(comboBox->findText(value));
    }
    

    table.h

    #ifndef TABLEMODEL
    #define TABLEMODEL
     
    #include <QWidget>
    #include <QStyledItemDelegate>
    #include <QComboBox>
    #include <QObject>
     
    class TableModel : public QAbstractTableModel
    {
        Q_OBJECT
    private:
        int                          m_nRows;
        int                          m_nColumns;
        QHash<QModelIndex, QVariant> m_hash;
     
    public:
        TableModel(int nRows, int nColumns, QObject* pobj = 0);
     
        QVariant data(const QModelIndex& index, int nRole) const;
     
        bool setData(const QModelIndex& index,
                     const QVariant&    value,
                     int                nRole
                    );
     
        int rowCount(const QModelIndex&) const ;
        int columnCount(const QModelIndex&) const ;
     
        Qt::ItemFlags flags(const QModelIndex& index) const;
    };
     
    #endif // TABLEMODEL
    

    table.cpp

    #include "tablemodel.h"
     
     
     
    TableModel::TableModel(int nRows, int nColumns, QObject* pobj)
        : QAbstractTableModel(pobj)
        , m_nRows(nRows)
        , m_nColumns(nColumns)
    {
    }
     
    QVariant TableModel::data(const QModelIndex& index, int nRole) const
    {
        if (!index.isValid())
        {
            return QVariant();
        }
        QString str = QString("%1,%2").arg(index.row() + 1).arg(index.column() + 1);
        return (nRole == Qt::DisplayRole || nRole == Qt::EditRole)
               ? m_hash.value(index, QVariant(str))
               : QVariant();
    }
     
    bool TableModel::setData(const QModelIndex& index,
                 const QVariant&    value,
                 int                nRole
                )
    {
        if (index.isValid() && nRole == Qt::EditRole) {
            m_hash[index] = value;
            emit dataChanged(index, index);
            return true;
        }
        return false;
    }
     
    int TableModel::rowCount(const QModelIndex&) const
    {
        return m_nRows;
    }
     
    int TableModel::columnCount(const QModelIndex&) const
    {
        return m_nColumns;
    }
     
    Qt::ItemFlags TableModel::flags(const QModelIndex& index) const
    {
        Qt::ItemFlags flags = QAbstractTableModel::flags(index);
        return index.isValid() ? (flags | Qt::ItemIsEditable)
                               : flags;
    }
    

    Where is mistake?
    Thanks!

    P.S. Sorry for my poor English



  • Hi,

    When you reimplemented the virtual methods setEditorData, setModelData and createEditor, you simply forgot the "const" at the end:

    QWidget* SimpleDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const {
      QStringList values;
      values << "Enabled" << "Disabled";
    
      QComboBox* comboBox = new QComboBox(parent);
      comboBox->addItems(values);
      return comboBox;
    }
    
    void SimpleDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const {
      QComboBox* comboBox = qobject_cast<QComboBox*>(editor);
      QString value = comboBox->currentText();
      model->setData(index, value, Qt::EditRole);
    }
    
    void SimpleDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const {
      QString value = index.model()->data(index, Qt::EditRole).toString();
      QComboBox* comboBox = qobject_cast<QComboBox*>(editor);
      comboBox->setCurrentIndex(comboBox->findText(value));
    }
    
    

    If you can, try to use C++11 and add the "override" keyword at the end of the methods in your header files. Then the compiler would tell you if the overridden method is really a method to override.

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

    Now it works, but obviously it replaces the integer value with "enable" or "disable". Not sure that was what you wanted.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.