PDA

View Full Version : Reimplement of resizeEvent



Shawn
27th May 2007, 04:52
what I want: show image at the central of the QMainwindow(centralWidget)
but after resizing, the image is still at the previous position

my code is like this:


SLD::SLD(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
ui.setupUi(this);
}

void SLD::showCB(int x, int y, int w, int h)
{
label=new QLabel(ui.centralWidget);
label->setGeometry(x,y,w,h);
label->setPixmap(QPixmap("Resources/CB.bmp"));
}

void SLD::resizeEvent(QResizeEvent * /* event */)
{
mWidth = width();
showCB((mWidth-50)/2,0,100,50);
}
please help me.

jpn
27th May 2007, 06:36
The easiest possible way is to let the label scale its contents:


SLD::SLD(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
ui.setupUi(this);
QLabel* label=new QLabel(this);
label->setPixmap(QPixmap("Resources/CB.bmp"));
label->setScaledContents(true); // let the label scale its contents
setCentralWidget(label); // label will get automatically resized as a central widget
}


If you need more intelligent scaling, like keeping aspect ratio or something, you might want to scale it by hand. This would be done by storing the image as a member variable, scaling it for example in resizeEvent() and setting the scaled image on the same label. I'd suggest doing it a bit delayed so that each and every resizeEvent() in a row doesn't scale and set a new image.

