Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
QAbstractListModel数据更改信号未更新ListView(QML) 我有一个QuestActListMod连接到QML中的ListVIEW,但是我有一个问题,从C++更新视图。这与Qt 5.6 mingw、QtQuick 2.6和QtQuick.Controls 1.5一起使用_C++_Qt_Listview_Qml_Qtquick2 - Fatal编程技术网

QAbstractListModel数据更改信号未更新ListView(QML) 我有一个QuestActListMod连接到QML中的ListVIEW,但是我有一个问题,从C++更新视图。这与Qt 5.6 mingw、QtQuick 2.6和QtQuick.Controls 1.5一起使用

QAbstractListModel数据更改信号未更新ListView(QML) 我有一个QuestActListMod连接到QML中的ListVIEW,但是我有一个问题,从C++更新视图。这与Qt 5.6 mingw、QtQuick 2.6和QtQuick.Controls 1.5一起使用,c++,qt,listview,qml,qtquick2,C++,Qt,Listview,Qml,Qtquick2,设置: ListView使用带有属性的自定义复选框委托来存储模型中的值。当用户单击代理时,代理将更新模型。在我的QML中,我还有一个切换按钮,它调用模型中的一个插槽,该插槽切换模型中的数据,并为所有行发出dataChanged()信号(将所有复选框设置为not checked或checked) 问题: 切换按钮工作正常,直到用户与任何复选框代理交互为止。用户执行此操作后,dataChanged()信号不再更新该特定委托。我还验证了我的模型的data()函数在用户交互之前被所有行调用,然后它只在用

设置: ListView使用带有属性的自定义复选框委托来存储模型中的值。当用户单击代理时,代理将更新模型。在我的QML中,我还有一个切换按钮,它调用模型中的一个插槽,该插槽切换模型中的数据,并为所有行发出dataChanged()信号(将所有复选框设置为not checked或checked)

问题: 切换按钮工作正常,直到用户与任何复选框代理交互为止。用户执行此操作后,dataChanged()信号不再更新该特定委托。我还验证了我的模型的data()函数在用户交互之前被所有行调用,然后它只在用户交互之后没有单击的行上被调用。这让我相信,在幕后的某个地方,视图选择不更新某些行,但我不知道为什么

可能的解决办法: 在模型中发出layoutChanged()会更新“我的切换”按钮的视图,而不考虑用户交互,但这会导致重新绘制整个视图,并且速度相对较慢

此问题是使用复选框创建的,但它适用于任何类型的用户交互。下面是重新创建我的问题所需的所有代码

main.qml

import QtQuick 2.6
import QtQuick.Controls 1.5
import QtQuick.Layouts 1.3

ApplicationWindow {
    visible: true
    width: 640
    height: 480

    ColumnLayout {
        anchors.fill: parent
        spacing: 10

        Button {
            Layout.preferredHeight: 100
            Layout.preferredWidth: 100
            text: "Test!"
            onClicked: {
                console.log("attempting to refresh qml")
                testModel.refresh()
                testModel.print()
            }
        }


        ScrollView {
            Layout.fillHeight: true
            Layout.fillWidth: true

            ListView {
                id: view
                anchors.fill: parent
                spacing: 5
                model: testModel
                delegate: Rectangle {

                    height: 50
                    width: 100
                    color: "lightgray"

                    CheckBox {
                        id: checkBox
                        anchors.fill: parent
                        checked: valueRole

                        onClicked: {
                            valueRole = checked
                        }
                    }
                }
            }
        }
    }
}
TestModel.cpp

#include "testmodel.h"

TestModel::TestModel(QObject *parent) : QAbstractListModel(parent) {

    roleVector << TaskRoles::valueRole;
    testValue = false;
}

TestModel::~TestModel() {}

void TestModel::setup(const QList<bool> &inputList) {

    // Clear view
    removeRows(0, valueList.length());

    // Update value list
    valueList = inputList;

    // Add rows
    insertRows(0, valueList.length());
}

// Emits data changed for entire model
void TestModel::refresh() {

    qDebug() << "attempting to refresh c++";

    // Toggle all values in model
    for (int i=0; i < valueList.length(); i++) {
        valueList[i] = testValue;
    }

    // Toggle test value
    testValue = !testValue;

    // Update view
    // this works but is slow
//    layoutAboutToBeChanged();
//    layoutChanged();

    // this doesn't work if the user clicked the checkbox already
    dataChanged(createIndex(0, 0), createIndex(rowCount()-1, 0), roleVector);
}

void TestModel::print() {
    qDebug() << "Model:" << valueList;
}

QHash<int, QByteArray> TestModel::roleNames() const {

    QHash<int, QByteArray> roles;
    roles[valueRole]         = "valueRole";
    return roles;
}

int TestModel::rowCount(const QModelIndex & /*parent*/) const {

    return valueList.length();
}

