PDA

View Full Version : Problems with laying out custom widget



mtrpoland
18th August 2007, 18:35
When I place five objects of MTR::Button class on MyWidget object (simple testing area) using QVBoxLayout I receive five buttons on one pile!

How to achieve an ordinary vertical box layout effect in this case?

MTRButton.h:

#ifndef MTR_Button_H
#define MTR_Button_H
#include <QAbstractButton>
class QSize;
class QPaintEvent;

namespace MTR {
class Button : public QAbstractButton {
Q_OBJECT
public:
Button(QWidget *parent = 0);
Button(QString tekst, QWidget *parent = 0);
protected:
void paintEvent(QPaintEvent *event);
QSize sizeHint() const;
QSize minimumSizeHint() const;
void mouseMoveEvent(QMouseEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
private:
bool hovered;
QFont font;
};
}
#endif

its implementation
MTRButton.cpp

#include "MTRButton.h"
#include <QtGlobal>
#include <QtCore>
#include <QtGui>

namespace MTR {
Button::Button(QWidget *parent) : QAbstractButton(parent) { setMouseTracking(true); hovered = false; }
Button::Button(QString tekst,QWidget *parent) : QAbstractButton(parent) { setMouseTracking(true); hovered = false; this->setText(tekst); }
void Button::paintEvent(QPaintEvent * /* event */) {
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, true);
QPen borderPen(QColor(Qt::black),1);
painter.setPen(borderPen);
QBrush ribbonBrush(palette().dark());
painter.setBrush(ribbonBrush);
painter.drawRoundRect(5,5,this->width() -10, this->height() - 10,25,25);
QBrush insideBrush(palette().mid());
if(isDown()) insideBrush = palette().light();
painter.setBrush(insideBrush);
painter.drawRoundRect(10,10,this->width() -20, this->height() - 20,25,25);
if((this->height()-20)/2 >= 0) {
QRadialGradient gradRed(QPointF(15+(this->height()-20)/2/4, 15+(this->height()-20)/2/3), (this->height()-20)/2);
if(!hovered) {
gradRed.setColorAt(0,Qt::white);
gradRed.setColorAt(1,Qt::red);
} else {
gradRed.setColorAt(0,Qt::white);
gradRed.setColorAt(1,Qt::black);
}
QBrush circBrush(gradRed);
painter.setBrush(circBrush);
painter.drawEllipse(15,15,(this->height()-20)/2,(this->height()-20)/2);

QRadialGradient gradGreen(QPointF(15+(this->height()-20)/2 + 2 +(this->height()-20)/2/4, 15+(this->height()-20)/2/3), (this->height()-20)/2);
if(hovered || isDown()) {
gradGreen.setColorAt(0,Qt::white);
gradGreen.setColorAt(1,Qt::green);
} else {
gradGreen.setColorAt(0,Qt::white);
gradGreen.setColorAt(1,Qt::black);
}
circBrush = QBrush(gradGreen);
painter.setBrush(circBrush);
painter.drawEllipse(15+(this->height()-20)/2 + 2,15,(this->height()-20)/2,(this->height()-20)/2);
}
painter.setPen(borderPen);
font = QFont(tr("Arial"),10,50,false);
painter.setFont(font);
QRect textRect(this->height(), 5 + this->height()/6, this->width() - this->height() - 20, this->height()-20);
painter.drawText(textRect,Qt::AlignTop | Qt::AlignHCenter, this->text());
}
QSize Button::minimumSizeHint() const {
return QSize(200,40);
}
QSize Button::sizeHint() const {
QFontMetrics fm(font);
int tekstSzer = fm.width(this->text());
return QSize(tekstSzer + 28 + 40,40);
}
void Button::mouseMoveEvent(QMouseEvent *event) {
QRect rect(10,10,this->width()-20,this->height()-20);
if(rect.contains(event->pos())) {
if(hovered) return;
else { hovered = true; update(); }
}
else {
if(!hovered) return;
else { hovered = false; update(); }
}
}
void Button::mousePressEvent(QMouseEvent * /* event */) {
setDown(true);
}
void Button::mouseReleaseEvent(QMouseEvent *event) {
setDown(false);
QRect rect(10,10,this->width()-20,this->height()-20);
if(rect.contains(event->pos())) emit clicked();
}
}


