[SOLVED] QWidget subclass drawing in wrong place



  • 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();
    

    }
    @


  • Lifetime Qt Champion

    Hi,

    From a quick overlook, you are doing your painting based of the parentWidget position which doesn't really make sense. You should only use your current widget geometry to do that.



  • Yes, you are right. But how can I have a size reference to create the QRect linhaTempo?. And the QRect linhaTempo must be resizable. And its does not resize when it has a fixed size.

    Thank you for the reply.

    Cheers.


  • Lifetime Qt Champion

    Use the widget geometry ?



  • I tryed

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

    inside my widget constructor, but it stills not resizing.


  • Lifetime Qt Champion

    What do you mean it's not resizing ? The widget ? Did you put it in a layout manager ?

    What exactly are you trying to achieve ?



  • Yes. My custom widget is not resizing when the window resizes.

    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();
    

    }
    @


  • Lifetime Qt Champion

    If MainWindow is a QMainWindow then you are not setting your widget as central widget.

    In the other case, you don't put your widget in a layout set on MainWindow



  • The widget is inside a QGridLayout as the line 21 shows. This layout is inside a tabwidget and resizes normally. I did the same procedure to all tabs using QWidgets as QPushButtons, QLineedits, etc and it works fine.

    Just when I put my widget inside it does not work. Theres something I am no figuring out about this code.



  • 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);
    
    //------------------------------------------------------------------------
    

    @


  • Lifetime Qt Champion

    When giving a layout a widget parent you set it on the widget. This means that currently you start by setting gridLayoutInvestimento5 as layout of boxInvestimento3. Then you create fluxoCaixa and button as child of boxInvestimento3. Then you create vertical as child of boxInvestimento3 thus making it its layout manager (you should have a warning telling you that boxInvestimento3 already has a layout manager when running).
    Then you put both button and fluxoCaixa in vertical and then you put that in gridLayoutInvestimento5 and finally set gridLayoutInvestimento5 as boxInvestimento3.

    That's pretty messy

    @
    //Tool Box 3
    fluxoCaixaWidget *fluxoCaixa = new fluxoCaixaWidget;
    QPushButton *button = new QPushButton(tr("Teste"));
    QVBoxLayout *vertical = new QVBoxLayout;
    vertical->addWidget(button);
    vertical->addWidget(fluxoCaixa);

    QGridLayout *gridLayoutInvestimento5 = new QGridLayout(boxInvestimento3);
    gridLayoutInvestimento5->addLayout(vertical,0,0);
    

    @

    When using layouts the parenting is done for you.



  • Hello SGaist!

    First of all, thanks for the help.

    I changed the code, but it stills no expanding or shrinking when the window is rezised.

    The button resizes but fluxocaixawidget dont.

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

    fluxoCaixaWidget *fluxoCaixa = new fluxoCaixaWidget(boxInvestimento3);
    
    QPushButton *button = new QPushButton("Teste", boxInvestimento3);
    gridLayoutInvestimento5->addWidget(button,0,0);
    gridLayoutInvestimento5->addWidget(fluxoCaixa,1,0);
    

    @


  • Lifetime Qt Champion

    Did you tried it within just a simple widget ?



  • I did 2 examples with my custom widget (fluxocaixawidget). In both cases my widget do not change the size when the window is resized.

    First
    @
    #include "mainwindow.h"
    #include "ui_mainwindow.h"

    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
    ui->setupUi(this);

    fluxoCaixaWidget *fluxo = new fluxoCaixaWidget(this);
    
    setCentralWidget(fluxo);
    

    }

    MainWindow::~MainWindow()
    {
    delete ui;
    }
    @

    Second
    @
    #include "mainwindow.h"
    #include "ui_mainwindow.h"

    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
    ui->setupUi(this);

    fluxoCaixaWidget *fluxo = new fluxoCaixaWidget(this);
    
    QPushButton *button = new QPushButton("Teste", this);
    
    QGridLayout *gridLayout = new QGridLayout(this->ui->frame);
    
    gridLayout->addWidget(button,0,0);
    
    gridLayout->addWidget(fluxo,1,0);
    

    }

    MainWindow::~MainWindow()
    {
    delete ui;
    }
    @

    fluxocaixawidget.cpp
    @
    #include "fluxocaixawidget.h"

    #include <QDebug>
    #include <QGridLayout>

    fluxoCaixaWidget::fluxoCaixaWidget(QWidget *parent) :
    QWidget(parent)
    {
    this->setMouseTracking(true);
    //this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

    linhaTempo.setRect(20,this->sizeHint().height() / 2 - 15, this->sizeHint().width()-40, 30);
    dentro = false;
    fluxo = NULL;
    

    }

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

    QPen caneta;
    
    QBrush pincel(Qt::white);
    painter.setBrush(pincel);
    
    painter.drawRect(0,0,this->sizeHint().width(), this->sizeHint().height());
    
    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));
        }
    }
    //this->updateGeometry();
    

    }

    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, linhaTempo.y(), 10, 50));
            fluxoDentro.append(false);
        }
        else
        {
            fluxoRect.append(QRect(20 + espacamento * i, linhaTempo.y(), 10, 50));
            fluxoDentro.append(false);
        }
    }
    
    this->update();
    

    }

    QSize fluxoCaixaWidget::sizeHint() const
    {
    return QSize(350, 200);
    }
    @

    fluxocaixawidget.h
    @
    #ifndef FLUXOCAIXAWIDGET_H
    #define FLUXOCAIXAWIDGET_H

    #include <QWidget>
    #include <QPainter>

    class fluxoCaixaWidget : public QWidget
    {
    Q_OBJECT
    public:
    explicit fluxoCaixaWidget(QWidget *parent = 0);

    void setFluxo(QList<double> *f);
    QSize sizeHint() const;
    

    protected:
    void paintEvent(QPaintEvent *);
    void mouseMoveEvent(QMouseEvent *);

    private:
    bool dentro;
    QRect linhaTempo;
    QList<double> *fluxo;
    QList<QRect> fluxoRect;
    QList<bool> fluxoDentro;

    signals:

    public slots:

    };

    #endif // FLUXOCAIXAWIDGET_H
    @


  • Lifetime Qt Champion

    You initialize linhaTempo once and never update it. One way would be to reimplement the resizeEvent method to update linhaTempo. But not the question is: do you really need that variable ? Can't you just use the widget geometry in paintEvent ?



  • Well, yes, I need it. This variable is a timeline, a very important point in the widget.

    This is my first custem widget. Could you show me how to use the geometry the make it resizable?


  • Lifetime Qt Champion

    Have a look at e.g. the analog clock example in Qt's documentation



  • SOLVED

    SGaist, thank you for your 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);
        }
    }
    

    }
    @


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.