Reputation: 17
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
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