Best way to send a QBitArray to QML App? - qt

I'm quite a beginner in QtQuick, and I'm working on a small project where I have a C++ class (that I intend to register as a QML Type later) that, everytime my QML app feeds it some input, produce a QBitArray which gets read by QML and is outputted as a grid. (Basically, let's say I'm working on a 2D game with a board, where every cell has two possible states, and the list of states is produced by C++)
I'm wondering about the best way to make QML reads the BitArray. The most obvious solution to me would be to set it as a property, but QBitArray isn't a QObject (I guess I could inherit it and Qobject in a wrapper, but it feels unelegant).
I could also call a method of MyCLass wrapping the BitArray, but I'm wondering about threading overhead. If my object has been created in QML/JS, will there be overhead to call its C++ methods ?
So, in conclusion, what is the most elegant/efficient/idiomatic way to do this ?

Related

Qt Quick Game Loop

This is one of the things that still confuses me about QML / QtQuick: How shall I implement a simple game like pong that uses a loop?
I googled a bit and looked through similar questions here but none of them addressed the following:
I want to create a simple game like pong that uses a loop. In this loop first all the objects are updated (in case of pong the ball and the bars) and then everything is rendered. For the rendering part I think QML will do the job once all the properties are set.
I want to use QML and QtQick and not QGraphicsScene.
I have seen some examples that just use a timer and then adjust the properties, for example this one: https://github.com/NicholasVanSickle/QtQuickTests/blob/master/Pong.qml But is this really the way to do it. In this case you would have the loop that updates the QML properties and the timer as well and I don't understand how the work together.
Also there are some game engines that use QML. I would like to know how to use QML within a game loop. For example could you write the game loop in C++ and then have QML on top of it? Or what is the recommended way of doing it. Sadly I could not find this in any of the Qt documentation.
I had a similar question when I first started with Qt and got the same answers you're getting (which are correct). It's a different way of thinking than if you had come from using say, SDL.
I want to add an approach that lets you have some control over the updates. It's been a while since someone shared this with me, but from what I remember, it has something to do with ensuring a consistent update frequency.
Regardless of whether or not it's an improvement over just using a simple timer or not, having some actual code will help get you started. In addition, having the delta (to calculate the position of the ball and paddles) is something you'd have to do yourself, which this code already does for you.
Here's the meat of GameTimer:
void GameTimer::doUpdate()
{
// Update by constant amount each loop until we've used the time elapsed since the last frame.
static const qreal delta = 1.0 / mFps;
// In seconds.
qreal secondsSinceLastUpdate = mElapsedTimer.restart() * 0.001;
mRemainder += secondsSinceLastUpdate;
while (mRemainder > 0) {
emit updated(delta);
mDateTime = dateFromSimulatedTime();
mRemainder -= delta;
mSimulatedTime += delta;
}
}
It's used in C++ like this:
void DirectPather::timerUpdated(qreal delta)
{
QHashIterator<QuickEntity*, DirectPathData> it(mData);
while (it.hasNext()) {
it.next();
QuickEntity *entity = it.key();
DirectPathData pathData = it.value();
if (mSteeringAgent->steerTo(entity, pathData.targetPos, delta)) {
mData.remove(entity);
}
}
}
Since this example (quickpather) is QML-based, it has a complex setter for connecting to the timer. If you don't need stuff to be in QML like the example is, you can just create the timer in C++ and connect to its update signal directly wherever necessary:
connect(mTimer, &GameTimer::updated, foo, &MyGameObject::update);
// ...
connect(mTimer, &GameTimer::updated, bar, &MyOtherGameObject::update);
The delta is in seconds (1.0 == one second).
You can take anything you need from the example to help you get started with your game.
To answer some of your questions directly:
I have seen some examples that just use a timer and then adjust the properties, for example this one: https://github.com/NicholasVanSickle/QtQuickTests/blob/master/Pong.qml But is this really the way to do it. In this case you would have the loop that updates the QML properties and the timer as well and I don't understand how the work together.
I wouldn't recommend doing the logic in QML/JavaScript as this game does. C++ is better suited to this (aka faster) than JavaScript. Things like scripting are well suited for JavaScript though.
Also there are some game engines that use QML. I would like to know how to use QML within a game loop. For example could you write the game loop in C++ and then have QML on top of it? Or what is the recommended way of doing it. Sadly I could not find this in any of the Qt documentation.
My "engine" uses C++ for all of the logic (except scripts, which are kept relatively small) and QML for the GUI and also the entities (animations, sprites, etc.).
I don't think there's any documentation about this exact topic (games written in C++ with QML frontends), but there are some QML-based game examples:
http://doc.qt.io/qt-5/qtquick-demos-maroon-example.html
http://doc.qt.io/qt-5/qtquick-demos-samegame-example.html
You don't need a game loop in QML, the whole thing is event driven and powered by an underlying event loop anyway.
You can readily tap into that, use timers, signals, animations and what not out of the box.
Game loop are locking in nature. And in QML you can only use the main thread. And thou shalt not lock the main thread - it has to spin or your app will stop responding.

