How to connect signal from nested qml item from c++ code? - c++

I have a UI written in QML. The UI contains a TextEdit nested somewhere deep in the tree. I want to connect the signal onTextChanged to my c++ logic in the background. How can I access the nested signal from c++?

Sounds like a design issue, you shouldn't really access QML from C++, it is best to keep the interaction one way - access the exposed C++ API from QML only.
In your case, instead of making the connection on the C++ side, you can simply install a handler for the signal in QML:
onTextChanged : cppLogic.callCPPfoo()
This is faster, easier, more flexible and can pass data even if the signal doesn't have data parameters.

Related

QT: Signal / Slot connection via connect or on_

I am new to QT. As far as I can see, there are two ways to connect signals and slots with each other. One way would be using the connect method. When e.g. wanting to put a method ButtonReleased() to the slot that is triggered after the released() signal of a pushButton with name pushButton, one could write:
connect(ui->pushButton, SIGNAL(released()), this, SLOT(ButtonPressed()));
However, as far as I see, one could also define a method with name on_pushButton_released() to achieve the same connection. Is there any difference between both methods and if so, which one is preferred?
Thanks in advance!
There are indeed two main ways to connect signals to slots.
The first one, using the connect method allows to connect any signal to any slot (or signal) as long as the function signatures match. This is the main way to connect signals in Qt.
The second way are member methods that are called on_ObjectName_SignalName(). These are automatically connected by Qt, if a UI element called ObjectName exists and has a signal called SignalName. This is specifically meant for the use case of having some Widget with a separate .ui file, which contains these elements that you want to connect to. As such, this mechanism does not work if you create UI elements "by hand" in your C++ code.
As you can see, the second mechanism has very specific requirements that need to be satisfied to work, although these are not uncommon. So if you have satisfied these conditions I see no Problem in doing it this way, but others may disagree and this is largely personal preference.
Also note: The syntax in your question is the old syntax from Qt4. If you are using Qt5 and newer, it is highly advised to use the new syntax.
You can read more about signals and slots on the Qt Documentation.

Handling Qt C++ events in QML context

The C++ API has QEvent along with multiple other classes derived from it (QMouseEvent, QGestureEvent etc.). QML on the other hand has events too. However I am struggling to find an elegant way of directly processing C++ events in QML.
Usually what I do is I create a custom QQuickWidget (or similar including QQmlEngine), override the QWidget::event(QEvent* event) and upon receiving a specific C++ event I propagate it through signals to QML slots with the QML code being loaded through that widget. This seems like a lot of work and I'm wondering if there is some sort of QML built-in event handling for events that come from C++ context.
In particular I'm interested in handling QGestureEvents in QML but I guess what works for this type of events should also work for any other type of event.
There is no direct support for event handling in QML, even keyboard and mouse are accessible through auxiliary objects.
QEvent itself is not a QObject derived, and as such, the same applies to all the derived events as well. That means no meta-information and no easy way to use from QML.
Since you are interested in a particular type of events, it would be easiest to create your own auxiliary object for those type of events, implement it in C++ and interface it to QML via signals you can attach handlers to.
If QGestureEvent can be copy-constructed you could simply create a Q_GADGET based adapter:
class QmlGestureEvent : public QGestureEvent
{
Q_GADGET
Q_PROPERTY(...) // for the things you want to access from QML
public:
QmlGestureEvent(const QGestureEvent &other) : QGestureEvent(other) {}
};
If it is not copy-constructable you'll have to add data members to the adapter and copy the values from the event.

Signals and Slots in Qt4

I'm trying to create a signal and slot in Qt4 and I am fairly new to Qt. From what I understand in Qt5 it is just created automatically and this is not the case in Qt4 it seems. I'm trying to create a an action when the user clicks on an option in the menu bar at the to of the UI.= I see that there is a Signal/Slot editor at the bottom of the screen with options "Sender", "Signal", "Receiver", and "Slot". I'm not entirely sure how to use this function. Any help is appreciated.
Basically you need to connect your signal and slot
connect(ui->button1, SIGNAL(clicked()), this, SLOT(yourSlot()));
and in this link there is good example about signals and slot: signals and slots in qt.
You seem to have misunderstood.
The difference in Qt 5 is that it offers new syntax to make the connections.
The connection is "automatic" when you don't specify the connection type, i.e. direct, queued, etc, the default is automatic, which makes Qt check the object's thread ownership and select the appropriate connection type.
Connections must either be explicitly made in code, or be made using the UI editor, and while the latter may save you some typing in some cases, in general most of the connections you end up making are explicit in code, so you better learn how to do it, because the UI editor can help you only in a few corner cases. I haven't really used the UI editor for connections, and have tried it once or twice years ago, but the limitation I think is that you can only make connections between UI elements and signals and slots of the widget.
Consider that signal and slot connections are not merely a UI thing, it is a core principle in Qt and UI is just one of its many uses.

