Search code examples
c++qtqt5qpixmap

Qt cannot save pixmap


Hello i have a strange problem to save pixmap.

My Widget Header

public:
  QPixmap *base;  //Base Poses
  QPixmap *Hair;  //Hair
  QPixmap *Composited;  //Final Composition

  bool compisition = false;

  void Composite();

My Widget Cpp

At paintEvent

 base = &pic;
    Hair = &hairs;

    if(compisition)
    {
        QPixmap pix(128,192);
        QPainter *p = new QPainter(&pix);

        p->drawPixmap(0,0,128,192,*base);
        p->drawPixmap(0,0,128,192,*Hair);

        Composited = &pix;
        compisition = false;
    }
void AnimPreview::Composite()
{
    compisition = true;
    this->update();


}

At main form source

void MainWindow::on_commandLinkButton_clicked()
{
    QString file = QFileDialog::getSaveFileName(this,
                                               tr("Save Sprite file"),
                                               "",tr("File PNG (*.png)"));

    const QPixmap *pix = ui->SpriteFront->pixmap();

    if(!file.isEmpty())
    {
        QFile files(file);
        files.open(QIODevice::WriteOnly);

        ui->SpriteFront->Composite();
        ui->SpriteFront->Composited->save(&files,"PNG");
    }
}

When i try to save a file, the process work but whit on error

An unhandled win32 exception

For more information complete code here

https://pastebin.com/GtaVCXGf


Solution

  • I have avoided reviewing where the error can be generated since there are many possible sources of the problem, among them the following:

    • It is not necessary that you create QPixmap pointers since in the end you will have the job of eliminating it from memory.

    • The same happens with QPainter since it only needs to be a local variable, in addition to that the painting is not done immediately, to be sure that it is painted you must call its end() method.

    • paintEvent is a protected method, so by design we prefer it to remain so.

    • It is not necessary to use a QFile to save an image, you can directly pass the filename to it.

    Considering all the above, we obtain the following:

    *.h

    #ifndef ANIMPREVIEW_H
    #define ANIMPREVIEW_H
    
    #include <QLabel>
    #include <QPixmap>
    
    class AnimPreview : public QLabel
    {
    public:
        AnimPreview(QWidget *parent = 0);
    
        void Rotate(int value);
        void Composite();
        void Create(int _sex, int _hair);
        QPixmap Composited;
    
    private:
        int sex = 0;
        int hair = 0;
        bool draw = true;
    
        int rotation = 0;
        const int offsetX = 16;
        const int offsetY = 32;
    
        QPixmap base;
        QPixmap Hair;
        bool compisition = false;
    
    protected:
        void paintEvent(QPaintEvent *);
    };
    
    #endif // ANIMPREVIEW_H
    

    *.cpp

    #include "animpreview.h"
    
    #include <QPainter>
    
    AnimPreview::AnimPreview(QWidget *parent):QLabel(parent)
    {
    }
    
    void AnimPreview::paintEvent(QPaintEvent *){
    
        QPainter p(this);
        QPixmap pic;
        QPixmap hairs;
    
        if(draw)
        {
            //Sesso
            switch(sex)
            {
            case 0:
                pic.load(":/Male/Base/Res/man_f.png");
                break;
            case 1:
                pic.load(":/Male/Base/Res/woman_f.png");
    
                break;
            }
    
            //capelli
            if(sex == 1)
            {
                switch(hair)
                {
                case 1:
                    hairs.load(":/Female/Hair/Res/7_aqua.png");
                    break;
                case 2:
                    hairs.load(":/Female/Hair/Res/5_gold.png");
                    break;
                }
            }
    
            if(sex == 0)
            {
                switch (hair)
                {
                case 0:
                    break;
                case 1:
                    hairs.load(":/Male/Hair/Res/1_aqua.png");
                    break;
                case 2:
                    hairs.load(":/Male/Hair/Res/14_black.png");
                    break;
                }
            }
    
        }
    
        p.drawPixmap(width()/2 - offsetX,height()/2 - offsetY,pic,0,rotation,32,48);
        p.drawPixmap(width()/2 - offsetX,height()/2 - offsetY,hairs,0,rotation,32,48);
        p.drawRect(0,0, width()-1, height()-1);
    
        base = pic;
        Hair = hairs;
    
        if(compisition)
        {
            QPixmap pix(128,192);
            QPainter p(&pix);
    
            p.drawPixmap(0,0,128,192, base);
            p.drawPixmap(0,0,128,192, Hair);
    
            p.end();
    
            Composited = pix;
            compisition = false;
        }
    }
    
    void AnimPreview::Rotate(int value)
    {
        rotation = value;
        update();
    }
    
    void AnimPreview::Create(int _sex, int _hair)
    {
        sex = _sex;
        hair = _hair;
        draw = true;
    }
    
    void AnimPreview::Composite()
    {
        compisition = true;
        update();
    }
    

    void MainWindow::on_commandLinkButton_clicked()
    {
        QString file = QFileDialog::getSaveFileName(this,
                                                    tr("Save Sprite file"),
                                                    "",tr("File PNG (*.png)"));
    
        if(!file.isEmpty())
        {
            ui->SpriteFront->Composite();
            ui->SpriteFront->Composited.save(file,"PNG");
        }
    }