PDA

View Full Version : QWidget subclass drawing in wrong place



guidupas
31st May 2014, 13:47
Hello all!

I hava a QWidget subclassed and the painting is not going right. When I call setFluxo all the rects appear in the screen on position y 0



#include "fluxocaixawidget.h"

#include <QDebug>

fluxoCaixaWidget::fluxoCaixaWidget(QWidget *parent) :
QWidget(parent)
{
this->setMouseTracking(true);
dentro = false;
fluxo = NULL;

this->update();
}

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

linhaTempo.setRect(20, this->parentWidget()->height() / 2 - 20, this->parentWidget()->width()-65, 30);

QPen caneta;

QBrush pincel(Qt::white);
painter.setBrush(pincel);

painter.drawRect(parentWidget()->rect());

if(this->dentro == true)
{
painter.drawText(QRect(20, 15, linhaTempo.width(), 25), "Linha do tempo", QTextOption::QTextOption(Qt::AlignCenter));
caneta.setWidth(4);
}
else
{
caneta.setWidth(2);
}

painter.setPen(caneta);

painter.drawRect(linhaTempo);

if(fluxo != NULL)
{
for(int i = 0; i < fluxo->count(); i++)
{
if(fluxo->at(i) < 0)
{
caneta.setColor(Qt::red);
caneta.setWidth(2);

painter.setPen(caneta);
painter.drawRect(fluxoRect.at(i));
}
else
{
if(fluxo->at(i) == 0)
{
caneta.setColor(Qt::black);
caneta.setWidth(2);

painter.setPen(caneta);
painter.drawRect(fluxoRect.at(i));
}
else
{
if(fluxo->at(i) > 0)
{
caneta.setColor(Qt::blue);
caneta.setWidth(2);

painter.setPen(caneta);
painter.drawRect(fluxoRect.at(i));
}
}
}
}
}
}

void fluxoCaixaWidget::mouseMoveEvent(QMouseEvent *)
{
if(this->linhaTempo.contains(this->mapFromGlobal(QCursor::pos())))
{
dentro = true;
}
else
{
dentro = false;
}
this->update();
}

void fluxoCaixaWidget::setFluxo(QList<double> *f)
{
fluxo = f;

fluxoRect.clear();

int espacamento = 0;

if(fluxo->count() > 1)
{
espacamento = linhaTempo.width() / (fluxo->count() - 1);
}

for(int i = 0; i < fluxo->count(); i++)
{
if(i == 0)
{
fluxoRect.append(QRect(20, this->parentWidget()->height() / 2 - 20, 10, 50));
}
else
{
fluxoRect.append(QRect(20 + espacamento * i, this->parentWidget()->height() / 2 - 20, 10, 50));
}
}

this->update();
}

anda_skoa
31st May 2014, 14:47
Why are you accessing parentWidget()?

Aside from it not making any sense, what if there is no parent widget?

Cheers,
_

guidupas
31st May 2014, 14:53
Yes, you are right. But how can I have a size reference to create the QRect linhaTempo?. And the QRect linhaTempo must be resizable.

Thank you for the reply.

Cheers.

anda_skoa
31st May 2014, 17:00
Your own widget has a size as well, does it not?

Cheers,
_

guidupas
1st June 2014, 19:45
Yes, it has, but its does not resize when it has a fixed size.

Could you help me?

d_stranz
2nd June 2014, 00:46
Yes, it has, but its does not resize when it has a fixed size.

Are you using layouts in the parent widget? If not, this is almost certainly the cause of your widget not resizing. If you put your widget inside a layout on the parent widget, the layout will automatically resize your widget when the parent resizes.

guidupas
2nd June 2014, 23:42
Yes. My widget is inside a layout on the parent widget. But it does not resize



QGridLayout *gridLayoutInvestimento5 = new QGridLayout(boxInvestimento3);

fluxoCaixaWidget *fluxoCaixa = new fluxoCaixaWidget(boxInvestimento3);

boxInvestimento3->setLayout(gridLayoutInvestimento5);
gridLayoutInvestimento5->addWidget(fluxoCaixa);

d_stranz
3rd June 2014, 05:14
Sorry, I can't tell you what is wrong. You aren't showing us enough of your code to understand where your problem is. Six lines of code without any idea of where those lines are being used isn't enough information.

When I am faced with a problem like this, I create a demo project that simplifies the UI to the most basic level. If the problem still occurs in the demo project, then I figure out what is wrong and I fix it. It is very difficult to diagnose UI problems inside of a much larger project because usually too many other things are happening. Isolate the problem to the most basic parts and fix the problem.

guidupas
3rd June 2014, 19:50
Sorry, its because its a large code. I will put below a larger code

mainwindow.cpp