QML in C++ app or vice versa [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
Consider the case of a simple GUI displaying the output of rather elaborate calculation.
Now I would like to write a nice, custom GUI using QML.
I would also like to write my background app in QT C++.
I'm sitting in front of the QT documentation and wonder
if I
1) should write a QML application and somehow embed my C++ classes in it
(which is absolutely possible) or if I
2) should write a C++ application
and somehow embed the QML GUI in it and modify QML properties from my classes
(which is again possible)
I already wrote everything in C++ using QT Widgets for the GUI. I only want to move the GUI to QML and keep the C++ classes even though I am willing to rewrite the interface to the GUI.
Possible anser:
The marked solution below suggested keeping the C++ classes and interface the GUI exclusively through SIGNALS and SLOTS. So basically I ended up with a main.cpp that instantiates my main working class and displays the QML GUI like this:
QQuickView viewer;
viewer.setSource(QUrl("./qml/main.qml"));
viewer.show();
then I added myClass and got me an object to do the connections:
MyClass myClass;
QQuickItem* item = viewer.rootObject();
QObject::connect(item, SIGNAL(buttonClicked()), &myClass, SLOT(mySlot()));
QObject::connect(&myClass, SIGNAL(mySignal(QVariant)), item, SLOT(updateGUI(QVariant)));
When implementing the slots and signals in the C++ classes you must use QVariant objects to transfer the data. The QML file then implements SIGNALS e.g. for clicked buttons and SLOTS to receive data to display.
This is exactly what I was hoping for. The only change to my non GUI code was to do all the interactions via SIGNALS and SLOTS. Now I can even use both GUIs (QML / Widgets) for my application.
Just write your core logic in C++, interface it with signals and slots, and you can use the same component with widgets and also with QML.
It is not rocket science, C++ logic allows usage with C++ and QML, JS logic - only QML. C++ and the Qt API is the more sound solution, because from JS you don't really have access to that much functionality of the Qt APIs, only a few methods are "ported" into the QML world. But all the high performance data containers and the execution performance itself is in C++.
If you only need to display results and console is not good enough, I'd rather keep to QtWidgets, because adding the declarative module slows compilation down significantly. The widget module is standalone now, so you are adding "extra" module even with QtWidgets (in Qt4 it was part of QtGui) but it is lighter. After you use widgets for prototyping your core logic, you can then implement a QML interface and just hook that up to the existing signals/slots/properties and bindings using them.
And no, you don't embed QML in C++ classes, it is the other way around, C++ is the more low-level layer, which is used to create QML components. As for the actual instantiation, you can go both ways - if you register a QObject based class to the QML engine, you can instantiate it in QML. Or you could instantiate the class in C++ and only make it available in the QML context - it doesn't really matter. If you need a single object, you better instantiate it in C++ in the main() function and make it available in the QML context, if it is components you intend to instantiate a lot - then create a QML component.
You could prototype the core logic with JS in QML and later port it to C++ if you want too. It looks like twice the effort, but if you make your bed right it is actually a productivity increase, because prototyping is that much faster in QML, catching errors is much safer and informative, and if you make your API well, porting the JS code to C++ is usually a minor nuisance - replace some vars with concrete types, replace some . with -> and stuff like that.
Any "elaborate calculation" you really WANT to ultimately do in C++. Every time the calculation is completed, you can simply emit it as a signal, and automatically display the result to whatever slot the signal is connected, be that in a widget or in QML, or even both at the same time.
This is very opinion based. No 'true' answer possible. For me it is 'easier' to write in QML and 'extend' qml with Qt plugins. That's because I did a big project this way. Others might have other experiences and might because of that like a different approach. None of our 'life stories' could help you much.

Singleton or Signal and Slots?

I am trying to reimplement or modify a tab code in a gui application. They are currently using Qt signal and slots system to handle addition and removal of tabs from the tab bar (For example if a tab was being drag from one tab widget to another, the old tab widget will signal the new tab widget that a new tab is coming). I was thinking rather than using that, I could simplify things using a thread safe singleton class. Then when ever a tab is moved, the widget just call on the singleton rather than emitting a signal.
Thanks
Signals and Slots.
Without even starting why the singleton would be bad, the way the data is updated inside Qt would be messed up by the singleton approach.
Don't do that. You are working within an environment and should use the mechanism the framework provides. What about if the UI in the future will have multiple windows and maybe multiple instances?
If possible you should always try to use the way from the framework you are using. This will also help in the future for the maintenance (upgrades, new hires, etc.)
You want to use a singleton, which will accept messages and dispatch them back ? (note: if you use a garden variety object instead of a singleton, you're essentially implementing an Observer pattern).
Then you are reinventing signals and slots, which use a global state internally. Instead of putting work in reinventing some difficult piece of code, why don't you use the already existing signals and slots ?