0

I'm working on a C++ Qt project that will eventually communicate with the serial port. One part of this is accessing QML objects in the C++ portion. I have code that can set properties of the QML, but accessing those features that are methods now has me stumped. View the following code:

object = view.rootObject();

rect = object->findChild<QObject *>("box");
rect->setProperty("color", "red");                  // Verifies the object tree is accessible
viewer = object->findChild<QObject *>("viewer");    // Access the viewer text box

viewer->append("dummy text");           // OOPS! This doesn't compile!!!

Now, the type as a method setProperty(..), but how do you access methods of an object. "viewer" is a TextArea and I want to first do a selectAll(), then a cut() to clear the box.

The question here is how is this coded? Thanks all.

3
  • Provide QML part. The guess is that you should make it to talk via the property text of that viewer. Commented Mar 7, 2017 at 19:19
  • QML looks something like this. import QtQuick 2.0 import QtQuick.Controls 1.2 Item { width: 350 height: 450 TextArea { id: viewer x: 8 y: 8 width: 223 height: 415 text: "text" font.pixelSize: 12 objectName: "viewer" } Button { id: open x: 251 y: 8 text: "Open" } } Commented Mar 7, 2017 at 20:10
  • @JoeVoytovich - next time include the QML code in the question, where it can be properly formatted. Commented Mar 7, 2017 at 20:50

3 Answers 3

4

Of course it would not compile, QObject doesn't have an append() method.

If it is a C++ function, you will have to qobject_cast to the appropriate type that has it. This however is not always readily available for many of the stock QML types that are implemented in C++, and as C++ types they are not part of the public API and not generally intended for direct use by an end user.

If it is a JS function, you will have to use QMetaObject::invokeMethod. That will also work for C++ functions for which meta data has been generated. Which is also how setProperty() works, whereas setColor() would not work with a QObject* much like append() doesn't.

Last but not least, there is absolutely no good reason for you to be doing those kinds of things from C++. Using QML objects from C++ is poor design and an anti-pattern. You will only develop bad habits trying to do that. Such interactions must be limited to a clearly defined interface using signals, slots and properties. Generally speaking, it is OK for QML to reach into C++, because that only happens through an exposed interface, but the opposite way, even if possible, should not utilized.

Think of it like this - a car uses the engine, the engine doesn't use the car. And the engine control is interfaced through the starter key and the gas pedal, it is not used directly. The C++ stuff should be reserved to the application engine - the high performance or efficiency core logic, or the back-end, whereas the QML part is for the GUI/front-end.

Sign up to request clarification or add additional context in comments.

3 Comments

Yes, I saw that QObject doesn't have the append() method. I did try the qobject_cast process, but couldn't get the right object to case it into. TextArea is defined on the Qt web site as being a QML type. Do these types intermingle (QObject, QML)?
@JoeVoytovich the corresponding type is QQuickTextArea. However it is "private" as a C++ type, so while possible, its direct use is not readily available. So you should try to see if invokeMethod() will work.
Invoke() is a good solution. I tried it, it works, and it's short. 3 for 3! Can't miss with a hat trick. I like the GUI / back-end separation logic too.
2

The author's QML part may expose alias property to operate with desired text field content:

import QtQuick 2.0
import QtQuick.Controls 1.2

Item {
    property alias viewerText: viewer.text // added

    width: 350
    height: 450
    TextArea {
        id: viewer
        x: 8
        y: 8
        width: 223
        height: 415
        text: "text"
        font.pixelSize: 12
        objectName: "viewer"
    }
    Button {
        id: open
        x: 251
        y: 8
        text: "Open"
    }
}

And then the author's C++ part can easily do:

auto* object = view.rootObject();    
viewer = object->findChild<QObject *>("viewer");
viewer->setProperty("viewerText", "dummy text"); // using the new property added

Comments

0

Using the posted answer here using the invoke method, here's the solution that works:

// C++ Code to call function reset()
QMetaObject::invokeMethod(object, "reset");

// QML code to select all text the delete it
function reset() {
    viewer.selectAll()
    viewer.cut()
}

2 Comments

That could also work, although it is the wrongest possible solution. First you are reaching from C++ into QML which is wrong and unnecessary. Second - you don't need to copy all the text into the clipboard just to clear the text area, you can just viewer.text = "". Which you could also easily do from C++ via setProperty("text", "").
I'll try this too. This would be even simpler.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.