QML Connections 在 Qt6 中无法正常运行

Posted

技术标签:

【中文标题】QML Connections 在 Qt6 中无法正常运行【英文标题】:QML Connections cannot run normally in Qt6 【发布时间】:2021-08-27 00:28:22 【问题描述】:

QML 连接问题

qrc:/main.qml:12:5: QML Connections: Detected function "onTop" in Connections element. This is probably intended to be a signal handler but no signal of the target matches the name.
qrc:/main.qml:13: ReferenceError: classA is not defined

如图所示,我无法链接到我的 Qt Signal 问题是 QML 无法识别我的 Qt 信号 void onTop(),我该如何解决?在 Qt 6 中 感觉QML问题很多,没有传统QWidget那么好用,相关资料也很少。

头文件

#pragma once
#include <QOBject>
#include <QUdpSocket>
class CupSingleHelper : public QObject

    Q_OBJECT
    Q_PROPERTY(NOTIFY onTop)
public:
    CupSingleHelper(QObject *parent = nullptr);
    ~CupSingleHelper();
public:
    void initSocket();
    void setAppPid(qint64 app_pid);
    void readData();
    Q_INVOKABLE void printStr2();
public:
    QUdpSocket* udp_socket = nullptr;
    qint64 pid;
public slots:
    void printStr();

signals:
    void onTop();
;

cpp 文件

#include "CupSingleHelper.h"
#include <QNetWorkDatagram>
#include <qmessagebox.h>
#include <QDebug>
CupSingleHelper::CupSingleHelper(QObject* parent)

    


void CupSingleHelper::printStr()

    qDebug() << "1111111";

void CupSingleHelper::printStr2()

    qDebug() << "22222";


void CupSingleHelper::setAppPid(qint64 app_pid)

    this->pid = app_pid;


void CupSingleHelper::initSocket()

    QString data = ":start";
    data.insert(0, QString::number(pid));

    QByteArray byte_data = data.toLatin1();

    udp_socket = new QUdpSocket(this);
    bool sStatus = false;
    sStatus = udp_socket->bind(QHostAddress::LocalHost, 8898);
    if (sStatus == false)  udp_socket->writeDatagram(byte_data, QHostAddress::LocalHost, 8889); exit(1); 
    connect(udp_socket, &QUdpSocket::readyRead, this, &CupSingleHelper::readData);

    udp_socket->writeDatagram(byte_data, QHostAddress::LocalHost, 8889);


void CupSingleHelper::readData()

    while (udp_socket->hasPendingDatagrams())
    
        QNetworkDatagram datagram = udp_socket->receiveDatagram();
        QString receive_data = datagram.data().data();
        QString temp = receive_data.section(":", 0, 0);
        if (temp.toInt() == pid)
        
            break;
        
        temp = receive_data.section(":", 1, 1);
        if (temp.compare("start") == 0)
        
            emit  onTop();
        
    


CupSingleHelper::~CupSingleHelper()

    if(udp_socket != nullptr)
    
        delete[]udp_socket;
    

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QTranslator>
#include <QLocale>
#include "CupSingleHelper.h"

int main(int argc, char *argv[])

#if defined(Q_OS_WIN)
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
    QGuiApplication app(argc, argv);

    CupSingleHelper cup_single_helper;
    qint64 app_pid = QCoreApplication::applicationPid();
    cup_single_helper.setAppPid(app_pid); //set process id
    cup_single_helper.initSocket();//init udpsocket to listen


    QTranslator t;
    QLocale ql;
    //Check system language and load
    if (ql.language() == QLocale::Chinese)
    
        bool status = t.load(":/x64/Debug/cuptools_zh.qm");
    
    if (ql.language() != QLocale::English)
    
        app.installTranslator(&t);
    


    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;
    
    QQmlContext* rootContext = engine.rootContext();
    rootContext->setContextProperty("classA",&cup_single_helper);

    return app.exec();

main.qml

import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.2

Window 
    visible: true
    width: 500
    height: 720
    title: qsTr("CupTools") 
    property var strd: "22222"
    
    Connections 
       target: classA
         function onTop() 
           label12.text = strd 
         
    

    Text 
     id: label12
     anchors 
        top: parent.top
        horizontalCenter: parent.horizontalCenter
        topMargin: 20
     
     text:"11111"
    

    Button 
         id: mbutton
         anchors.centerIn:parent
         text: "Click"
         onClicked: classA.printStr()
    

【问题讨论】:

【参考方案1】:

您的代码存在以下问题:

如果你要声明一个信号,那么你不应该使用 Q_PROPERTY。删除Q_PROPERTY(NOTIFY onTop)

您必须在加载 .qml 之前建立上下文属性,否则在加载时不会定义这些对象。

如果你想连接一个信号,那么语法是on&lt;signal&gt;,其中&lt;signal&gt;必须是驼峰格式,在你的情况下它必须是onOnTop。

在 Qt6 中,QML 模块的版本不是必需的。

由于 udp_socket 是该类的子类,因此没有必要消除它,因为它会导致分段错误,因为您要消除指针 2 次。

#ifndef CUPSINGLEHELPER_H
#define CUPSINGLEHELPER_H

#include <QObject>

class QUdpSocket;

class CupSingleHelper : public QObject

    Q_OBJECT
public:
    CupSingleHelper(QObject *parent = nullptr);
    ~CupSingleHelper();
public:
    void initSocket();
    void setAppPid(qint64 app_pid);
    void readData();
    Q_INVOKABLE void printStr2();
public:
    QUdpSocket* udp_socket = nullptr;
    qint64 pid;
public slots:
    void printStr();

signals:
    void onTop();
;

#endif // CUPSINGLEHELPER_H
#include "cupsinglehelper.h"

#include <QNetworkDatagram>
#include <QUdpSocket>

CupSingleHelper::CupSingleHelper(QObject* parent):QObject(parent)




void CupSingleHelper::printStr()

    qDebug() << "1111111";

void CupSingleHelper::printStr2()

    qDebug() << "22222";


void CupSingleHelper::setAppPid(qint64 app_pid)

    this->pid = app_pid;


void CupSingleHelper::initSocket()

    QString data = ":start";
    data.insert(0, QString::number(pid));

    QByteArray byte_data = data.toLatin1();

    udp_socket = new QUdpSocket(this);
    bool sStatus = false;
    sStatus = udp_socket->bind(QHostAddress::LocalHost, 8898);
    if (sStatus == false)  udp_socket->writeDatagram(byte_data, QHostAddress::LocalHost, 8889); exit(1); 
    connect(udp_socket, &QUdpSocket::readyRead, this, &CupSingleHelper::readData);

    udp_socket->writeDatagram(byte_data, QHostAddress::LocalHost, 8889);


void CupSingleHelper::readData()

    while (udp_socket->hasPendingDatagrams())
    
        QNetworkDatagram datagram = udp_socket->receiveDatagram();
        QString receive_data = QString::fromUtf8(datagram.data());
        QString temp = receive_data.section(":", 0, 0);
        if (temp.toInt() == pid)
        
            break;
        
        temp = receive_data.section(":", 1, 1);
        if (temp.compare("start") == 0)
        
            emit  onTop();
        
    


CupSingleHelper::~CupSingleHelper()


#include "cupsinglehelper.h"

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>


int main(int argc, char *argv[])

#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif

    QGuiApplication app(argc, argv);

    CupSingleHelper cup_single_helper;
    qint64 app_pid = QCoreApplication::applicationPid();
    cup_single_helper.setAppPid(app_pid); //set process id
    cup_single_helper.initSocket();//init udpsocket to listen

    QQmlApplicationEngine engine;
    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) 
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    , Qt::QueuedConnection);

    QQmlContext* rootContext = engine.rootContext();
    rootContext->setContextProperty("classA",&cup_single_helper);

    engine.load(url);

    return app.exec();

import QtQuick
import QtQuick.Window
import QtQuick.Controls

Window 
    visible: true
    width: 500
    height: 720
    title: qsTr("CupTools")
    property string strd: "22222"

    Connections 
        target: classA
        function onOnTop()
            label12.text = strd
        
    

    Text 
        id: label12
        anchors 
            top: parent.top
            horizontalCenter: parent.horizontalCenter
            topMargin: 20
        
        text:"11111"
    

    Button 
        id: mbutton
        anchors.centerIn:parent
        text: "Click"
        onClicked: classA.printStr()
    

【讨论】:

以上是关于QML Connections 在 Qt6 中无法正常运行的主要内容,如果未能解决你的问题,请参考以下文章

运行时更改Connections的target

QML - .qml 文件中的“连接”不会触发来自 python 脚本的信号

在QML :: Image视图上更新多个QImages仅显示最后发送的QImages

无法在 Loader QML 文件中保存 QML 对象

QML TableView:如何绑定到 selection.onSelectionChanged()

Qt6.2发布(含项目代码升级到Qt6吐血经验总结)