QVariant TestModel::headerData(int /*section*/, Qt::Orientation /*orientation*/, int /*role*/) const {

    return QVariant();
}

Qt::ItemFlags TestModel::flags(const QModelIndex & /*index*/) const {

    return static_cast<Qt::ItemFlags>(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable |  Qt::ItemIsEditable);
}

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

//    qDebug() << QString("Get Data - Row: %1, Col: %2, Role: %3").arg(index.row()).arg(index.column()).arg(role);

    int row = index.row();

    if (row >= 0 && row < valueList.length()) {

        switch(role) {
            case valueRole:
            qDebug() << QString("Get Data - Row: %1, Col: %2, Role: %3").arg(index.row()).arg(index.column()).arg(role);
                return valueList.at(row);
            default:
                return QVariant();
        }
    }

    return QVariant();
}

bool TestModel::setData(const QModelIndex &index, const QVariant &value, int role) {

    qDebug() << QString("Set Data - Row: %1, Col: %2, Role: %3").arg(index.row()).arg(index.column()).arg(role);

    int row = index.row();

    if (row >= 0 && row < valueList.length()) {

        switch(role) {
            case valueRole:
                valueList[row] = value.toBool();
                break;
            default:
                break;
        }

        dataChanged(index, index, QVector<int>() << role);
        print();
    }

    return true;
}

bool TestModel::insertRows(int row, int count, const QModelIndex & /*parent*/) {

    // Check bounds
    if (row < 0 || count < 0) {
        return false;
    }

    if (count == 0) {
        return true;
    }

    if (row > rowCount()) {
        row = rowCount();
    }

    beginInsertRows(QModelIndex(), row, row+count-1);
    endInsertRows();

    return true;
}

bool TestModel::removeRows(int row, int count, const QModelIndex & /*parent*/) {

    // Check bounds
    if (row < 0 || count < 0 || rowCount() <= 0) {
        return false;
    }

    if (count == 0) {
        return true;
    }

    if (row >= rowCount()) {
        row = rowCount() - 1;
    }

    beginRemoveRows(QModelIndex(), row, row+count-1);
    endRemoveRows();

    return true;
}

将您的委托修改为以下内容:

delegate: Rectangle {

    height: 50
    width: 100
    color: "lightgray"

    CheckBox {
        id: checkBox
        anchors.fill: parent
        checked: valueRole

//      onClicked: {
//          valueRole = checked
//      }
    }

    MouseArea {
        anchors.fill: parent
        onClicked: {
            valueRole = !checkBox.checked
        }
    }
}

复选框
的值绑定到
valueRole
,但单击时,它只是用
bool
值覆盖此绑定。如果您以其他方式处理单击,例如用
MouseArea
覆盖
复选框
,您将忽略破坏绑定,一切都将正常工作。

另一个选项是恢复绑定

CheckBox {
    onClicked: {
        valueRole = checked;
        checked = Qt.binding(function() { return valueRole; });
    }
}

这种方法的优点是,如果用户交互不是简单的点击,也就是说,如果用户交互不能简单地用鼠标拦截,那么它也可以工作。

我刚刚测试了这段代码,它可以工作!谢谢你的回答和解释。这很有见地。
dataChanged()
不是一种方法!这是一个信号
qml: attempting to refresh qml
attempting to refresh c++
"Get Data - Row: 0, Col: 0, Role: 257"
"Get Data - Row: 1, Col: 0, Role: 257"
"Get Data - Row: 2, Col: 0, Role: 257"
"Get Data - Row: 3, Col: 0, Role: 257"
"Get Data - Row: 4, Col: 0, Role: 257"
Model: (false, false, false, false, false)

qml: clicked checkbox
"Set Data - Row: 0, Col: 0, Role: 257"
Model: (true, false, false, false, false)

qml: attempting to refresh qml
attempting to refresh c++
"Get Data - Row: 1, Col: 0, Role: 257"
"Get Data - Row: 2, Col: 0, Role: 257"
"Get Data - Row: 3, Col: 0, Role: 257"
"Get Data - Row: 4, Col: 0, Role: 257"
Model: (true, true, true, true, true)

qml: attempting to refresh qml
attempting to refresh c++
"Get Data - Row: 1, Col: 0, Role: 257"
"Get Data - Row: 2, Col: 0, Role: 257"
"Get Data - Row: 3, Col: 0, Role: 257"
"Get Data - Row: 4, Col: 0, Role: 257"
Model: (false, false, false, false, false)
delegate: Rectangle {

    height: 50
    width: 100
    color: "lightgray"

    CheckBox {
        id: checkBox
        anchors.fill: parent
        checked: valueRole

//      onClicked: {
//          valueRole = checked
//      }
    }

    MouseArea {
        anchors.fill: parent
        onClicked: {
            valueRole = !checkBox.checked
        }
    }
}
CheckBox {
    onClicked: {
        valueRole = checked;
        checked = Qt.binding(function() { return valueRole; });
    }
}