Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to send QFrame to the back?



  • Hi, what I want to do is to draw lines at the front of the QFrame but currently it is drawn behind the QFrame. I am wondering if there is a way to move the qframe back.

    /*Adding qframe to my vboxlayout*/
    void sender::setNewDrawingPad(void)
    {
        path -> clear();
        pad -> setStyleSheet("background-color: rgb(220,220,220);");
        vbox -> addWidget(pad,1);
    }
    
    /*this is my paintevent*/
    void sender::paintEvent(QPaintEvent *event)
    {
        QPainter paint(this);
        paint.drawPath(*path);
    }
    
    
    

  • Lifetime Qt Champion

    To ensure which are called use Q_FUNC_INFO in your debug lines.

    There's no need for the installEventFilter call.

    You cannot paint on a widget from a different one. The correct way is like you started with QFrame, then override paint event, call the base class implementation and do your own painting afterward.


  • Lifetime Qt Champion

    Hi,

    How do you setup your widgets ?
    What is the role of sender with regard to that QFrame ?



  • @SGaist Thank you for your reply. This is my code for my sender class and the its setup. What I want to do is to display a drawing pad done by using QFrame when 'new' button is clicked.

    class sender : public QWidget
    {
        Q_OBJECT
    
    public:
        sender(QWidget *parent = nullptr);
        ~sender();
        void paintEvent(QPaintEvent *event);
        void mousePressEvent(QMouseEvent *event);
        void mouseReleaseEvent(QMouseEvent *event);
    
    private slots:
        void getPath();
        void clear();
        void setNewDrawingPad();
    
    private:
        QPainterPath *path;
        QHBoxLayout *hbox;
        QVBoxLayout *vbox;
        QFrame *pad;
        bool padOn;
    
    };
    
    sender::sender(QWidget *parent) : QWidget(parent)
    {
        setMinimumSize(QSize(500,500));
        path = new QPainterPath();
        pad= new QFrame;
        padOn = false;
    
        hbox = new QHBoxLayout;
        hbox -> setSpacing(3);
        vbox = new QVBoxLayout(this);
    
        QPushButton *New = new QPushButton("New",this);
        New -> setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
        connect(New, &QPushButton::clicked, this, &sender::setNewDrawingPad);
    
        hbox -> addStretch(1);
        vbox -> addLayout(hbox);
    }
    

  • Lifetime Qt Champion

    So you draw on sender and then want to show the result on your pad object ?



  • @SGaist A beginner's mistake made by a beginner. Thank you for point that out to me. But, I am still unsure how to paint on to my qframe. Do I change the QPainter painter(this) to QPainter painter(this->frame)?



  • Instead of changing this to this -> frame which obviously doesn't work, I create a MyFrame class which inherits from QFrame and overrides mousepressevent and mousereleaseevent so that I can store the positions into my path variable. In my window class, I has a private member that is a member of class myFrame. However, even though I am sure that I click on the frame, the mouseevent seems to be handled in the parent class instead of the child class. I am not sure why is that?

    
    class MyFrame : public QFrame
    {
        Q_OBJECT
    public:
        MyFrame(QWidget *parent = nullptr);
        void paintEvent(QPaintEvent *event);
        void mousePressEvent(QMouseEvent *event);
        void mouseReleaseEvent(QMouseEvent *event);
    
    private:
        QPainterPath *path;
    };
    
    class window : public QWidget
    {
        Q_OBJECT
    
    public:
        window(QWidget *parent = nullptr);
        void mousePressEvent(QMouseEvent *event);
        void mouseReleaseEvent(QMouseEvent *event);
    
    public slots:
    
    private slots:
    
    private:
        MyFrame *frame;
    };
    
    #include "window.h"
    #include "ui_window.h"
    #include <QDebug>
    #include <QtCore>
    #include <QBoxLayout>
    #include <QDebug>
    
    
    
    window::window(QWidget *parent)
        : QWidget(parent)
    {
        //setMinimumSize(QSize(500,500));
        frame = new MyFrame();
        QBoxLayout *layout = new QBoxLayout(QBoxLayout::TopToBottom);
        layout -> addWidget(frame);
        frame -> installEventFilter(this);
    }
    
    
    void window::mousePressEvent(QMouseEvent *event)
    {
        qDebug()<<event -> x()<<event -> y();
    }
    
    void window::mouseReleaseEvent(QMouseEvent *event)
    {
        qDebug()<<event -> x()<<event -> y();
    }
    MyFrame::MyFrame(QWidget *parent) : QFrame(parent)
    {
        setStyleSheet("background-color: rgb(220,220,220)");
    }
    
    void MyFrame::mousePressEvent(QMouseEvent *event)
    {
        qDebug()<<event ->x()<<event->y();
    }
    
    void MyFrame::mouseReleaseEvent(QMouseEvent *event)
    {
        qDebug()<<event ->x()<<event->y();
    }
    

  • Lifetime Qt Champion

    To ensure which are called use Q_FUNC_INFO in your debug lines.

    There's no need for the installEventFilter call.

    You cannot paint on a widget from a different one. The correct way is like you started with QFrame, then override paint event, call the base class implementation and do your own painting afterward.


Log in to reply