为啥我的 QString 没有得到 TextField 的值?

Posted

技术标签:

【中文标题】为啥我的 QString 没有得到 TextField 的值?【英文标题】:Why does not my QString get the value of the TextField?为什么我的 QString 没有得到 TextField 的值? 【发布时间】:2017-10-20 17:23:11 【问题描述】:

我正在尝试将 TextField 的值传递给字符串,我相信 Source 是正确的,但是当我将“值”插入 TextField 并单击按钮时,它什么也不返回,但是如果我设置这个值在 TextField Text:"Example",它返回:"Example",有什么想法吗?

FirstPage.qml

Item 

Rectangle 
    anchors.fill: parent

    ColumnLayout 
        id: layoutLogin
        anchors.centerIn: parent
        anchors.margins: 3
        spacing: 3

        TextField 
            objectName: "login"
            Layout.fillWidth: true
            placeholderText: "Username"
        

        TextField 
            property string password: text
            objectName: "passwordd"
            Layout.fillWidth: true
            placeholderText: "Password"
            echoMode: TextInput.Password
        

        Button 
            id: proccessButton
            text: "Login"
            Layout.fillWidth: true
            onClicked: Login.test()
        
      
   

login.cpp:

Login::Login() 
QQuickView view;
view.setSource(QUrl(QStringLiteral("qrc:/FirstPage.qml")));
QObject *object = view.rootObject();
QObject *login = object->findChild<QObject*>("login");
QObject *password = object->findChild<QObject*>("password");
login_u = login->property("login").toString();
password_u = password->property("password").toString();

void Login::test()
    qDebug() << "user:" << login_u;
    qDebug() << "password" << password_u;

点击“按钮”时的输出:

user: ""
password ""

【问题讨论】:

在哪里触发Login 构造函数来检索值?不应该在test() 操作中完成吗? 您可以放置​​一个可重现的代码,您已经消除了一些重要的细节。 我试试@user0042,结果一样。 @CésarAugusto 尝试您的解决方案,如果您有任何问题,请告诉我,我可以帮助您 对于密码字段,objectName 中有一个错字:objectName: "passwordd" 【参考方案1】:

我的回答会更深入一点,试图解决背景问题,即如何正确地从 C++ 中获取 QML 数据。

第一个任务是实现一个继承自QObject的类并处理用户名和密码属性,如下所示:

在这个类中,我们必须使用 Q_PROPERTY 宏来公开属性,如果我们想从 QML 调用一个函数,它必须以 Q_INVOKABLE 开头。

#ifndef LOGIN_H
#define LOGIN_H

#include <QObject>

#include <QDebug>

class Login : public QObject

    Q_OBJECT
    Q_PROPERTY(QString username READ username WRITE setUsername NOTIFY usernameChanged)
    Q_PROPERTY(QString password READ password WRITE setPassword NOTIFY passwordChanged)
public:
    explicit Login(QObject *parent = nullptr):QObject(parent)

    
    Q_INVOKABLE void test()
        qDebug()<<mUsername<<mPassword;
    

    QString username() const
        return mUsername;
    

    void setUsername(const QString &username)
        if(mUsername == username)
            return;
        mUsername = username;
        emit usernameChanged(mUsername);
    


    QString password() const
        return mPassword;
    

    void setPassword(const QString &password)
    
        if(mPassword == password)
            return;
        mPassword = password;
        emit passwordChanged(mPassword);
    

signals:
    void usernameChanged(QString username);
    void passwordChanged(QString password);
private:
    QString mUsername;
    QString mPassword;
;


#endif // LOGIN_H

然后我们使用 qmlRegisterType 在 QML 旁边注册它,所以现在这是一个 QML 库

#include "login.h"

#include <QGuiApplication>
#include <QQmlApplicationEngine>

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

    QGuiApplication app(argc, argv);

    qmlRegisterType<Login>("com.examples.login", 1, 0, "Login");
    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();

最后我们在 qml 端使用它们分配相应的连接

import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.3
import com.examples.login 1.0

Window 
    visible: true
    width: 640
    height: 480
    title: qsTr("Login")

    Login
        id: login
        username: usernameField.text
        password: passwordField.text          
    

    Rectangle 
        anchors.fill: parent

        ColumnLayout 
            id: layoutLogin
            anchors.centerIn: parent
            anchors.margins: 3
            spacing: 3

            TextField 
                id: usernameField
                textColor: "black"
                Layout.fillWidth: true
                placeholderText: "Username"
            

            TextField 
                id: passwordField
                Layout.fillWidth: true
                placeholderText: "Password"
                echoMode: TextInput.Password
                textColor: "black"
            

            Button 
                id: proccessButton
                text: "Login"
                Layout.fillWidth: true
                onClicked: login.test()

            
        
    

完整的例子可以在下面的link找到

【讨论】:

【参考方案2】:

我认为属性名称应该是文本。 试试这个:

login_u = login->property("text").toString();
password_u = password->property("text").toString();

我意识到您正在获取 Login 类的构造函数中的值。 应该在调用test()的时候获取。

void Login::test()

    QQuickItem *object = m_view->rootObject();
    QObject *login = object->findChild<QObject*>("login");
    QObject *password = object->findChild<QObject*>("password");
    login_u = login->property("text").toString();
    password_u = password->property("text").toString();

    qDebug() << "user:" << login_u;
    qDebug() << "password" << password_u;

在这里工作

【讨论】:

以上是关于为啥我的 QString 没有得到 TextField 的值?的主要内容,如果未能解决你的问题,请参考以下文章

为啥使用 QString::right 在字符串的开头省略逗号?

为啥我的 QDeclarativeItem 没有得到任何鼠标/键盘事件?

为啥我的数据没有得到持久化?

为啥我的 C 结构在输入中没有得到任何数据?

为啥我的数字类型的表单输入没有得到任何价值?

为啥 const QString& 参数返回错误的 const char* 指向数据的指针