我的源代码如下:
我有2个qml文件。已从maim.qml文件中调用了第二个qml文件。我想使用信号和插槽方法从第二个qml文件中获取文本。
main.qml文件:
ApplicationWindow {
id: applicationWindow1
StackLayout {
id: swipeView
anchors.left: sideBar.right
anchors.right: parent.right
anchors.bottom: tabBar.top
anchors.top: parent.top
currentIndex: tabBar.currentIndex
firstpage{}
Secondpage{}
}
TabBar {
id: tabBar
height: 42
anchors.bottom: parent.bottom
anchors.left: sideBar.right
anchors.right: parent.right
currentIndex: swipeView.currentIndex
TabButton {
text: qsTr("firstpage")
}
TabButton {
text: qsTr("Secondpage")
}
}
secondpage.qml
Item{
signal submitTextField(string text)
// this function is our QML slot
function setTextField(text){
console.log("setTextField: " + text)
textField1.text = text
}
visible: true
width: 360
height: 360
TextField {
id: textField1
x: 31
y: 169
placeholderText: qsTr("Enter some text...")
}
Button {
x: 193
y: 167
text: qsTr("Uppercase me!")
onClicked:
// emit the submitTextField signal
submitTextField(textField1.text)
}
}
代码C ++:HandleTextField.h文件
class HandleTextField : public QObject
{
Q_OBJECT
public:
explicit HandleTextField(QObject *parent = 0) {}
signals:
void setTextField(QVariant text);
public slots:
void handleSubmitTextField(const QString& in)
{
qDebug() << "c++: HandleTextField::handleSubmitTextField:" << in;
emit setTextField(in.toUpper());
}
}
main.cpp文件
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
QQuickView view;
view.setSource(QUrl(QStringLiteral("qrc:/secondpage.qml")));
QObject *item = view.rootObject();
HandleTextField handleTextField ;
QObject::connect(item,SIGNAL(submitTextField(QString)),&handleTextField ,SLOT(handleSubmitTextField(QString)));
QObject::connect(&handleTextField ,SIGNAL(setTextField(QVariant)),item,SLOT(setTextField(QVariant)));
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
->>当我按下按钮时,没有任何动作。请告诉我我在做什么错。
谢谢
答案 0 :(得分:0)
该代码最明显的问题是,您实际上从未使用过创建并secondpage
到的connect()
实例。也没有在其中创建QQuickView
的{{1}}。 QQmlApplicationEngine
是您加载并显示main.qml
的地方,并且在其中创建了secondpage
的全新实例。
假设您有使用中间HandleTextField
类的正当理由(而不是仅在不涉及C ++的QML中直接连接QML信号/插槽),那么我建议您采用另一种策略。看起来您至少已经读过Interacting with QML Objects from C+的某些内容,但要特别注意此特定部分中显示的警告:
警告:尽管可以从C ++访问QML对象并对其进行操作,但除测试和原型设计目的外,不建议使用此方法。 ...
要修复您现有的代码(如果最终选择此路由):
main.qml
ApplicationWindow {
id: applicationWindow1
StackLayout {
id: swipeView
...
Secondpage {
objectName: "mySecondPage" // add an object name
}
}
...
}
main.cpp
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
// First load the main QML file, which also loads the Secondpage item you want to access.
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
HandleTextField handleTextField;
// Here we find the "Secondpage" item loaded into main.qml by its objectName property
QObject *item = engine.rootObjects().first()->findChild<QObject *>("mySecondPage");
if (item) {
QObject::connect(item, SIGNAL(submitTextField(QString)), &handleTextField, SLOT(handleSubmitTextField(QString)));
QObject::connect(&handleTextField, SIGNAL(setTextField(QVariant)), item, SLOT(setTextField(QVariant)));
}
return app.exec();
}
注意:代码未经测试。检查stderr
(控制台)上来自Qt的任何警告,以确保这些connect()
操作实际上成功完成。这种方法的另一个问题是,“旧样式” Qt连接只能在运行时进行验证(与“新样式”在编译时进行验证),并且只有在积极查看{{ 1}}输出。但这是连接到QML信号/插槽的唯一方法。
答案 1 :(得分:0)
您的第一个错误是您认为使用QQuickView创建的窗口与在main.qml中创建的窗口相同,因为不是,它们是2个不同的对象。
QML和C ++有2 approaches可以交互:
Pulling References from QML:这是您要实现的方法,但是它有很多不便之处,因为使用例如您没有使用的对象名来搜索对象,除了在复杂结构中之外,还很复杂还是无法获得,除了很多QML对象是由您在另一时间获得的对象创建和销毁的,我可以指向非保留内存,而且C ++代码对QML有依赖性,所以这种方法是不是最好的,也不推荐。
Pushing References to QML:此方法没有问题,因为使用setContextProperty导出对象时,该对象在所有QML中都是可见的,因为它是全局的,因此,如果创建或消除了QML对象,则不会会产生类似前一种方法的问题,我们不需要对象名,就可以像在QML中创建对象一样建立连接。
如上所述,我将使用第二种方法:
main.cpp
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
HandleTextField handleTextField;
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("handleTextField", &handleTextField);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
Secondpage.qml
Item{
Connections{
target: handleTextField
onSetTextField: textField1.text = text // <---
}
visible: true
width: 360
height: 360
TextField {
id: textField1
x: 31
y: 169
placeholderText: qsTr("Enter some text...")
}
Button {
x: 193
y: 167
text: qsTr("Uppercase me!")
onClicked: handleTextField.handleSubmitTextField(textField1.text) // <---
}
}
main.qml 不应修改。