Introduction to Qt/QML (Part 49) - Creating New Elements from C++

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
Hi. My name is Jesper Pedersen. I'm from KDAB.  You're watching programming with Qt and QML, and   we are looking at the integration between QML  and C++. Did I say QML on C++?   I used to say C++ in QML. But, this time,  it's actually between QML and C++, because,   in this very video, we are going to see  how we can create elements that can be   instantiated from the QML side. So, it almost  feels like it's QML that is back in control. To not just export an object up to the   QML level from C++, but to create a new element  that you can instantiate from the QML side, you   need to do four things. First, you need to subclass  from either QObject or QQuickItem.   If you subclass from QQuickItem, the element  has the option of   being seen on the screen. So, in  this example, we're just creating a timer that   isn't visible, but you could still  choose to make it subclass it from QQuickItem,   simply because that adds some of the facility  that QQuickItem offers you, among other things   component.uncomplete that we've seen a number of  times. If you subclass from QQuickItem, of course,   GammaRay will tell you that you have an item  that has a size of 0,0.   But, if you can live with that, that  doesn't seem like a terribly bad choice.   Next step: once you have created a subclass  from QObject, or from QQuickItem,   you need to actually tell the QML environment  about this new element and you need to make   it possible for the QML environment to instantiate  your class because, on the QML side, there   will be code that says it wants a timer. Then,  your C++ side needs to new-up such a timer.   So, we need a bit of glue code for that. On the QML  side, that's step three and four. You just import   the elements that you created there, just like  we've seen import QQuick2.0 or import   QQuick.layout -- whatever version that was. You  will have to import your own version, or your own   your own library, in that way and then you'll  just use it, just like any other QML element. So, let's see those four steps  on the slide, here. First of all, I create my timer.   It's a random timer that's subclassing from  QObject. It has this Q_Object, as we've   discussed so many times. It has a constructor  with the QObject pointer parent equal to   no pointer. And we have my real QTimer  sitting as an instance variable. I'll get back to the discussion of why  I am not just exporting a QTimer. Why   didn't I subclass from QTimer,  and am, instead,   creating a completely new  object and then just having my QTimer as   an instance variable? I'll get back to  that discussion in just a little bit,   just so that you're at ease with that  design already, now. I could have done one of the   other two, but I chose for a reason that will be  apparent to you in five minutes, to do it this way. That is the step of creating it. Of course,  I need to implement it, somehow. Now, the next   step is registering it. And registering it is done  using a method called qmlRegisterType. It   takes a template parameter, here, which is the  actual class that I had. So, just go back here to   class RandomTimer. So, it's a class name that I  got there. And then, it takes four parameters in the   constructor. CustomComponents 1.0 is what I'm  going to import on the QML side. Once I've done   that, I will have access to a new element that's  called RandomTimer.   It's not an entire coincidence they're called the  same, but there's nothing that requires it to be   called the same. We haven't talked too much about  versioning of QML. We've seen that you can    write "import Qt Quick 2.0" or "2.7," or  whatever we have throughout the code, here.   So, if we had two different versions I could have  exported, I could have called this qmlRegisterType   two times. One time, I was exporting Random  Timer v1 and, the second time, RandomTimer v2.   And, when I exported RandomTimer v1,  it would be CustomComponents 1.0 RandomTimer.   And, for the v2, it might be  CustomComponents 2.0 RandomTimer.   If I had two different versions of my RandomTimer,  RandomTimer v2 was the updated, cool version that   could also brew coffee underwater, or whatever it  was able to do, where I still might have code that   I didn't want to touch and, therefore, I would still  want to use RandomTimer v1 in that code, so   the RandomTimer here. And the random timer here  usually is the same name, but it doesn't have to be.   I'll give you a link in the description below  where you can learn more about the versioning in   QML. I will touch more on that in this video  series. Finally, import CustomComponents 1.0,   and now I'll just use random timer as I was  using any other element: Rectangle, Item, whatever.   Let's see a slightly more involving example of  this, so we can see it running and we can see    the different approaches to what would  I want to subclass from. So, my RandomTimer...   simply, whenever I click here, the timer is  running and says, "meebeep, meebeep," and when   I click again, well, the RandomTimer stops.  My main.cpp, here, is really just what it was on my   slide. I'm registering RandomTimer: RandomTimer  CustomComponents 1.0. So, let's go to my main.qml.   My main.qml is instantiating this RandomTimer,  here. It sets a property on that object. So, it's   just a regular QObject that I exported. And  remember, my QObject that I exported can   access properties, and signals, and slots, and Q_INVOKABLE. So, I'm setting a property on   that QObject, here. It has a signal that is  called timeout. So, I'm connecting to onTimeout   and, when onTimeout fires, i print out timer fired  on my console, for debugging purposes, i guess.   And then I say to my beep animation, "Will you  please start running?" And my beep animation   is this sequential animation we have down there.  For 50 milliseconds, it will have the   opacity of my beep text go from zero to one. So, it  comes in over 50 milliseconds. And then, after that,   for 300 milliseconds it will then go away again.  So, we watch again. I cannot count; you'll have to   do that yourself. So, it comes in  50 milliseconds, goes away for 300 milliseconds. The RandomTimer interval came from the  timer. So it's itself, randomInterval.   I don't really need to write timer.random  Interval here, but hey, that's cool.   Every time it goes off, it starts this animation.  My RandomTimer class...RandomTimer.h...   there's really nothing different from what  we saw in the previous video, where we saw how we   can export our QObject. It's purely how we  are making it available to the QML side. So, I got   Q_OBJECT. I subclass from QObject,  here. It could have been QQuickItem,   as we discussed. I got the QProperty,  where I set up the interval and the active.   My RandomTimer constructor, here...set  Interval and interval, they are used in my   property definition, up here. I got my  Q_INVOKABLE, which is this method that   I can execute from the QML side to get a random  number, here. And I got some timer set up, and so on. So, the only thing that's really worthwhile  discussing in this setup is why subclass from QObject, rather  than just subclassing from QTimer?   Well, let me kill that idea first. Well, no --  I had the idea before. Why didn't you just   export the QTimer? I could have exported  a QTimer. Well, first of all, this example was   written in the Qt 4.8 days. So, back then, the   QTimer had not been updated with properties for   active, and so on. Go and read the API documentation  for that, if you don't believe me. That's the first   thing. The second thing is I actually need  more than a QTimer. I also need the    randomInterval that you see here. I need that on  my QTimer. So, I couldn't just give it a QTimer.   I needed an excuse, sorry. Now, the  second thing is why didn't you, then, subclass from   QTimer instead of subclassing from   QObjects? Well, I'm glad that you asked. I did so   because I wanted to show you the more generic way  of doing this. So, sometimes you have an object that   fits straight into your QML. You can just export  that object. If QTimer had been your object, you   would have likely just added that randomInterval  on that one and exported that straight into QML.   It might have been that it was team A over there  that had created that object and you couldn't   do that, so you'd sub class from their object,  add the the randomInterval, and export that up.   But, sometimes, you have objects that might not  even subclass from QObjects that you want to   to make available as new elements in QML. It might  be that you have the concept of a sensor and the   sensor element is really something very low-level.  It can read data from a bus, or whatever, and you   want to make them available in QML. But you're  definitely not going to get the idea of    subclassing your sensor class. Subclassing that  from QObject -- you're not going to   get that idea from the low-level team. So, there, you  create this proxy object that has the sensor as an   instance variable. You add the properties, you add  the signal, you add the communication to the real   sensor, and, somehow, the sensor will tell you that  it has changed, however that communication is   done. And when that sensor data is changed, you're  going to emit a signal. So, you will have this   proxy QObject between the sensor that doesn't  have anything to do with Qt, and the QML level. That's it. Now you know how to create your own  new element. They don't look like anything. That's   the last little piece of the puzzle that we are  missing. How can you make your new element actually   look like something? And that is the next video  that we're going to do -- the last one this module. So,   please do hang in there. In just 15 minutes, you  will know how to create your own user interface   element -- well, 15 minutes from when you start the  next video. If it hasn't been published already,   this sounds like a good time for you to subscribe  to our channel. Until then, have a great day.
Info
Channel: KDAB
Views: 2,032
Rating: undefined out of 5
Keywords: QML, C++, Qt, KDAB
Id: YdTxhI-EFFs
Channel Id: undefined
Length: 12min 36sec (756 seconds)
Published: Wed Jan 27 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.