【问题标题】:Why is my QML textArea not appending?为什么我的 QML textArea 没有附加?
【发布时间】:2017-11-29 16:59:16
【问题描述】:

我正在尝试编写一些与 QML 对象交互的 Qt C++ 代码。目标是将 TCP 套接字上接收的字符串附加到 GUI 上的文本日志中。每次收到新字符串时,我都会运行 appendText() 函数。我有一个当前工作的实现,它使用 QWidgets 和 .ui 文件。我需要一个相同的 QML 实现。我的 QWidget 实现使用 textBrowser 和 append 函数,如下所示。 “theString”随着程序的运行而变化,每个变化都会被附加,填满文本日志。

//update the text log with data received on TCP socket
void MainWindow::appendText() {
    ui->textBrowser->append(theString);

}

这给了我想要的结果,将每个字符串附加到文本框中。输出应该如下所示。

Control connection successful.
Data connection successful.
Control Packet Receieved: 
1
Control Packet Receieved: 
2
Control Packet Receieved: 
3
Control Packet Receieved: 
4
Control Packet Receieved: 
1
Control Packet Receieved: 
2
Control Packet Receieved: 
3
Control Packet Receieved: 
4

但是,当使用以下代码执行我认为与 QML 对象相同的功能时...

//update the text log with data received on TCP socket
void MainWindow::appendText() {
    QMetaObject::invokeMethod(textbox, "append", Qt::DirectConnection, Q_ARG(QVariant, theString));
    //QQmlProperty(textbox, "text").write(theString);

}

它只附加前两个字符串,除此之外没有更多。输出看起来像这样。

Control connection successful.
Data connection successful.

我已经广泛查看了在 C++ 中调用 QML 方法的文档,但仍然没有任何运气。任何帮助表示赞赏。感谢您的宝贵时间。

【问题讨论】:

    标签: c++ qt text append qml


    【解决方案1】:

    我无法重现您的问题。

    可能的解决方案

    使用import QtQuick.Controls 2.0可能是一个解决方案。

    在这种情况下,我收到以下错误消息:

    QMetaObject::invokeMethod: No such method QQuickTextArea::append(QVariant)
    Candidates are:
        append(QString)
    

    根据错误消息的建议,您现在应该使用QString 而不是QVariant 作为参数类型:

    QMetaObject::invokeMethod(textbox, "append", Qt::DirectConnection, Q_ARG(QString, theString));
    

    更好的选择

    正如Qt所说,你应该avoid manipulating QML object from C++(深入对象树):

    警告:虽然可以使用 C++ 在对象树的深处访问和操作 QML 对象,但我们建议您不要 在应用程序测试和原型设计之外采用这种方法。一 QML 和 C++ 集成的优势在于能够实现 QML 用户界面与 C++ 逻辑和数据集后端分开, 如果 C++ 方面深入到 QML,这个策略就会中断 组件来直接操作它们。

    因此,在 C++ 中实现一个信号可能是更好的选择,它发出新接收到的消息并从 QML 端连接到它。这种方法清楚地将用户界面和编程逻辑分开。

    工作示例代码

    以下代码每秒将"test" 附加到TextArea

    main.cpp:

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QTimer>
    #include <QQuickItem>
    
    QObject *textbox;
    
    void onTimeout()
    {
      QMetaObject::invokeMethod(textbox, "append", Qt::DirectConnection, Q_ARG(QVariant, "test"));
    }
    
    int main(int argc, char *argv[])
    {
      QGuiApplication app(argc, argv);
    
      QQmlApplicationEngine engine;
      engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    
      QTimer t;
      QObject::connect(&t, &QTimer::timeout, &onTimeout);
      textbox = engine.rootObjects().first()->children().first();
    
      t.start(1000);
    
      return app.exec();
    }
    

    main.qml:

    import QtQuick 2.0
    import QtQuick.Window 2.2
    import QtQuick.Controls 1.0
    
    Window
    {
        visible: true
        width: 600
        height: 600
    
        TextArea
        {
            id: textbox
            anchors.fill: parent
        }
    }
    

    【讨论】:

    • 感谢您的回复。当我尝试使用 QString 进行修复时,我收到此错误: QMetaObject::invokeMethod: No such method TextArea_QMLTYPE_31::append(QString) 候选人是:append(QVariant)... 我相当确定前两条消息不是由任何其他方法,因为我拥有的 appendText() 函数是我实际向 GUI 写入任何内容的唯一方法。在此期间,我将尝试基于信号的方法。
    • 您使用的是哪个 Qt/QML 版本?你在使用内置的TextArea 吗?如何在 C++ 中获得textbox?你确定MainWindow::appendText 调用正确吗?
    • 我使用的是 Qt Creator 4.2.1。我在我的 QML 文件中使用 TextArea 对象。 TextArea 对象是 groupBox 对象的子对象。我通过执行此行获得文本框: textbox = groupBox2->findChild("networkStatus");..... 另外我正在使用 QMetaObject:invokeMethod,其中有一个名为 append for TextArea 对象的方法
    • 导入 QtQuick.controls 2.1 修复它!谢谢。
    猜你喜欢
    • 1970-01-01
    • 2012-05-22
    • 2019-01-12
    • 2020-04-15
    • 1970-01-01
    • 2021-11-30
    • 1970-01-01
    • 2021-04-30
    • 2013-05-31
    相关资源
    最近更新 更多