QWidget *MainWindow::criaEstruturaNovoIvestimento()
{
QWidget *tabInvestimento = new QWidget(this->tabWidgetInvestimento);

QGridLayout *gridLayoutInvestimento2 = new QGridLayout(tabInvestimento);
gridLayoutInvestimento2->setMargin(0);
QToolBox *toolboxInvestimento = new QToolBox(tabInvestimento);
gridLayoutInvestimento2->addWidget(toolboxInvestimento);
QWidget *boxInvestimento = new QWidget(toolboxInvestimento);
QWidget *boxInvestimento2 = new QWidget(toolboxInvestimento);
QWidget *boxInvestimento3 = new QWidget(toolboxInvestimento);

//SOME CODE

//HERE IS THE PROBLEM
//Tool Box 3
QGridLayout *gridLayoutInvestimento5 = new QGridLayout(boxInvestimento3);

fluxoCaixaWidget *fluxoCaixa = new fluxoCaixaWidget(boxInvestimento3);

boxInvestimento3->setLayout(gridLayoutInvestimento5);
gridLayoutInvestimento5->addWidget(fluxoCaixa);
//MORE CODE BELOW
}


fluxocaixawidget.cpp


#include "fluxocaixawidget.h"

#include <QDebug>

fluxoCaixaWidget::fluxoCaixaWidget(QWidget *parent) :
QWidget(parent)
{
linhaTempo.setRect(20, 100, 700, 30);

this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);



this->setMouseTracking(true);

dentro = false;
fluxo = NULL;
}

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

//linhaTempo.setRect(20, this->parentWidget()->height() / 2 - 20, this->parentWidget()->width()-65, 30);

//linhaTempo.setRect(20, this->parentWidget()->rect().height() / 2 - 20, this->parentWidget()->rect().width()-65, 30);

QPen caneta;

QBrush pincel(Qt::white);
painter.setBrush(pincel);

//painter.drawRect(parentWidget()->rect());
painter.drawRect(0,0,800,600);

if(this->dentro == true)
{
painter.drawText(QRect(20, 15, linhaTempo.width(), 25), "Linha do tempo", QTextOption::QTextOption(Qt::AlignCenter));
caneta.setWidth(3);
}
else
{
caneta.setWidth(2);
}

painter.setPen(caneta);

painter.drawRect(linhaTempo);

if(fluxo != NULL)
{
for(int i = 0; i < fluxo->count(); i++)
{
if(fluxo->at(i) < 0)
{
caneta.setColor(Qt::red);
}
else
{
if(fluxo->at(i) == 0)
{
caneta.setColor(Qt::black);
}
else
{
if(fluxo->at(i) > 0)
{
caneta.setColor(Qt::blue);
}
}
}

if(fluxoDentro.at(i) == true)
{
QString valor = QString::number(fluxo->at(i));
painter.drawText(QRect(20, 15, linhaTempo.width(), 25), valor, QTextOption::QTextOption(Qt::AlignCenter));
caneta.setWidth(3);
}
else
{
caneta.setWidth(2);
}
painter.setPen(caneta);
painter.drawRect(fluxoRect.at(i));
}
}
}

void fluxoCaixaWidget::mouseMoveEvent(QMouseEvent *)
{
if(linhaTempo.contains(this->mapFromGlobal(QCursor::pos())))
{
dentro = true;
}
else
{
dentro = false;
}

for(int i = 0; i < fluxoRect.count(); i++)
{
if(fluxoRect.at(i).contains(this->mapFromGlobal(QCursor::pos())))
{
fluxoDentro.insert(i, true);
dentro = false;
}
else
{
fluxoDentro.insert(i, false);
}
}

this->update();
}

void fluxoCaixaWidget::setFluxo(QList<double> *f)
{
fluxo = f;

fluxoRect.clear();
fluxoDentro.clear();

int espacamento = 0;

if(fluxo->count() > 1)
{
espacamento = linhaTempo.width() / (fluxo->count() - 1);
}

for(int i = 0; i < fluxo->count(); i++)
{
if(i == 0)
{
//fluxoRect.append(QRect(20, this->parentWidget()->height() / 2 - 20, 10, 50));
fluxoRect.append(QRect(20, linhaTempo.y(), 10, 50));
fluxoDentro.append(false);
}
else
{
//fluxoRect.append(QRect(20 + espacamento * i, this->parentWidget()->height() / 2 - 20, 10, 50));
fluxoRect.append(QRect(20 + espacamento * i, linhaTempo.y(), 10, 50));
fluxoDentro.append(false);
}
}

this->update();
}

guidupas
3rd June 2014, 23:12
when I do that, the QPushButton resizes but not my widget (fluxocaixawidget)


//Tool Box 3
QGridLayout *gridLayoutInvestimento5 = new QGridLayout(boxInvestimento3);

fluxoCaixaWidget *fluxoCaixa = new fluxoCaixaWidget(boxInvestimento3);

QPushButton *button = new QPushButton("Teste", boxInvestimento3);
QVBoxLayout *vertical = new QVBoxLayout(boxInvestimento3);
vertical->addWidget(button);
vertical->addWidget(fluxoCaixa);

//gridLayoutInvestimento5->addWidget(fluxoCaixa);

