c++ - 使用 QML 构建基本的 Qt 界面
问题描述
我正在开发一个使用在 QML 中创建的用户界面的程序。它的核心程序有两个线程:运行 UI 的主线程和处理所有其余工作的第二个线程。所以程序有一个类用于与 UI 交互,第二个类是后端进程。问题在于将插槽/信号从 UI 类连接到第二个线程上的第二个类。
代码如下: main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "QmlInterface.h"
#include "MainClass.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
qmlRegisterType<QmlInterface>("CppInterface",1,0,"CppInterface");
/* Ui Stuff */
QmlInterface qml;
qml.SetupUI();
/* Main class */
MainClass work;
QObject::connect(&qml, SIGNAL(onButtonClicked()), &work, SLOT(on_ButtonClicked()) );
return app.exec();
}
Qml接口.h
#ifndef QMLINTERFACE_H
#define QMLINTERFACE_H
#include <QObject>
#include <QDebug>
#include <QQmlApplicationEngine>
class QmlInterface : public QObject
{
Q_OBJECT
public:
explicit QmlInterface();
virtual ~QmlInterface();
void SetupUI();
public slots:
Q_INVOKABLE void buttonClicked();
signals:
void onButtonClicked();
private:
QQmlApplicationEngine *engine;
};
#endif // QMLINTERFACE_H
QmlInterface.cpp
#include "QmlInterface.h"
QmlInterface::QmlInterface()
{
}
QmlInterface::~QmlInterface()
{
}
void QmlInterface::SetupUI()
{
engine = new QQmlApplicationEngine;
engine->load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine->rootObjects().isEmpty())
{
qDebug() << "Failed to load UI";
}
}
void QmlInterface::buttonClicked()
{
qDebug() << "Button clicked! Signal to be emited!";
emit onButtonClicked();
}
主类.h
#ifndef MAINCLASS_H
#define MAINCLASS_H
#include <QThread>
#include <QtDebug>
class MainClass : public QThread
{
Q_OBJECT
public:
MainClass();
virtual ~MainClass() {}
public slots:
void on_ButtonClicked();
private:
void run();
};
#endif // MAINCLASS_H
主类.cpp
#include "MainClass.h"
MainClass::MainClass()
{
}
void MainClass::on_ButtonClicked()
{
qDebug() << "Button click received in main class!";
}
void MainClass::run()
{
while(1)
{
QThread::sleep(1);
}
}
最后是 main.qml
import QtQuick 2.11
import QtQuick 2.8
import QtQuick.Controls 2.1
import QtQuick.Window 2.1
import CppInterface 1.0
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
CppInterface
{
id: cpp
}
Button
{
text: "Click me"
onPressed: {
cpp.buttonClicked();
}
}
}
QML 和 QmlInterface 之间的连接工作正常!问题在于 QmlInterface 和 MainClass 之间的连接。
更具体地说,问题在于main.cpp中调用的connect()函数似乎无法将给定信号与来自 MainClass 的给定插槽链接:
QObject::connect(&qml, SIGNAL(onButtonClicked()), &work, SLOT(on_ButtonClicked()) );
解决方案
问题是您创建了 2 个实例QmlInterface
:
QmlInterface qml;
qml.SetupUI();
和
CppInterface
{
id: cpp
}
并且您已经连接了第一个实例的信号,并且您正在使用第二个实例发出信号。
因此,不是创建 2 QmlInterface
,而是创建一个,为方便起见,您无需在 QML 中创建对象,而仅使用以下命令导出在 C++ 中创建的对象setContextProperty()
:
// ...
#include <QQmlContext>
// ...
void QmlInterface::SetupUI()
{
engine = new QQmlApplicationEngine;
engine->load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine->rootObjects().isEmpty())
qDebug() << "Failed to load UI";
else
// export
engine->rootContext()->setContextProperty("cpp", this);
}
*.qml
import QtQuick 2.11
import QtQuick.Controls 2.1
import QtQuick.Window 2.1
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Button
{
text: "Click me"
onPressed: cpp.buttonClicked();
}
}
另一方面,不需要注册为类型,QmlInterface
以便您可以将其删除:
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
/* Ui Stuff */
QmlInterface qml;
qml.SetupUI();
/* Main class */
MainClass work;
QObject::connect(&qml, &QmlInterface::onButtonClicked, &work, &MainClass::on_ButtonClicked );
return app.exec();
}
推荐阅读
- raspberry-pi - ARM 处理器如何使用超过 4GB 的内存?
- xamarin - Xamarin forms ios - b2c 身份验证在模拟器中有效,但在设备中无效
- fiware - fiwarequantumleap 插入 cratedb 不起作用(缺少架构)
- javascript - 在 react 中跟踪 children prop 的值或事件变化
- javascript - 根据图像文件的实际高度和宽度(React)为图像动态跨越网格行和列
- clickhouse - 我应该使用哪些数据类型将 Jaeger 日志从 Kafka 读取到 Clickhouse?
- javascript - 如何通过与地图元素比较来创建新字符串?
- python - Qiskit:如何在量子电路中为每个镜头使用不同的状态?
- django - Django postgresql postgis不正确的空间查找
- android - 从图库或相机返回后不调用 onActivityResult