【问题标题】:QML Remove Animation of ListView Item with a QSqlTableModelQML 使用 QSqlTableModel 删除 ListView 项的动画
【发布时间】:2020-09-18 10:05:51
【问题描述】:

我在后台使用带有 QSqlTableModel 的列表视图。我还为列表视图元素使用 SwipeDelegate 来提供“删除按钮”,如下所示:

现在按下按钮时,使用 QSqlTableModel 子类中的以下代码从数据库中删除项目:

void qsoModel::deleteQSO(int id) {
    removeRow(id);
    submitAll();
}

附带问题:当我理解正确时,removeRow 隐式调用 beginRemoveRows(...) 和 endRemoveRows()?

对于 ListView,我使用了一个移除转换:

    ListView {
        id: listView
        anchors.fill: parent
        model: qsoModel

        //...

        delegate: QSOItem {}

        remove: Transition {
               NumberAnimation { property: "opacity"; from: 1.0; to: 0; duration: 400 }
               NumberAnimation { property: "scale"; from: 1.0; to: 0.0; duration: 400 }
        }

但是,如果我按下删除按钮,则不会显示动画。列表元素很快就消失了。任何想法为什么会发生这种情况?

完整的源代码可以在这个提交中找到:https://github.com/myzinsky/cloudLogOffline/tree/b501d41a0f23d40139cfca9a6d4f724f4ab251b2

【问题讨论】:

  • 您不是必须使用ParallelAnimation 来组合您的动画吗?我记得Transition 应该只包含一个动画项。
  • qml remove: Transition { ParallelAnimation { running: true NumberAnimation { property: "opacity"; from: 1.0; to: 0; duration: 400 } NumberAnimation { property: "scale"; from: 1.0; to: 0.0; duration: 400 } } } 也无济于事:(
  • 从我可以看到删除动画根本没有触发:(

标签: qt listview qml qtquick2 qsqltablemodel


【解决方案1】:

从 github 上的代码来看,模型似乎正在执行 beginRemoveRows()endRemoveRows() 方法,所以我认为这不是问题。而且您说记录已从数据库中删除,所以我认为问题与 qml 更相关。

所以关于 qml 动画有几件事:

首先,如果您希望不透明度和缩放动画并行,您需要将它们包装在ParallelAnimation 中。第二件事是您需要为removeDisplaced 指定一个转换,否则当您从列表中删除一个项目时将在列表中向上移动的项目只是被推送到覆盖正在执行动画的记录的新位置移动。 如果您将转换分配给removeDisplaced,您应该能够看到这一点,如下所示。

removeDisplaced:Transition{
    NumberAnimation{
        property:"y" // Specifying "y" so the displaced records slowly proceed upwards
        duration:5000 // 5s should be enough to see what's actually happening
        easing.type: Easing.InOutQuad
    }
}

编辑:

我在原帖中提到的问题并不是唯一的问题。问题是removeRow() 函数没有调用beginRemoveRows()endRemoveRows()!如果您将这些调用包裹在 removeRow() 调用周围,您将看到动画正在发生。但是您仍然需要为 removeDisplaced 分配一个转换以查看正在发生的一切。

由问题作者编辑

这个想法是在 QML 端的动画之后更新模型:

remove: Transition {
    SequentialAnimation {
        NumberAnimation {
            property: "opacity"
            from: 1.0
            to: 0
            duration: 400
        }
        ScriptAction {
            script: {
                qsoModel.select()
            }
        }
    }
}

我只是在 QML 端完成动画时调用 select

【讨论】:

  • 我想我们快到了。但是,我更改了这样的代码:void qsoModel::deleteQSO(int id) { beginRemoveRows(QModelIndex(), id, id); removeRow(id); submitAll(); endRemoveRows(); } 现在总是从视图中删除两行。但是从数据库中只删除了一行。它真的很奇怪。还有什么提示吗?非常感谢!
  • 啊发现问题了。它与 submitAll 有关。我现在确实避免了。当前代码在这里:github.com/myzinsky/cloudLogOffline/commits/…
  • 很高兴我能帮上忙 :)
  • 很抱歉再次打扰您。但它仍然无法正常工作。动画还是不错的。但是当我删除一些东西时。它并不总是从数据库中删除。有时该行会保留在数据库表中,而删除的行会在下一次应用程序启动时再次出现。你能看看这里还有什么问题吗:github.com/myzinsky/cloudLogOffline/tree/…谢谢!
  • 所以,我发现的问题是该条目已从数据库中删除,但并未从模型中删除。这是预期的行为,文档中说“删除立即提交到数据库。模型为成功删除的行保留一个空白行,直到使用 select() 刷新。” ->doc.qt.io/qt-5/qsqltablemodel.html#removeRows。这就是为什么如果再次打开 ListView,模型会显示一个空行。