首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >qml库与成员函数:不能调用方法‘破坏’为null

问qml库与成员函数:不能调用方法‘破坏’为null
EN

Stack Overflow用户
提问于 2021-04-12 21:02:00
回答 1查看 295关注 0票数 0

在我的代码上下文中,纯JavaScript库(标记为".pragma库“)中的函数与QML中的成员函数之间有什么区别?

代码语言:javascript
复制
import QtQuick 2.15
import QtQuick.Controls 2.15
import "."

ApplicationWindow {
    id: applicationWindow

    width: 400
    height: 400
    visible: true

    function showDialog(params) {
        const comp = Qt.createComponent("qrc:/MyPopup.qml");
        const err = comp.errorString();
        if (err)
            console.log("MyPopup component loading failed:", err);

        const dlg = comp.createObject(params.parent, params);
        console.assert(dlg !== null, "MyPopup object creation failed");
        console.log("opening");
        dlg.open();
    }

    Button {
        text: "Press me"
        anchors.centerIn: parent
        onClicked: {
            console.log("you press button");

            const params = {parent: applicationWindow.contentItem};
            //applicationWindow.showDialog(params); // !!! 1
            CreateDialog.showDialog2(params); // !!! 2
        }
    }
}

我的弹出式窗口:

代码语言:javascript
复制
import QtQuick 2.0
import QtQuick.Controls 2.15

Popup {
    id: view

    width: 300
    height: 300
    onClosed: {
        console.log("onClosed was called", view);
        view.destroy();
    }

    Text {
        anchors.centerIn: parent
        text: "Popup!!!"
    }
}

如果我使用变体(1),如果我打开弹出,然后按"Alt+F4“(在macOS上)或"Command+Q”,所有操作都很好。

但是,如果我将“showDialog”移到“CreateDialog.js”文件中,并在其顶部添加“.pragma库”,那么在使用打开的弹出式退出应用程序时,我会得到:

代码语言:javascript
复制
qrc:/MyPopup.qml:11: TypeError: Cannot call method 'destroy' of null

因此Qt/QML运行时调用死对象的信号。究竟是怎么回事,在“纯javascript”的情况下引用对话框“悬挂”,所以Qt不能正确地销毁它?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-04-12 23:46:14

默认情况下,从QML导入的JavaScript文件与QML组件共享它们的上下文。 --如果从JS文件中删除.pragma library,代码的行为与在主QML文件中运行JS代码的行为相同,因为它们共享相同的上下文。那么,为什么.pragma library会影响到这一点呢?.pragma library创建了一个类似于单例的JS文件,而且由于任何QML文件都可以访问它,所以它的上下文通常被设置为根上下文或一些顶级的孤立上下文(不确定,无法从文档中确定),而不是调用它的文件的上下文。

根据背景文件:

虽然在上下文中实例化的QML对象并不严格属于该上下文,但它们的绑定是。如果上下文被销毁,未决QML对象的属性绑定将停止计算。

我相信你所看到的与第二句相反,在第二句中,根上下文拥有弹出窗口的绑定,并且在它被破坏后调用它的onClosed信号。

因此,您的两个场景描述了:

第一个场景:

  1. 创建、分配applicationWindow父级的弹出窗口,其创建上下文与applicationWindow匹配
  2. 窗口关闭,applicationWindow销毁开始
  3. 因为弹出窗口是applicationWindow的子程序,所以它被销毁了。
  4. applicationWindow上下文被破坏,绑定将停止计算。
  5. 不调用弹出关闭信号,因为它的创建上下文已被破坏,没有引发错误。

第二个场景:

  1. 弹出已创建,指定为applicationWindow父级,但其创建上下文是根上下文
  2. 窗口关闭,applicationWindow销毁开始
  3. 因为弹出窗口是applicationWindow的子程序,所以它被销毁了。
  4. applicationWindow上下文被销毁
  5. 在applicationWindow销毁后,将调用弹出关闭信号,因为其(根)创建上下文仍然存在,而由于信号处理程序中的引用已被销毁,引发错误。

解决这一问题的最好方法可能是在管理对象创建的JS文件中不使用.pramga library。否则,它并不是一个特别令人担忧的错误,因为它足够聪明地知道引用已经被销毁,并且没有访问已释放的内存。您可以通过在调用if (view)之前检查view.destroy()来消除错误

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67065636

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档