2017-06-26 10 views
2

Ich versuche, Qt C++ - Code zu schreiben, der mit QML-Objekten interagiert. Das Ziel besteht darin, dass Zeichenfolgen an einem TCP-Socket empfangen werden, der an ein Textprotokoll auf der GUI angehängt wird. Jedes Mal, wenn eine neue Zeichenfolge empfangen wird, führe ich die Funktion appendText() aus. Ich habe eine Implementierung dieser derzeit arbeiten, die QWidgets und eine .ui-Datei verwendet. Ich brauche eine identische QML-Implementierung. Meine QWidget-Implementierung verwendet einen TextBrowser und die Append-Funktion wie die folgende. "theString" ändert sich, wenn das Programm ausgeführt wird und jede Änderung angehängt wird, wodurch das Textprotokoll gefüllt wird.Warum hängt meine QML textArea nicht an?

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

} 

Das gibt mir das gewünschte Ergebnis, jede Zeichenfolge in das Textfeld anhängt wie sie hereinkommen. Die Ausgabe wie folgt aussehen sollte.

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 

Wenn jedoch das tun, was ich glaube, die gleiche Funktion mit einem QML-Objekt mit dem folgenden Code sein ...

//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); 

} 

Es wird nur die ersten beiden Strings anhängt, und nicht mehr darüber hinaus . Die Ausgabe sieht stattdessen so aus.

Ich habe die Dokumentation zum Aufruf von QML-Methoden in C++ ausgiebig durchgesehen und habe immer noch kein Glück gehabt. Jede Hilfe wird geschätzt. Vielen Dank für Ihre Zeit.

Antwort

1

Ich kann Ihr Problem nicht reproduzieren.

Mögliche Lösung

Es wurde eine Lösung import QtQuick.Controls 2.0 zu verwenden sein kann.

In diesem Fall erhalte ich die folgende Fehlermeldung:

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

Besser:

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

Wie die Fehlermeldung vorgeschlagen, Sie QString jetzt statt QVariant als Parametertyp verwenden sollten Alternative

Wie von Qt erwähnt, sollten Sie avoid manipulating QML object from C++ (tief in den Objektbaum):

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.

Daher kann es eine bessere Alternative sein, um ein Signal in C++, die die neu empfangenen Nachrichten auszusenden und zu implementieren, um es von der QML Seite zu verbinden. Dieser Ansatz trennt Benutzerschnittstelle und Programmierlogik klar voneinander.

Arbeitsbeispiel Code

Der folgende Code anhängt "test" zum TextArea jede Sekunde.

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 
    } 
} 
+1

Danke für die Antwort. Wenn ich das Update mit QString versuchen erhalte ich diesen Fehler: QMetaObject :: InvokeMethod: Keine solche Methode TextArea_QMLTYPE_31 :: append (QString) Kandidaten sind: append (QVariant) ... ich ziemlich sicher bin, die ersten beiden Nachrichten werden nicht mit einer anderen Methode gedruckt, weil die Funktion appendText(), die ich habe, die einzige ist, in der ich tatsächlich etwas in die GUI schreibe. Ich werde in der Zwischenzeit einen signalbasierten Ansatz versuchen. – 9tm09

+0

Welche Qt/QML-Version verwenden Sie? Verwenden Sie den eingebauten 'TextArea'? Wie erhalten Sie 'textbox' in C++? Sind Sie sicher, dass 'MainWindow :: appendText' korrekt aufgerufen wird? – m7913d

+0

Ich verwende Qt Creator 4.2.1. Ich verwende ein TextArea-Objekt in meiner QML-Datei. Das TextArea-Objekt ist das untergeordnete Objekt eines GroupBox-Objekts. Ich erhalte Textbox, indem ich diese Zeile tue: textbox = groupBox2-> findChild ("networkStatus"); ..... Auch ich benutze QMetaObject: invokeMethod, wo es eine Methode namens append für TextArea Objekte gibt – 9tm09

Verwandte Themen