Jzhang
Jzhang

Reputation: 17

QML Connections cannot run normally in Qt6

enter image description here

Problems with QML Connections

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

as the picture shows,I cannot link to my Qt Signal The problem is that QML cannot recognize my Qt signal void onTop(), how can I solve it? In Qt 6 I feel that QML has a lot of problems, it is not as easy to use as traditional QWidget, and there are few related materials.

head file

#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 file

#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()
    }
}

Upvotes: 1

Views: 943

Answers (1)

eyllanesc
eyllanesc

Reputation: 244252

Your code has the following problems:

  • If you are going to declare a signal then you should not use Q_PROPERTY. Remove Q_PROPERTY(NOTIFY onTop).

  • You must establish the contexproperties before loading the .qml since otherwise at the time of loading those objects will not be defined.

  • If you want to connect a signal then the syntax is on<signal> where <signal> must be in camelcase format, in your case it must be onOnTop.

  • In Qt6 the versions of the QML modules are not necessary.

  • Since udp_socket is a child of the class then it is not necessary to eliminate it since it will cause a segmentation fault since you are eliminating the pointer 2 times.

#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()
    }
}

Upvotes: 2

Related Questions