how to parent qpainter (code) to QTabWidget (Design Mode)



  • Hi

    I have a QMainWindow that contains a QTabWidget, done in QT-Creator Design Mode.
    Now I have some code from another project that is a QPainter code. When I add the code the painter object is drawn behind the QTabWidget on the QMainWindow. How can I make the "QPainter painter(this)" parent to the QTabWidget?

    mainwindow.cpp:

    ...
    MainWindow::MainWindow(QWidget *parent) :
    	QMainWindow(parent),
    	ui(new Ui::MainWindow)
    {
    	ui->setupUi(this);
    	update_pha();
    	
    	QTimer *timer = new QTimer(this);
    	connect(timer, &QTimer::timeout, this, &MainWindow::update_pha);
    	timer->start(1000);
    }
    
    MainWindow::~MainWindow()
    {
    	delete ui;
    
    }
    ...
    void MainWindow::paintEvent(QPaintEvent *){				// Paint the circle an and the stuff inside
    	// qDebug() << p_rotation;
    	QPainter painter(this);
    	QPen whitethindotted(Qt::lightGray,1 ,Qt::DotLine);
    	painter.setRenderHint(QPainter::Antialiasing);
    
    	// Main circle position
    	QPoint center(90,380);
    	painter.translate(center);
    ...
    

    here is an image:
    https://pauledd.files.wordpress.com/2016/08/parent.jpg


  • Qt Champions 2016

    Hi
    You cannot change where painter paint that way

    The paintEvent(QPaintEvent *) is where you are allowed to use painter-
    so if you want to draw on QTabWidget, you need to subclass it and create a
    paintEvent for that.

    But its unclear what you your goal is.

    If you just want to show the output from painter, sort of like an image, you
    can paint to a Pixmap and display the pixmap in a label.

    Pixmap pix(500,500);
    QPainter paint(pix);
    paint.setPen( QColor(255,34,255,255) );
    paint.drawRect(15,15,100,100);
    ui->somelabel->setPixmap(pix);



  • My goal is to have the painter update every second so the image method might not be the way to do it.

    @mrjj said in how to parent qpainter (code) to QTabWidget (Design Mode):

    you need to subclass it and create a
    paintEvent for that.

    I need to read into subclassing...
    A subclass of what? Of the QTabWidget?


  • Qt Champions 2016

    @pauledd

    • A subclass of what? Of the QTabWidget?

    If you want to draw on that directly.
    Still not clear how/where you want this drawing.

    Alternativ you can make a subclass of QWidget and just give it
    the paintEvent. And then place this into the TabWidget like any other widget and
    simply tell it to update() via the timer.

    class MyWidget : public QWidget
    {
    ...
    protected:
        void paintEvent(QPaintEvent *) { code };
    };
    

    You can easy use your own class in Designer with the promote feature
    http://doc.qt.io/qt-4.8/designer-using-custom-widgets.html

    That let you design with a placeholder and when your code runs, its your widget.



  • @mrjj said in how to parent qpainter (code) to QTabWidget (Design Mode):

    Still not clear how/where you want this drawing.

    It should go there, my old application is on the right, the new on the left:
    https://pauledd.files.wordpress.com/2016/08/parent2.jpg
    Its all static. It is fixed in position and the window size will not change.

    I will try your suggestions and figure out how it works, so far thank you.


  • Qt Champions 2016

    @pauledd
    Ok, thanks. very clear :)
    So thats actually a Tab Page Widget you want to draw on.
    I suggest to use the QWidget way as it easier than getting to draw directly on
    the Tabwidgets page child.



  • Made it! (With costum widget and promote)
    https://pauledd.files.wordpress.com/2016/08/parent3.jpg

    The video that helped me:
    https://www.youtube.com/watch?v=Yt-YCxgEnyw

    Thanks @mrjj for directing to the solution!


  • Qt Champions 2016

    @pauledd
    Hi
    That was fast. :)
    Nice video. Good to know ! :)



  • @mrjj said in how to parent qpainter (code) to QTabWidget (Design Mode):

    Alternativ you can make a subclass of QWidget and just give it
    the paintEvent. And then place this into the TabWidget like any other widget and
    simply tell it to update() via the timer.

    Ok, I am back with more problems. I decided to not use the designer at all. I want to code it
    by myself to understand whats all behind that.

    A few lines of code. A mainwindow based on QWidget contains QGridLayout that contains QTabWidget that contains to tabs made of two QWidgets.

    A QPaintEvent that has "tab1" as parent. Why does it not paint that line?

    main.cpp

    #include <QApplication>
    #include <QTabWidget>
    #include <QWidget>
    #include "mainwindow.h"
    int main(int argc, char **argv){
    	
    	QApplication app(argc, argv);
    	
    	MainWindow mainWindow;
    	mainWindow.show();
    	return app.exec();
    }
    
    

    mainwindow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    #include <QWidget>
    #include <QTabWidget>
    #include <QPainter>
    
    class MainWindow : public QWidget
    {
    	Q_OBJECT
    public:
    	explicit MainWindow(QWidget *parent = 0);
    protected:
    	void paintEvent(QPaintEvent *event);
    private:
    	QTabWidget *tabWidget;
    	QWidget *tab1;
    	QWidget *tab2;	
    };
    #endif // MAINWINDOW_H
    
    

    mainwindow.cpp

    #include "mainwindow.h"
    #include <QGridLayout>
    
    
    MainWindow::MainWindow(QWidget *parent) : QWidget(parent)
    {
    	resize(800,480);
    	QGridLayout *gl = new QGridLayout(this);
    	tabWidget = new QTabWidget();
    	tab1 = new QWidget();
    	tab2 = new QWidget();
    	tabWidget->setStyleSheet("QTabWidget {font-size:20px;font-weight:bold}");
    	tabWidget->addTab(tab1,"Finder");
    	tabWidget->addTab(tab2,"Alignment");
    	gl->addWidget(tabWidget);
    }
    
    void MainWindow::paintEvent(QPaintEvent *event)
    {
    	QPainter painter(tab1);
    	painter.drawLine(0,0,800,480);
    
    }
    
    

    I also get this application output:

    Starting /home/paul/store/c++/build-pat_tab2-QT5_6_1-Debug/pat_tab2...
    QWidget::paintEngine: Should no longer be called
    QPainter::begin: Paint device returned engine == 0, type: 1
    


  • I think I got it. I removed the tab1 widget and subclassed (I hope that is subclassing) it in a new class:

    mywidget.h

    #ifndef MYWIDGET_H
    #define MYWIDGET_H
    
    #include <QWidget>
    #include <QPainter>
    
    class MyWidget : public QWidget
    {
    Q_OBJECT
    	
    public:
    	MyWidget(QWidget *parent = 0);
    	~MyWidget();
    	
    protected:
    	void paintEvent(QPaintEvent *event);
    };
    
    
    #endif // MYWIDGET_H
    
    

    mywidget.cpp

    #include "mywidget.h"
    
    MyWidget::MyWidget(QWidget *parent)
    {
    	
    }
    
    MyWidget::~MyWidget()
    {
    	
    }
    
    void MyWidget::paintEvent(QPaintEvent *event)
    {
    	QPainter painter(this);
    	painter.drawLine(0,0,400,400);
    	
    }
    
    

    Then I replaced the declaration in mainwindow.h with " MyWidget *tab1;" and in mainwindow.cpp "tab1 = new MyWidget();".
    And that is how it looks:
    https://pauledd.files.wordpress.com/2016/08/tabwidget.jpg


  • Qt Champions 2016

    hi
    just a note

    void MainWindow::paintEvent(QPaintEvent *event)
    {
    	QPainter painter(tab1);
    

    seems a bit surprising.

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

    would be as normally seen.



  • @mrjj you are absolutely right. That was in my faulty first try. In the new tab1 QWidget subclass (mywidget.cpp) it is once more "QPainter painter(this);"
    But thank you for hinting the wrong code :)


  • Qt Champions 2016

    @pauledd
    :)
    class MyWidget : public QWidget << yes that is subclassing :)

    Also, a widget can only paint on it self.
    its not possible to paint on other widget from inside a
    paintevent.
    Thats why the first sample didnt work. You asked painter to paint on tab from inside mainwindows paintEvent :)
    I guess you already found out but its just to make clear for other readers.



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