Hi. I'm Jesper Pedersen from KDAB. Welcome
to this second module on Programming with Qt and QML. In this module, we're
going to see four videos (actually, six). The first video and the one that you're looking at now
is about images. Then, we'll see a video on transformation of items. That
could, of course, be transformation of images. But it could be rectangle; it
could be anything. You can do a lot of stuff with images and
transformation, as you will see. Following that, we'll talk about layout managers. We
have three or four possible different ways of laying out our user
interfaces with QML. And we'll see one of those four ways, namely the anchor
layout, in the third video (actually, the fourth) of this module. And the final and fourth video (actually, sixth) of this
module will address colors and gradients, just so that we can apply a bit of color
to our rectangles that we're going to love so much at the end of this
videos. Images in QML can do so many things.
If you looked at the table of contents of this video series up until
now, we've seen rectangles, an item which doesn't
look like anything, and now we're gonna see images. Is that really what user
interfaces are about? Where are my more complex elements? Well, your more complex
elements, we will get to those. We'll see especially the ListView element. It's
very powerful that you've got a bunch of items laid out on top of each other and
then you can scroll them with your fingers. But you will be surprised, once
you can start it with QML, how powerful it is to compose your user interfaces
off just a bunch of images. I'll show you a very, very simple user interface of an
analog clock. The analog clock actually looks pretty good and it even works. And
that is done with three images: the background of the analog clock, the
larger arm, and the smaller arm. And some transformation is applied to that to
make it look right. But that is in the next video; we'll see that. In this video,
we'll start out with this very simple user interface, here. It's just started up
in Qt Creator. The user interface doesn't look like much.
We got a blue background here. On top of that, we got this rocket.
It's not a beautiful rocket, but it's a rocket.
The rocket is in this image element here. And the image elements specifies where the
rocket is. It doesn't say anything about its width and its height. So, it will use
whatever is size of the image is. Then, it's loaded from disk. I can show you the
rocket here. It's one level up and then into images and it was called rocket.png There is your rocket. Doesn't look like much, but it's a start. There are a few things to notice about the
image element. The first thing is that the images
do have a size. They have a number of pixels in width and height in the image
file. What we show on the screen, if I do not specify a width and height is gonna
be that of the image file. But I could specify a width and a height. I could say width
: 500. It's gonna be a big rocket now. Height, I can spell that -- height : 500. Now
when I run my application, you can see just the corner of my image here. I
can scale it up so you see the full rocket. You can actually
ask the image element about its size. Still, go and look at the
reference documentation for image: F1 on top of the image, F1 one more time, to see
the full thing here. What you'll see is that we have the source size. The source size tells us the size
of the element. I can use that if I want to say that I want to shrink the
image to half the size. Then, I could write something like source or just well
this - twice is already small. And source size and, of course, height times 2,
width times 2. Now, I got an image that is twice as high. I got other ways of scaling it up
using transformations that we'll see in the next video, but this is one way of doing it. Let me just show you this small trick that is very, very useful
when you program with QML. You can write Component.onCompleted and what
I write after it is a piece of JavaScript code. That JavaScript code
will be executed once a component has been completely initialized. And a
component of this setup here is just
the image element. So, I can write console .log(width, height, sourceSize), like this. And now you can see here. 94 x 222 -- so, that's the
width and the height that we actually ended up seeing on the
screen. But the size that came out of the image, the size on disk, is 47 x
111. Let me just grab some code that I prepared up front here. That will show
you something else. The images are loaded asynchronously.
This means that I'll set up my image element, I will display it on the screen,
and then in the background it will start loading in the image. And I'll create a
small example of that here. I created
a small example here with an image. It has a width and a height of a thousand
pixels in each direction. I went somewhere, to NASA, and found a really big
image that they have there. I think it's two megabytes big, or
something, I guess. At least it's not a trivial little one. I have some fillMode
here. We can talk about that later on. But that basically tells how I'm
going to shrink and resize the image. You can go and click F1 on this one.
Here you can see the different fillModes for the image. Anyway, I have a rectangle
that sits on top of my image. It is at position 0 and at position
950 y-wise. And it's 50 in height and it the width is a thousand times the
image.progress. So, image.progress tells me how much my image has been
loaded already and it's visible when the progress is not 1. So the end it's
going to be 1. So let me run this example here. You can
see 1000 x 1000. Now, you can see the red progress bar. It's a
pretty trivial progress bar that I implemented, but you can see that the
image is loading now. We don't see anything on the screen until I make it
to 100%. And here is my image loaded now. That's
basically what you needed to see from this small example. We got this image.progress that tells us how far we are in loading the image. The width is 1000 x image.progress That's because my window
is 1000 wide, so I go from 0 to 1 of my loading.
That was an image. Sometimes you want to create some fancy user interfaces.
Imagine that you want to have a speech bubble that should resize
with the user interface. How would you do that? If you just draw a picture of that
speech bubble and you resize that picture, then it would look weird
in the corners perhaps. So what we can do instead is we
have this element called a border image. The idea with the border image is that you
will look at your input image, just a regular PNG file or whatever format you
have, and then you will simply cut it in nine squares. And number one in our image, the topmost, leftmost corner, will not be
scaled. 3, 7, and 9 will also
not be scaled. But the sides will be scaled vertically, and the top and the
bottom will be scaled horizontally, and the whole the center of it will be scaled
both horizontally and vertically. So, our speech bubble would, in
the speech part of the the bubble, come up in the seven part. And then I'll
have my corners in 1, 3, and 9. We have three different modes that we
can scale. The 2, 4, 6, 8, and 5 sections on that is using stretch,
repeat, or wrapped. And with stretch, I simply take whatever image is in, say 2,
and just stretch it out. So the input 12 pixels that I had will now
be scaled out to 200 pixels. That is perfectly fine if they were just a
straight line, but if they aren't some pattern then it will likely not look
good. So, there I can do repeat, which basically takes the input and
repeats it a number of times. And then we've got this special version called
round. And round makes sure that my image will be in an
integral amount of our sections. Let's see an example for this that makes it
much easier. So, I have my border images we see here. The source is this file here.
My border is left: 30; top: 30; right: 30; and bottom: 30. So, that's basically my left, my right,
my top, and my bottom line that we see here. So, that's 30 pixels from here up to
here. And then in this screenshot here, it
comes out of this example that we have down here. In that, I play with a
different horizontal tile mode and a different vertical tile mode. So BorderImage.Stretch
and BorderImage.Repeat. That's likely what we see here. I'm stretching
it, so I'm cutting actually in the middle of one of these. Here I am
stretching there, too. Well, here I'm stretching and here I'm repeating.
You can see it's stretched so that I'll
have an integral amount of diamonds. There's one thing in this example that we
haven't seen before in this video series. You can see it says border
left and so on. It could actually just have said border.left:
30; border.top: 30; border.right: 30; and border.bottom: 30. But we can
do this with properties in a compound way where I simply say border
and then left, right, top, and so on. We'll see that we use that trick a lot
when we talk about anchor layout 2 videos from now. The final element
that you see here is our animated image. And let me be brutally honest with you:
yes, I did include this slide here just so you can see my animation running
in my slide here. The slide deck is actually a tool that we've created at KDAB
called Slide Viewer. Sorry, it's not available for the outside world. But Slide Viewer is a QML application and this QML application loads in this
example that we see up there. Let me show you the code for the animated
images. I've loaded it up in Qt Creator now.
And what you'll see in here is there's a bunch of comments. Don't be disturbed
about that. That's again our Slide Viewer application that is able to read
those files exactly as it is. So, when you see the code block inside of the slide,
it's actually loaded in from here. So, just ignore these "slide" and "hide" and
whatever. What you're seeing here is I've got a rectangle and I've just run the
example so you can remember what it looks like. Coming up...there we are. So
it's my animated image here and the rectangle with this red bar jumping down
there. So I got my rectangle that's the background of everything. I've got my
animated image. My animated image has an x and a y and a width and height and
so on. Here is the source of this animated image. It has this onStatusChanged. That's a signal handler. We'll talk about that a bit later. But
that's a signal handler in our animated image and it says whenever the status
is equal to ready then frames is equal to frameCount and frames is a
property that I have up here. We'll also talk about that later. And then, I got my
rectangle with this rectangle. That is the red bar that moves all the
time. And I gotta take them on the same frame or
whatever of whatever. And the whatever part here is animation.currentFrame. So my animation has this property that is updated whenever I'm at the next
frame. So relatively simple, you can get an animation into your application if you want
to do that. Why you want to do that is beyond me. But now I've given you the
tools. That's the end of this video here. We've now seen how we can create images
in our application. We got this rocket loaded up. But we want more than that. We
want perhaps our rocket to be rotated or scaled or whatever and, for that, please
stay tuned. Subscribe to our channel and, in the next video, we're gonna see how we
can transform our items.