QPaintEven



  • Dear forum,
    I have created a GUI that can display a pie chart using QPainter (draw(QPainter* painter)) and I'm trying to modify the pie chart via a signal (pie values) from my MainWindow. In my Designer, I promoted a widget to the following class:

    class PieChartWidget : public QWidget
    {
    Q_OBJECT
    public:
    PieChartWidget(QWidget parent);
    ~PieChartWidget();
    int draw(QPainter
    painter);
    void setColor(Qt::GlobalColor);
    protected:
    void paintEvent(QPaintEvent* e);
    };

    void PieChartWidget::paintEvent(QPaintEvent* e)
    {
    QWidget::paintEvent(e);
    QPainter painter(this);
    QFont font;
    painter.begin(this);
    PieChartWidget PieChart(this);
    PieChart.draw(&painter);
    PieChart.setColor(Qt::green);
    }

    How can I modify the pie chart from my MainWindow with a signal? I have tried to create an object and call the setColor function but nothing happen and I know my function works well because when I run the code, the pie chart display the right color.

    Can you help me to figure out what I'm missing here?

    Kind Regards,

    Massi



  • Your code should not work, it should not even compile.
    For example: int draw(QPainter painter); and PieChart.draw(&painter); refer to completely different functions.

    • I am not sure what exactly PieChartWidget::setColor does since you do not show the code.
      But you probably wanted to set variable which will store the color used somewhere within draw().
      Natural choice in this case would be to add QColor variable to PieChartWidget , which you would set with setColor.
      If above is true, first PieChart::setColor( ... ); should have been called before PieChart::draw(&painter);

    • creating instance of the class and not even showing it in the paintEvent does not make any sense, even more if you tried to show it there you would get something like stack overflow. paintEvent only needs to draw widget, its elements or may be child widgets.

    paintEvent will be called automatically when needed, but if you changed myColor you may call update() then call to it will be scheduled.
    Also check parameters of PieChartWidget constructor.
    It should take pointer to widget.
    Below you may find code which should explain basics:

    #include <QColor>
    class PieChartWidget : public QWidget
    {
    Q_OBJECT
    public:
    PieChartWidget(QWidget* parent);
    ~PieChartWidget();
    void setColor(QColor c) { myColor = c; }

    protected:
    int draw(QPainter* painter) {
    ....
    // use myColor
    ...
    }
    void paintEvent(QPaintEvent* e);

    private :
    QColor myColor;
    };

    void PieChartWidget::paintEvent(QPaintEvent* e)
    {
    QPainter painter(this);
    painter.begin(this);
    draw(&painter);
    }

    Make sure myColor is initialized



  • Thank you for your reply
    Well here is my original code, it works fine for changing the color but I'm facing an issue that I tried to avoid; the paint is done on the MainWindow and I don't know how to set it (draw it) in the widget. So I tried to create a class that inherit from QWidget, set paintEvent and promote the widget to this class and use a signal from the MainWindow to change the color

    #include piechartwidget.h

    class mainClass : public QMainWindow
    {
    Q_OBJECT
    public:
    mainClass(QWidget *parent = 0);
    ~mainClass();

      /**some functions**/
    

    protected:
    void paintEvent(QPaintEvent* e);

    public slots:

       /**some functions**/
    

    private:
    Ui::mainClass ui;
    };

    cpp file
    void mainClass::paintEvent(QPaintEvent* e)
    {
    QPainter painter(this);
    painter.begin(this); <-- it set the paint in mainClass, how can I set it within the widget?
    PieChartWidget PieChart;
    PieChart.setColor(Qt::green);
    PieChart.draw(&painter); // I set the color in this function
    /some codes/
    }

    /************************************/
    class PieChartWidget
    {
    public:
    PieChartWidget();
    ~PieChartWidget();

       /**some functions**/
    

    void setColor(QColor c) { myColor = c; }

       /**some functions**/
    

    void draw(QPainter* painter) {
    /use myColor/
    }

    private :
    QColor myColor;
    };

    Regards,


  • Lifetime Qt Champion

    Hi,

    From your last code, you're doing it wrong. You should only reimplement the paint event from PieChartWidget since it's the widgets that knows how to draw said pie.

    You should also have an instance of it as e.g. the MainWindow central widget. Then just change it's color when needed. That will avoid useless allocations.



  • @SGaist said:

    MainWindow central widget

    Thank you very much for your help!! I decided to enable the painting & changing color by pressing a button. I added another function to set a bool variable (enableDrawing) as follow:
    from the main class

    this->ui.widget.setColor(Qt::red);
    this->ui.widget.setEnable(true);
    
    class PieChartWidget : public QWidget
    {
    public:
    PieChartWidget(QWidget* parent);
    ~PieChartWidget();
    
       /**some functions**/
    void setColor(QColor c) { myColor = c; }
    void setEnable(bool ok){enableDrawing = ok;}
    
       /**some functions**/
    void draw(QPainter* painter) {
    /use myColor/
    }
    protected:
    void paintEvent(QPaintEvent* e)
    {
    if (enableDrawing){
    QPainter painter(this);
    painter.begin(this); 
    setColor(Qt::green);
    draw(&painter);
    /some codes/
    enableDrawing = false;
    }
    
    private:
    bool enableDrawing = false;
    }
    

    I'm not familiar with painting, but now I'm facing another issues.

    • If I resize the widget or the mainWindow or even pressing another button, the paint disappears. how can I keep the previous paint?

    • And how can I delete paint and restart a new one (e.g. set new values for the pie chart) because it seems overdrawing on the previous paint?

    I ll try a second way using plugin and see if it works better.

    Regards,

    [edit: Added missing coding tags ``` SGaist]


  • Lifetime Qt Champion

    1. Did you put your widgets in a layout ?
    2. Just change the color and call update in the slot, that will schedule a new paint event.

    I'd recommend mastering the painting before trying to create plugins.



  • @SGaist

    Yes exactly, I put the widget in a layout vertically split, btw I already called update in the slot:

    this->ui.widget->repaint();
    this->ui.widget->setColor(Qt::red);
    this->ui.widget->setEnable(true);
    this->ui.widget->update(); 
    

    every time I resize the widget, it creates new instance of QWidget and set a new empty paintEvent(QPaintEvent* e) !

    Regards,


  • Lifetime Qt Champion

    Why are you recreating that widget all the time ?



  • @SGaist
    No I'm not creating a new widget. Just when I resize the widget, it seems repainting the widget (creating new one). I'm investigating the resizevent function.


  • Lifetime Qt Champion

    If you put your widget in a layout you won't have to fiddle with the resize event.


Log in to reply
 

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