2017-06-26 20 views
2

我正在嘗試編寫一些與QML對象交互的Qt C++代碼。我們的目標是在附加到GUI上的文本日誌的TCP套接字上接收字符串。每次接收到新字符串時,都會運行appendText()函數。我有一個目前正在使用QWidgets和.ui文件的實現。我需要有一個相同的QML實現。我的QWidget實現使用了textBrowser和append函數,如下所示。 「theString」在程序運行時發生變化,並且每次更改都被追加,填滿文本日誌。爲什麼我的QML textArea不會追加?

//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方法的文檔,但仍然沒有任何運氣。任何幫助表示讚賞。謝謝你的時間。

回答

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++(進深對象樹):

Warning: While it is possible to use C++ to access and manipulate QML objects deep into the object tree, we recommend that you do not take this approach outside of application testing and prototyping. One strength of QML and C++ integration is the ability to implement the QML user interface separately from the C++ logic and dataset backend, and this strategy breaks if the C++ side reaches deep into the QML components to manipulate them directly.

因此,它可能是實現在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(); 
} 

爲主。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 
    } 
} 
+1

感謝您的回覆。當我使用的QString嘗試修復我收到此錯誤: QMetaObject :: invokeMethod中:沒有這樣的方法TextArea_QMLTYPE_31 ::追加(QString的) 考生: 追加(的QVariant)... 我相當肯定前兩個消息不是通過任何其他方法打印的,因爲我所擁有的appendText()函數是我實際向GUI寫入任何內容的唯一方法。在此期間,我將嘗試一種基於信號的方法。 – 9tm09

+0

您正在使用哪種Qt/QML版本?你在使用內建的'TextArea'嗎?你如何在C++中獲得'textbox'?你確定MainWindow :: appendText被正確調用嗎? – m7913d

+0

我正在使用Qt Creator 4.2.1。我在我的QML文件中使用了一個TextArea對象。 TextArea對象是一個groupBox對象的子對象。我通過這樣做獲取文本框:textbox = groupBox2-> findChild (「networkStatus」); ..... 另外我正在使用QMetaObject:invokeMethod,其中有一個方法稱爲Append for TextArea對象 – 9tm09