Text in Custom QQuickItem

I am implementing a Custom QQuickItem which should be able to make a lineplot (x vs y). For performance reasons I did this using QSGNodes. I wonder what is the best way to implement the Text-Labels for the x-ticks (they should get set automatically according to the data range).
Should I use a QQuickPaintedItem or is there a way to do it via the QQuickItem?
Or is it possible to dynamically create text qml types ( http://doc.qt.io/qt-5/qml-qtquick-text.html) in my c++ file?
Don't over-complicate things by reinventing wheels. QML already has a Text type.
There is a downside - the decision to not have a public API to use the QML types from C++ in their C++ form. And I would not recommend creating QML objects from C++, it is just counterproductive.
Which means that your custom QML type will not be implemented purely in C++, you can implement the "core" stuff in C++ and still compose the complete type on the QML side, where you also get to use bindings, anchors, models, positioners, dynamic scoping and all that good stuff that is hard to do in C++.
This is not uncommon, lots of the stock QML controls are implemented this way - an abstract C++ core exposed to QML, where it is finished into a complete control in QML syntax.

How to efficiently expose many C++ data members of a single object to QML?

I have a C++ object pointer with many data members. I need them all available in QML. One obvious way would be to create a Q_PROPERTY for each member so they can be individually accessed via QML. However, if we are talking about dozens of data members, well that's a lot of lines of Q_PROPERTY, not to mention having to individually handle these in QML as separate properties as well (especially if dealing with "on changed" signals for each property).
I am wondering if it is possible to make a single Q_PROPERTY that would include all the data members I need. But what is not clear to me is the apparent mismatch between the types that QML supports and the types you can list in a Q_PROPERTY. For example, in QML, we have a basic string but its corresponding lising in a C++ Q_PROPERTY must be QString:
Q_PROPERTY(QString datastring READ showdata NOTIFY datastringChanged)
//in QML, `datastring` is just a plain string
Would there be more complex properties like lists or arrays that can be easily matched? QML has a list type and C++ has the QList but are these the same thing? Where can I find a listing of compatible types between C++ and QML?
On the other hand, having individual Q_PROPERTY for each data member could likely be better performance (my data is large and often changing) since the QML would not need to parse anything, perhaps.
Would there be more complex properties like lists or arrays that can
be easily matched? QML has a list type and C++ has the QList but are
these the same thing? Where can I find a listing of compatible types
between C++ and QML?
Have a look at the C++/JS data conversion help page. I think the list missed that QList<QObject*> is also possible.
On the other hand, having individual Q_PROPERTY for each data member
could likely be better performance (my data is large and often
changing) since the QML would not need to parse anything, perhaps.
Maybe, yes, depends on your performance needs. A C++ QList gets converted to a JavaScript list when accessed from QML/JS. That's a bit of conversion overhead indeed. Also, ff an item in the list changes, you need to emit the notify signal for the complete property, and every JS binding in which the list was used needs to be reevaluated, which will again be many list conversions. That could be better by having more fine-grained properties, but it really depends.
Btw, with Qt 5.1 there now is MEMBER, which makes writing Q_PROPERTYs a bit easier.

qt performance – OpenGL

i wan't to use Native OpenGL in the paint function of my widgets(QPainter), to improve performance.
i saw that there is function QPainter::begin/endNativePainting(), that can help me.
but i can't find examples for that...
i wanted to know if those functions are low cost, or evry use of them reduce performance?
2.can i define beginNativePainting() and endNativePainting(), in general for all the widgets i use, instead of using that in every paint function i have.
tnx for any help....
There is some basic example code right in the documentation: http://doc.qt.io/qt-4.8/qpainter.html#beginNativePainting
The functions themselves should be fairly low-cost, but calling them might still cause a noticeably overhead, because Qt has to flush its internal painting queue on the beginNativePainting() call and probably has to assume that everything is changed as soon as endNativePainting() is called.
For the second part I am not sure if I understand what you are aiming at. Basically if you have a QPainter object, you can call beginNativePainting() once. But you have to match it with an endNativePainting() call. So the usual place would be the paint() method.
Qt is using a range of OpenGL functionalities to implement its 2D painting, including custom shaders and various frame buffers. It puts OpenGL into a pretty messy state.
beginNativePainting / endNativePainting are there to allow Qt's drawing engine to save this context and retrieve it once the user is done drawing.
It would have been nice to have the xxxNativePainting methods do the contrary (i.e. automatically save and restore user configuration of OpenGL), but since Qt allows to call OpenGL primitives directly, saving the global state is nigh impossible without tons of code and potential serious performance hit.
Instead, these methods simply save Qt's internal OpenGL state and, rather than having user code start in a configuration that would be meaningless anyway (and likely to change with each new Qt release), reset OpenGL to a "neutral" state.
It means that, inside a begin/end section, you will start with a clean slate: no shader linked, no vertex array, most of global parameters reset, etc.
Contrary to a simple QGLWidget / PaintGL scenario where you can afford to setup the global OpenGL state once and for all and simply call the rendering primitives each frame, you will have to restore pretty much everything just after the call to beginNativePainting (link/bind your shaders, set global parameters, select and enable various buffers, etc).
It also means that you should use native painting sparringly. Having each single widget do custom painting might soon bring your rendering to its knees.

How to use Qt Model/View framework with the Graphics View framework

I am working on a mapping application and need to display the data objects using a table, a form and as graphical objects in the map. I'm using PyQt, but that's not really important as this is a Qt question not a Python question.
If I only needed the table and form views this would be easy, I'd just use the Qt Model/View framework. However I need the map view to provide functionality only really available using the Graphics View framework, which is essentially it's own Model/View framework with the QGraphicsScene acting as the data model.
I can think of two ways to do this. One would be to start with an authoritative model subclassed from QAbstractItemModel, link it to a subclass of QAbstractItemView and from there generate and update QGraphicsItems in the scene. This looks ugly though because I'm not sure how to handle user interaction with and changes to the data items though interaction with the QGraphicsItems.
The other way I can think to do it is to treat the QGraphicsScene as the authoritative data source, storing the data object in each QGraphicsItem's .data() property. I'd then subclass QAbstractItemModel and write it so that it accesses the data in the scene as it's data store, the other views would then use this as their model. How would I propagate changes to the data in the scene up to the model though?
Whichever approach I take, it looks like there's a gap not handled by the frameworks. In Model/View all changes are assumed to be made in the model. In Graphics View all changes are assumed to be made in the scene.
So which approach would you choose QAbstractItemModel(authoritative)->QAbstractItemView->QGraphicsScene or alternatively QGraphicsScene(authoritative)->QAbstractItemModel->Other Views. Why would you choose one over the other and what gotchas do you anticipate? Has anyone else needed to bridge this gap between Qt's twin model/view frameworks and how did you do it?
QAbstractItemModel(authoritative)->QAbstractItemView->QGraphicsScene
Without a doubt. I have done this before, it does require a bit of duplication (at least some that I couldn't avoid) but nothing too bad.
This also allows you to represent your data in standard views along with the scene which is quite nice.
My best advice would be to store a QHash of QPersistantModelIndex to QGraphicsItem and a QGraphicsScene in the QAbstractItemView you create. This allows you to quickly go between Model/View land (QModelIndex) to Graphics View land (QGraphicsItem)

Resources