Notice that you were creating new QLabel widgets again and again during every resize event! Also, Qt has a concept of layouts (http://doc.trolltech.com/4.2/layout.html) to handle geometries. You barely set geometries by hand. ;)

Shawn
27th May 2007, 07:09
thanks for ur quick reply!

what's wrong with my code? it is supposed to work.
If I want to show the image"CB.bmp" exatcly at ((mWidth-50)/2,0,100,50) when the window is resized,what should I do?

marcel
27th May 2007, 07:20
#include "centrallabel.h"
#include <QLabel>
#include <QHBoxLayout>

centrallabel::centrallabel(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
ui.setupUi(this);

label = new QLabel( this->centralWidget() );
label->setPixmap( QPixmap("c:\\pix_png.png") );
label->setFixedSize( label->sizeHint() );
}

void centrallabel::resizeEvent(QResizeEvent* )
{
label->move( width()/2 - label->size().width()/2, 0 );
}

centrallabel::~centrallabel()
{

}
This one works. The label will be kept centered at all times.

As jpn said, the problem with your code was that you were always creating that label.
The label should be created only once.
Also, you shouldn't be so strict about sizes. In your case you should care only about position.

You also could implement a small, custom layout that centers the widget(s) in the parent's area.
But this works too.

Regards

wysota
27th May 2007, 08:21
AFAIR it's enough to set the label as the center widget, apply a pixmap to it and set the alignment in both directions to center. I think the problem here is that the author doesn't use a layout for the central widget at all.

marcel
27th May 2007, 08:24
apply a pixmap to it and set the alignment in both directions to center

I thought so first, but it seems that he just wants it centered horizontally. The y coord is always 0.

Shawn
27th May 2007, 08:31
AFAIR it's enough to set the label as the center widget, apply a pixmap to it and set the alignment in both directions to center. I think the problem here is that the author doesn't use a layout for the central widget at all.

Yes, i don't use central widget
because i need to draw MANY small images at their certain positions, and then show all of them as a whole structure.
this is also the reason why i kept drawing that label, because there may be many same images.
sorry that i didn't make it clear at the beginning.

and, why my code doesn't work? I don't know where this bug is.

marcel
27th May 2007, 08:37
Yes, i don't use central widget
because i need to draw MANY small images at their certain positions, and then show all of them as a whole structure.
sorry that i didn't make it clear at the beginning.

Then I suggest implementing a custom layout that positions the labels at their preset values( relative to parent).
By doing this you don't have to readjust the positions of the labels in resize event.

You can achieve this by modifying the Flow Layout example in the Qt Examples ( in the Layouts category ).

Regards

Shawn
27th May 2007, 08:46
dear marcel:
can you help finding out why my code doesn't work?
I have already reimplemented the resizeEvent

void SLD::resizeEvent(QResizeEvent * /* event */){ mWidth = width(); showCB((mWidth-50)/2,0,100,50);}

wysota
27th May 2007, 08:52
I thought so first, but it seems that he just wants it centered horizontally. The y coord is always 0.
Then he can center horizontally and vertically align to top. And set the size policy to minimumExpanding, so that the label takes all available space.


Yes, i don't use central widget
Of course you use a center widget.


because i need to draw MANY small images at their certain positions, and then show all of them as a whole structure.
So why not draw them on a pixmap and then just apply the pixmap to the label?


this is also the reason why i kept drawing that label, because there may be many same images.
If you only want to draw some images, you don't need a label.

marcel
27th May 2007, 08:52
Because you always create the label in showCB.
By creating a new one, the old one will remain in the old position.

You should create your label only once, and position it afterwards, as needed.
But my question is, what will you do when you have more labels?

marcel
27th May 2007, 08:58
So why not draw them on a pixmap and then just apply the pixmap to the label?

Yes, of course that would be better, but I thought maybe he wants to interact somehow with those images.

Anyway, there are many solutions, neither is that hard, and this thread seems to be one of those that gets 2-3 pages long, so I'm bailing out :).

Regards

Shawn
27th May 2007, 09:04
I consider a label as a "canvas" for showing a image.
so when I want to show a image, I creat a label for it.
maybe it's less efficient but I thought it would work.

just as you said, by creating a new label, the old one will remain in the old position
then there should 2 image, one at the new position and the other at the previous position, is that right?
in my program, the image just appear at the previous position, that's why I said"the image is still at the previous position"

waiting for your kindly reply!

marcel
27th May 2007, 09:14
I consider a label as a "canvas" for showing a image.
so when I want to show a image, I creat a label for it.
maybe it's less efficient but I thought it would work.

just as you said, by creating a new label, the old one will remain in the old position
then there should 2 image, one at the new position and the other at the previous position, is that right?
in my program, the image just appear at the previous position, that's why I said"the image is still at the previous position"

waiting for your kindly reply!

But the resize events are posted very quickly. So, if you resize your window by 100 pixels, there is a good chance that the window receives 50 ( I'm just estimating here, could be less, could be more ) resize events.

Therefore you create 50 labels with the same image.
JPN suggested in an earlier post ( in this thread ) to draw the label delayed ( using a QTimer or whatever ). But this isn't to work in your case either because you're creating the labels in the resize event handler.




I consider a label as a "canvas" for showing a image.
so when I want to show a image, I creat a label for it.
maybe it's less efficient but I thought it would work.

But why do you create them in when a resize event is received?
I don't know exactly what are you trying to do by this, but shouldn't you load them as a response to some user action ( button press, action trigger )?
Or do you want this to be some kind of background for your main window?

Please elaborate on this a little.
I understand you're trying to show some images, but why like this?

wysota
27th May 2007, 09:23
Why not use QGraphicsView?

Shawn
27th May 2007, 09:23
this is the outcome of my program:
every element is a small image.
the position for each element is given by a XML file, which I should parse at the beginning.
So, my program should parsing a XML file and generate this layout automatically.

what I want to implement now is to keep the layout at the central(horizontal) when someone resize the window.

marcel
27th May 2007, 09:38
In this case I approve Wysota's advice and I also strongly suggest you use a QGraphicsView.

Using the Graphics View Framework you will be able to achieve what I have seen in the screen shot much easier.

The Graphics View Framework is very well documented in Assistant and there are clarifying examples in the Qt Demos.

You should use this if you want your app to be fast and well behaved.
Once you understand the basics of this framework you will be able to do all those things very easily.

Of course, if you get stuck, you can ask here.

Regards

Shawn
27th May 2007, 09:39
and this one is the final goal

marcel
27th May 2007, 09:53
and this one is the final goal


Yes, you can do this with QGraphicsView.

The main drawbacks of the method you're currently using are:
- If the document gets bigger you will have to add a QScrollArea manually;
- You have to manage image positions manually at resize and scroll.
- Zooming would be very hard to implement

QGraphicsView offers all of the above by default, with simple to use API, so you should think about using it.
You could event interact with those components in your document( move them around, change connections, etc ).

Regards

wysota
27th May 2007, 09:55
QGraphicsView is certainly the way to go.

Shawn
27th May 2007, 10:04
Thank you very much for your suggestion!
I am gona to try it.