gridLayoutInvestimento5->addLayout(vertical,0,0);
boxInvestimento3->setLayout(gridLayoutInvestimento5);

//------------------------------------------------------------------------

d_stranz
4th June 2014, 00:12
Your "fluxoCaixaWidget" is derived from QWidget, right? Have you reimplemented the QWidget methods that are used by layouts to determine what size your widget is supposed to be?

In particular, methods like QWidget::minimumSize(), QWidget::minimumSizeHint(), and QWidget::sizeHint()?

guidupas
5th June 2014, 16:09
Hello d_stranz

First of all, thanks for the help

It is my first custom widget and I am not figuring out how I need to implement this methods. Can you help me with some code?

d_stranz
5th June 2014, 16:22
The most important thing is for your custom widget to return a reasonable sizeHint(). How big do you want it to be when it is first shown? 100 x 100, 200 x 200? Implement QWidget::sizeHint() to return QSize( 100, 100 ) or something sensible.

Do you want to items drawn inside your custom widget (in the paintEvent()) to change position as the widget is resized by the layout? Then you either need to customize the drawing (in paintEvent()) or change the position and size of the QGraphicsScene (in resizeEvent()) to make that happen.

There are many, many examples of writing custom widgets on the Web. Just Google for "custom QWidget example". The Analog Clock (http://qt-project.org/doc/qt-5/qtwidgets-widgets-analogclock-example.html) from the Qt documentation is a good place to start. It scales the clock size in the paintEvent() as the window size changes.

guidupas
7th June 2014, 15:03
SOLVED

Thank you d_stranz for yout replies and time



#include "fluxocaixawidget.h"

#include <QDebug>
#include <QGridLayout>

fluxoCaixaWidget::fluxoCaixaWidget(QWidget *parent) :
QWidget(parent)
{
this->setMouseTracking(true);

container.setRect(0,0,350,200);
dentro = false;
fluxo = NULL;
}

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

QPen caneta;

QBrush pincel(Qt::white);
painter.setBrush(pincel);

linhaTempo.setRect(20,container.height()/2 - 15, container.width()-40, 30);

painter.drawRect(container);

if(this->dentro == true)
{
painter.drawText(QRect(20, 15, linhaTempo.width(), 25), "Linha do tempo", QTextOption::QTextOption(Qt::AlignCenter));
caneta.setWidth(3);
}
else
{
caneta.setWidth(2);
}

painter.setPen(caneta);

painter.drawRect(linhaTempo);

if(fluxo != NULL)
{
for(int i = 0; i < fluxo->count(); i++)
{
if(fluxo->at(i) < 0)
{
caneta.setColor(Qt::red);
}
else
{
if(fluxo->at(i) == 0)
{
caneta.setColor(Qt::black);
}
else
{
if(fluxo->at(i) > 0)
{
caneta.setColor(Qt::blue);
}
}
}

if(fluxoDentro.at(i) == true)
{
QString valor = QString::number(fluxo->at(i));
painter.drawText(QRect(20, 15, linhaTempo.width(), 25), valor, QTextOption::QTextOption(Qt::AlignCenter));
caneta.setWidth(3);
}
else
{
caneta.setWidth(2);
}
painter.setPen(caneta);

int espacamento = 0;
if(fluxo->count() > 1)
{
espacamento = linhaTempo.width() / (fluxo->count() - 1);
}
if(i == 0)
{
painter.drawRect(20, linhaTempo.y(), 4, 50);
}
else
{
painter.drawRect(20 + espacamento * i, linhaTempo.y(), 4, 50);
}
}
}
}

void fluxoCaixaWidget::mouseMoveEvent(QMouseEvent *)
{
if(linhaTempo.contains(this->mapFromGlobal(QCursor::pos())))
{
dentro = true;
}
else
{
dentro = false;
}

for(int i = 0; i < fluxoRect.count(); i++)
{
if(fluxoRect.at(i).contains(this->mapFromGlobal(QCursor::pos())))
{
fluxoDentro.insert(i, true);
dentro = false;
}
else
{
fluxoDentro.insert(i, false);
}
}

this->update();
}

void fluxoCaixaWidget::resizeEvent(QResizeEvent *)
{
container.setRect(0,0, width(), height());

if(fluxo != NULL)
{
this->setFluxo(fluxo);
}
}

void fluxoCaixaWidget::setFluxo(QList<double> *f)
{
fluxo = f;

fluxoRect.clear();
fluxoDentro.clear();

int espacamento = 0;

if(fluxo->count() > 1)
{
espacamento = linhaTempo.width() / (fluxo->count() - 1);
}

for(int i = 0; i < fluxo->count(); i++)
{
if(i == 0)
{
fluxoRect.append(QRect(20, linhaTempo.y(), 4, 50));
fluxoDentro.append(false);
}
else
{
fluxoRect.append(QRect(20 + espacamento * i, linhaTempo.y(), 4, 50));
fluxoDentro.append(false);
}
}
}