QCombobox пользовательское поведение с моделью - PullRequest
0 голосов
/ 28 июня 2019

У меня есть модель, которая возвращает строки для DisplayRole. Я сделал setModel для моего QCombobox. Но мне нужно поместить «setSeparator» вместо некоторых значений. Поэтому не нужно показывать сам элемент, его нужно использовать как метку для размещения разделителя. Это потому, что я не могу использовать функцию setSeparator для своего QCombobox, она не действует, когда используется setmodel.

Как мне изменить поведение?

1 Ответ

0 голосов
/ 28 июня 2019

Сначала вам нужно вернуть разделитель из вашей модели. Для меня лучше использовать специальную роль для разделителя, но можно использовать и строковую метку.

class SeparatorModel : public QAbstractItemModel
{
    Q_OBJECT
public:
    static const int SeparatorRole = Qt::UserRole + 5;

    explicit SeparatorModel(QObject *parent = 0);

    int rowCount(const QModelIndex &parent) const;
    int columnCount(const QModelIndex &parent) const;
    QModelIndex index(int row, int column, const QModelIndex &parent) const;
    QModelIndex parent(const QModelIndex &child) const;
    QVariant data(const QModelIndex &index, int role) const;
    Qt::ItemFlags flags(const QModelIndex &index) const;

private:
    QStringList m_strings;

};

Верните разделитель в data методе

QVariant SeparatorModel::data(const QModelIndex &index, int role) const
{
    if (SeparatorRole == role)
    {
        if (index.row() == 3) //separator at row 3
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    if (Qt::DisplayRole == role)
    {
        return m_strings.at(index.row());
    }

    return QVariant();
}

Для предотвращения выбора разделителя также переопределить flags метод

Qt::ItemFlags SeparatorModel::flags(const QModelIndex &index) const
{
    Qt::ItemFlags flags;
    flags = Qt::ItemIsSelectable;
    if (index.row() == 3) //separator at row 3
    {
        //no enabled for separator
    }
    else
    {
        flags = flags | Qt::ItemIsEnabled;
    }

    return flags;
}

Затем вам нужно создать пользовательский элемент делегата

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

    /*
    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;
    */
    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
    QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;

};

В paint метод рисует линию, если данные для роли разделителя установлены

void SeparatorDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
                              const QModelIndex &index) const
{
    if (index.data(SeparatorModel::SeparatorRole).toBool())
    {
        painter->drawLine(option.rect.left(), option.rect.center().y(),
                          option.rect.right(), option.rect.center().y());
    }
    else
    {
        QStyledItemDelegate::paint(painter, option, index);
    }
}

А в sizeHint метод определения размера вашего разделителя

QSize SeparatorDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    if(index.data(SeparatorModel::SeparatorRole).toBool())
    {
        return QSize(0, 2);
    }

    return QStyledItemDelegate::sizeHint( option, index );
}

В конце концов, просто установите модель и делегируйте свой список

ui->comboBox->setModel(&m_model);
SeparatorDelegate *delegate = new SeparatorDelegate(this);
ui->comboBox->setItemDelegate(delegate);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...