PDA

View Full Version : Call Constructor within Designer



NoRulez
22nd June 2009, 14:18
Hi @all,

i have made a subclass of QPushButton.
This I had successfully assigned using "Promote To".
Is there a way to set some Variables for the Constructor anywhere?

Best Regards
NoRulez

wysota
22nd June 2009, 15:09
No, you have to rely on the default constructor if you want the widget created from within Designer generated code.

Lykurg
22nd June 2009, 16:12
...and if you want set your custom properties in the designer, you have to write a plugin for the designer, which is not so hard.

NoRulez
22nd June 2009, 16:28
Could you provide me a sample or something similar to use custom properties within the designer? A pluginexample is in the documentation, but what about custom properties? If I'm right, than you mean Q_PROPERTY?

Regards
NoRulez

Lykurg
22nd June 2009, 16:48
A pluginexample is in the documentation, but what about custom properties?
It's also in that documentation! E.g. the "Container Extension" example. Look also at QDesignerPropertySheetExtension. But that is not necessary at all, since you also add dynamic properties directly in the designer: Use the plus near to the filter in the property editor.

NoRulez
22nd June 2009, 17:10
OK, I've found it. It seems that this function is new in Qt 4.5.
So, now I added 2 pixmaps as follows: pressedPixmap = :/images/pressedButton.png" and normalPixmap = ":/images/normalButton.png".

Now i want to call my own constructor:
MyButton(QPixmap pressed, QPixmap normal);

This is the point where i don't know how to call it.

Regards
NoRulez

Lykurg
22nd June 2009, 17:27
OK, I've found it. It seems that this function is new in Qt 4.5.
So, now I added 2 pixmaps as follows: pressedPixmap = :/images/pressedButton.png" and normalPixmap = ":/images/normalButton.png".


Note, that you have to have proper Q_PROPERTY to do so!


MyButton(QPixmap pressed, QPixmap normal);

This is the point where i don't know how to call it.


That's not possible. And also not necessary. If you call
MyButton mb(QPixmap pressed, QPixmap normal);
or
MyButton mb;
mb.setPressed(QPixmap pressed);
mb.setNormal(QPixmap normal);
doesn't matter.

NoRulez
22nd June 2009, 17:39
It does a matter, because after the constructor the sizeHint() function is called.
The sizeHint() function should return the size of the image, otherwise the function returns 0x0 (width x height). At this point the sizeHint() returns 0x0, because the image is defined after the sizeHint() call.

So if i call a function then the following are done:

MyButton();
sizeHint()
setPressed(QPixmap pressed);
setNormal(QPixmap normal);

I need to set the image before the sizeHint() function is called.
So I thought the best way is the constructor.

Regards
NoRulez

Lykurg
22nd June 2009, 18:01
Don't understand. For what do you mean the size hint is important? for the correct arrangement in a layout? it will be adjusted even if you set the images after the c-tor is called. And by the way, the designer is creating the instructions exactly that way:

MyButton mb;
mb.setPressed(QPixmap pressed);
mb.setNormal(QPixmap normal);
So no other function is called between and if you don't call sizeHint() in your own c-tor, there is no difference.

NoRulez
23rd June 2009, 09:12
The BaseClass (QPushButton) calls the sizeHint() function. If you use debug messages in the overloaded functions you will see that the sizeHint() is called after the constructor. After the sizeHint() the other functions are called.

So when the size of my Pixmap is for example 250x130. then my button should also be the same size. To set the size of the button you could also write:

QSize MyButton::sizeHint() const {
return QSize(250,130);
//return normalButton.size();
}
But within this function I haven't the pixmap when I can't set it within the constructor

I hope you could understand what i mean.

Regards
NoRulez

wysota
23rd June 2009, 11:08
There is no "after the constructor". Besides, the sizeHint() can change, just call QWidget::updateGeometry() from within the methods used to set up the images. sizeHint() will be called again.

NoRulez
23rd June 2009, 11:49
Thanks for the hint, i'll give it a try

Regards
NoRulez

Lykurg
23rd June 2009, 12:01
Have you tested the approach? Now I see that the designer produced code give a layout to the ctor, which will invoke the size hint, because it adds the widget to the layout. But nonetheless I think when showing the widget size hint is called again and then your images are already set and the function will return the right size.

(But to call explicitly updateGeometry() is the saver way, also if you want to change the images at runtime)

NoRulez
23rd June 2009, 13:56
Ok, i can't get it to work. Here is the sample code i have.
ownbutton.h:


#ifndef OWNBUTTON_H
#define OWNBUTTON_H

#include <QtGui>
#include <QPixmap>

class OwnButton : public QPushButton {
Q_PROPERTY(QString MyImage READ getImage WRITE setImage)

public:
OwnButton(QWidget *parent = 0);
QSize sizeHint() const;
void setImage(QPixmap _pixmap);
QPixmap getImage();

protected:
void paintEvent(QPaintEvent *event);

private:
QPixmap pixmap;
};

#endif // OWNBUTTON_H

ownbutton.cpp:

#include "ownbutton.h"
#include <QtGui>

OwnButton::OwnButton(QWidget *parent) : QPushButton(parent) {
}

QSize OwnButton::sizeHint() const {
qDebug() << "Pixmap size: " << pixmap.size();
return pixmap.size();
}

void OwnButton::paintEvent(QPaintEvent *event) {
QPainter painter(this);

painter.drawPixmap(0, 0, pixmap.size().width(), pixmap.size().height(), pixmap);
}

