这是 Qt Quick ComboBox 中的错误吗?

Posted

技术标签:

【中文标题】这是 Qt Quick ComboBox 中的错误吗?【英文标题】:Is this a bug in Qt Quick ComboBox? 【发布时间】:2015-07-31 07:04:24 【问题描述】:

我使用QAbstractListModel 在 Qt Quick 中为ComboBox 创建自定义模型。 头文件中的代码:

#ifndef JREFINDER_H
#define JREFINDER_H

#include <QObject>
#include <QMap>
#include <QString>
#include <QAbstractListModel>

enum BitSize

    BitX86,
    BitX64
;

class JreInformation : public QObject

    Q_OBJECT
public:
    ..........
;

class JreFinder : public QAbstractListModel

    Q_OBJECT
public:
    enum JreFinderRoles
    
        JavaPath = Qt::UserRole + 1,
        JavaVerson,
        JavaType,
        Display
    ;

    explicit JreFinder(QObject *parent = 0);
    virtual QHash<int, QByteArray> roleNames() const;
    virtual QVariant data(const QModelIndex &index, int role) const;
    virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
    Q_INVOKABLE void refresh();
    Q_INVOKABLE void setIndex(int index);
    Q_INVOKABLE QObject* getJavaInfo();

signals:

public slots:

private:
    int m_index;
    QList<JreInformation*> m_foundJre;
    QHash<int, QByteArray> m_roleNames;
;



#endif // JREFINDER_H

以及源文件中的代码:

JreFinder::JreFinder(QObject *parent) : QAbstractListModel(parent)
  ,m_index(0)

    m_roleNames.insert(JavaPath, "javaPath");
    m_roleNames.insert(JavaVerson, "javaVersion");
    m_roleNames.insert(JavaType, "javaType");
    m_roleNames.insert(Display, "display");

    QHash<int, QByteArray> defaultRoleNames = QAbstractListModel::roleNames();
    QHashIterator<int, QByteArray> i(defaultRoleNames);
    while (i.hasNext())
    
        i.next();
        m_roleNames.insert(i.key(), i.value());
    


QHash<int, QByteArray> JreFinder::roleNames() const

    return m_roleNames;


QVariant JreFinder::data(const QModelIndex &index, int role) const

    qDebug()<<"row"<<index.row()<<" role"<<role<<" size"<<m_foundJre.size();
    if(index.row() >= m_foundJre.size() || index.row() < 0)
        return QVariant();

    if(role == JavaPath)
        return m_foundJre[index.row()]->path;
    else if(role == JavaVerson)
        return m_foundJre[index.row()]->version;
    else if(role == JavaType)
        return m_foundJre[index.row()]->type;
    else if(role == Display || role == Qt::DisplayRole) 
    
        QString d = m_foundJre[index.row()]->display();
        qDebug()<<"display:"<<d;
        return d;
    

    return QVariant();


int JreFinder::rowCount(const QModelIndex &) const

    qDebug()<<m_foundJre.size();
    return m_foundJre.size();


void JreFinder::refresh()

    beginResetModel();

    foreach (JreInformation* info, m_foundJre)
    
        delete info;
    
    m_foundJre.clear();

    ReadJreHome(m_foundJre);
    endResetModel();


void JreFinder::setIndex(int index)

    m_index = index;


QObject* JreFinder::getJavaInfo()

    if(m_index >= m_foundJre.size() || m_index < 0)
        return NULL;

    return m_foundJre[m_index];

我将它暴露在 QML 中:

JreFinder jreFinder;
jreFinder.refresh();
engine.rootContext()->setContextProperty("jreFinder", &jreFinder);

并使用此模型创建一个 ComboBox:

    ComboBox
    
        textRole: "display"
        model:jreFinder 
    

此代码运行完美,但请查看源文件的函数data() 中的这一行:

else if(role == Display || role == Qt::DisplayRole)

我认为在我设置ComboBoxtextRole之后,显示角色应该命名为“显示”,这是我根据m_roleNames.insert(Display, "display");自定义模型中的角色Display。但这并不总是正确的。

这是上面代码的qDebug()&lt;&lt; 输出:

1 1 第 0 行角色 260 大小 1 显示:“1.8.0_51 64bit”

还有

1 1 第 0 行角色 0 大小 1 显示:“1.8.0_51 64bit”

这两个输出是随机出现的。您会发现传递给data() 函数的role 参数有时会为零角色在 Qt 中表示Qt::DisplayRole

所以这是我的问题:如果设置textRole of ComboBox 意味着data role 设置为等于textRole 的值。为什么data role 有时会变成Qt::DisplayRole?是ComboBox的bug吗?

【问题讨论】:

【参考方案1】:

角色名称到角色 ID 的映射不明确是不明智的做法。映射必须是 1:1。 Qt 自己的DisplayRole 已经命名为display。将您的名称命名为仍然是有效 js 标识符的其他名称,或按原样使用 Qt。

【讨论】:

以上是关于这是 Qt Quick ComboBox 中的错误吗?的主要内容,如果未能解决你的问题,请参考以下文章

Qt Quick:如何从ComboBox获取当前文本

Qml Qt Quick Control 2:Text和ComboBox的字体大小区别

错误:QT 中的未知模块:qml quick - Qt Creator

项目错误:QT 中的未知模块:qml quick

Qt Quick 从角色返回对象

✿4-The Basics-Qt Quick and QML