Five such objects are placed in a QVBoxLayout on MyWidget
MyWidget.h

#ifndef TESTWIDGET
#define TESTWIDGET
#include <QWidget>
namespace MTR {
class Button;
}
class MyWidget : public QWidget {
Q_OBJECT
public:
MyWidget(QWidget *parent = 0);
public slots:
void TestujPrzycisk() { qDebug("Click!"); }
private:
MTR::Button *b1;
MTR::Button *b2;
MTR::Button *b3;
MTR::Button *b4;
MTR::Button *b5;
};
#endif


MyWidget.cpp

#include "MyWidget.h"
#include "MTRButton.h"
#include <QtCore>
#include <QtGui>

MyWidget::MyWidget(QWidget *parent) : QWidget(parent) {
b1 = new MTR::Button(QString::fromUtf8("Rozpocznij grę"),this);
b2 = new MTR::Button(QString::fromUtf8("Wczytaj grę"),this);
b3 = new MTR::Button(QString::fromUtf8("Wyniki"),this);
b4 = new MTR::Button(QString::fromUtf8("Zasady"),this);
b5 = new MTR::Button(QString::fromUtf8("Wyjdź"),this);

QVBoxLayout qvb;
qvb.addWidget(b1);
qvb.addWidget(b2);
qvb.addWidget(b3);
qvb.addWidget(b4);
qvb.addWidget(b5);
setLayout(&qvb);
}


and finally main.cpp

#include <QApplication>
#include <QtCore>
#include <QtGui>
#include "MTRButton.h"
#include "MyWidget.h"

int main(int argc, char * argv[]) {
QApplication app(argc, argv);
MyWidget widget;
QPalette orangePalette;
orangePalette.setColorGroup(QPalette::Active,QBrus h(Qt::black),QBrush(QColor(255,180,51)),
QBrush(QColor(255,212,71)),QBrush(QColor(70,100,10 5)),QBrush(QColor(255,118,54)),
QBrush(QColor(Qt::black)),QBrush(QColor(Qt::gray)) ,QBrush(QColor(Qt::black)),QBrush(QColor(255,180,5 1)));

orangePalette.setColorGroup(QPalette::Inactive,QBr ush(Qt::black),QBrush(QColor(255,180,51)),
QBrush(QColor(255,212,71)),QBrush(QColor(70,100,10 5)),QBrush(QColor(255,118,54)),
QBrush(QColor(Qt::black)),QBrush(QColor(Qt::gray)) ,QBrush(QColor(Qt::black)),QBrush(QColor(255,180,5 1)));
widget.setPalette(orangePalette);
widget.show();
return app.exec();
}

marcel
18th August 2007, 18:41
Don't allocate the layout on the stack. It get's deleted as soon the constructor exists.
Do it on the heap( i.e. QVBoxLayout * qvb = new QVBoxLayout(this));

Regards

jpn
18th August 2007, 18:42
"QVBoxLayout qvb" gets automatically destructed while going out of scope by the time MyWidge constructor ends.

Try something like this:


QVBoxLayout* qvb = new QVBoxLayout(this);
qvb->addWidget(b1);
...
setLayout(qvb);


Edit: D*mn you Marcel! ;)

marcel
18th August 2007, 18:48
[/code]Edit: D*mn you Marcel! ;)
:) Don't worry. These days I have time to answer only a few posts/day( not even those ), so the rest of them are yours.

Regards

mtrpoland
18th August 2007, 18:48
Bloody hell!
It is obvious!
:o
A short break from coding and such a stupid mistake.
Thanks

wysota
19th August 2007, 11:40
These days I have time to answer only a few posts/day( not even those ), so the rest of them are yours.

Hell, they are! I want my share too!

marcel
19th August 2007, 11:43
Hell, they are! I want my share too!

I meant working days, not weekend :).

Regards