void OwnButton::setImage(QPixmap _pixmap) {
pixmap = _pixmap;
QWidget::updateGeometry();
}

QPixmap OwnButton::getImage() {
return pixmap;
}

In the designer, I used a simple QPushButton, and add a Pixmap Property "setImage".
The value of the property is an image of the resource file.

Hope you can help me
Thanks in advance

Regards
NoRulez

Lykurg
23rd June 2009, 14:06
setImage is the setter not the property! So use MyImage (as you defined as a property), second, you need to provide a function which accept a QString, since this is the value the designer deals with when using embedded images. your QPixmap function is never called...

NoRulez
23rd June 2009, 14:29
I've updated the code, but it also does nothing :(

ownbutton.cpp

#include "ownbutton.h"
#include <QtGui>

OwnButton::OwnButton(QWidget *parent) : QPushButton(parent) {
}

QSize OwnButton::sizeHint() const {
qDebug() << "Pixmap size: " << pixmap.size();
return pixmap.size();
}

void OwnButton::paintEvent(QPaintEvent *event) {
QPainter painter(this);

painter.drawPixmap(0, 0, pixmap.size().width(), pixmap.size().height(), pixmap);
}

void OwnButton::MyImage(const QString& image) {
pixmap = QPixmap(image);
//pixmap = QPixmap(QString(":/") + image);
QWidget::updateGeometry();
}

void OwnButton::setImage(QPixmap _pixmap) {
pixmap = _pixmap;
QWidget::updateGeometry();
}

QPixmap OwnButton::getImage() {
return pixmap;
}


#ifndef OWNBUTTON_H
#define OWNBUTTON_H

#include <QtGui>
#include <QPixmap>

class OwnButton : public QPushButton {
Q_PROPERTY(QString MyImage READ getImage WRITE setImage)

public:
OwnButton(QWidget *parent = 0);
QSize sizeHint() const;
void MyImage(const QString& image);
void setImage(QPixmap _pixmap);
QPixmap getImage();

protected:
void paintEvent(QPaintEvent *event);

private:
QPixmap pixmap;
};

#endif // OWNBUTTON_H


Regards
NoRulez

Lykurg
23rd June 2009, 14:45
You got me wrong! The setter for MyImage must accept a QString.

OwnButton::setImage(const QString& image)
And how looks the uic generated code for your dynamic property?

NoRulez
23rd June 2009, 14:54
I have changed it to look like this:


public:
OwnButton(QWidget *parent = 0);
QSize sizeHint() const;
void setImage(const QString& image);
QPixmap getImage();

protected:
void paintEvent(QPaintEvent *event);



void OwnButton::paintEvent(QPaintEvent *event) {
QPainter painter(this);

painter.drawPixmap(0, 0, pixmap.size().width(), pixmap.size().height(), pixmap);
}

void OwnButton::setImage(const QString& image) {
pixmap = QPixmap(image);
QWidget::updateGeometry();
}

QPixmap OwnButton::getImage() {
return pixmap;
}

I got the following result without a button/image drawn.

Could you please give me a simple working example?

Thanks in advance

Regards
NoRulez

Lykurg
23rd June 2009, 14:59
please make a minimal compilable example.

NoRulez
23rd June 2009, 15:37
I've attached an example

Thanks in advance
Regards
NoRulez

wysota
23rd June 2009, 15:42
You forgot the Q_OBJECT macro.

Lykurg
23rd June 2009, 16:17
use Q_OBJECT in your class OwnButton
use the right property name in the designer! (MyImage not setImate)

and then, if you set QPixmap as a value in the custom property folowing is created:

pushButton->setProperty("MyImage", QVariant(QPixmap(QString::fromUtf8(":/button_1.png"))));
So you have to provide QPixmap-setter like in your first code post, but also inside the Q_PROPERTY! then it works.

NoRulez
24th June 2009, 09:27
Ok, many thanks

For those who also problems with this have, here is the corrected class:

ownbutton.h:

#ifndef OWNBUTTON_H
#define OWNBUTTON_H

#include <QtGui>
#include <QPixmap>

class OwnButton : public QPushButton {
Q_OBJECT
Q_PROPERTY(QPixmap pixmap READ pixmap WRITE setPixmap)

public:
OwnButton(QWidget *parent = 0);
QSize sizeHint() const;
QSize minimumSizeHint() const;
const QPixmap *pixmap() const;
virtual void setPixmap(const QPixmap &image);

protected:
void paintEvent(QPaintEvent *event);

private:
QPixmap _pixmap;
};

#endif // OWNBUTTON_H
ownbutton.cpp:

#include "ownbutton.h"
#include <QtGui>

OwnButton::OwnButton(QWidget *parent) : QPushButton(parent) {
}

QSize OwnButton::sizeHint() const {
return QSize(_pixmap.width(), _pixmap.height());
}

QSize OwnButton::minimumSizeHint() const {
return QSize(_pixmap.width(), _pixmap.height());
}

void OwnButton::paintEvent(QPaintEvent *event) {
QPainter painter(this);

painter.drawPixmap(0, 0, _pixmap.size().width(), _pixmap.size().height(), _pixmap);
painter.drawRect(0, 0, _pixmap.size().width()-1, _pixmap.size().height()-1);
}

const QPixmap *OwnButton::pixmap() const {
return &_pixmap;
}

void OwnButton::setPixmap(const QPixmap &image) {
_pixmap = image;
this->resize(_pixmap.size().width(), _pixmap.size().height());
QWidget::updateGeometry();
}


Regards
NoRulez