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

QPainter begin Error



  • I use QPainter in a thread to draw QImage. the Function run once is right. But in second time, at pait.begin(g_GE->GetDrawBuffer()) will error. The infomation is Signal Received windows, Signal name:SIGSEGV, Signal meaning: Segmentation fault.
    The Debuger output is: QPainterPrivate::attachPainterPrivate(QPainter*, QPaintDevice*) error.
    The code :
    QRect target;
    pait.begin(g_GE->GetDrawBuffer());
    pait.setRenderHint(QPainter::Antialiasing, true);
    g_GE->SetisDraw(true);
    while(g_GE->GetImageArray()->size()) {
    ImageInfo* pInfo = g_GE->GetImageArray()->at(0);
    g_GE->GetImageArray()->pop_front();
    if (pInfo->type == _gedraw) {
    target = pInfo->rect;
    pait.drawImage(target, *(pInfo->pImg), pInfo->rect);
    }
    }
    pait.end();
    g_GE->SetisDraw(false);
    return 0;

    Version is Qt 5.14.1 MinGW 7.3.0 32bit
    OS:Windows 10



  • @Runner111

    Do you try to paint on the same image twice (from different threads)?



  • No, I have only one thread.



  • @Pl45m4 And I use pait.isActive(); to check the pait is idle now.


  • Lifetime Qt Champion

    @Runner111 said in QPainter begin Error:

    g_GE

    Is this a valid pointer when the code is executed second time?



  • @jsulm Yes, it is a global object, because my project has some C interface, so use global object



  • This post is deleted!


  • @Runner111 said in QPainter begin Error:

    qpainter

    I try MSVC2015 the error is gone, but it will output
    22:46:08: Debugging starts
    QPainter::begin: A paint device can only be painted by one painter at a time.
    QPainter::end: Painter not active, aborted
    QPainter::begin: A paint device can only be painted by one painter at a time.
    QPainter::setRenderHint: Painter must be active to set rendering hints
    QPainter::setBackgroundMode: Painter not active
    QPainter::end: Painter not active, aborted
    QPainter::begin: A paint device can only be painted by one painter at a time.
    QPainter::setRenderHint: Painter must be active to set rendering hints
    QPainter::setBackgroundMode: Painter not active
    QPainter::end: Painter not active, aborted

    But the paintEvent in MainWindow, I already delete the code, it is a empty function, who call the QPainter?


  • Lifetime Qt Champion

    Hi,

    Can you show the actual code you are using including function signature ?



  • @SGaist The Project have many file, but I can explain the mathod. This project will read more RGB Data from Peripheral module, I use a thread to read the data, create a image, and then show on the mainwindow.

    In mainwindow:

        ui->setupUi(this);
        g_GE = &m_GraphEngine;
        m_GraphEngine.InitGraphEngine(this);
        QUIThread* p = new QUIThread;
        p->start();
    

    In mainwindow paintevent:

    void MainWindow::paintEvent(QPaintEvent *e) {
    }
    

    I doubt the part will conflict with thread, so I delete it.
    In Thread, because I need make some Interface for Peripheral module, some function write in C.

    void GraphEngine::InitGraphEngine(MainWindow* w) {
        QFile file(".\\GraphConfig.ini");
        if (!file.open(QIODevice::ReadOnly)) {
            return;
        }
    
        QTextStream in(&file);
        QString info = file.readLine();
        m_width = info.right(info.length() - info.indexOf(":") - 1).toInt();
        info = file.readLine();
        m_height = info.right(info.length() - info.indexOf(":") - 1).toInt();
        file.close();
        m_DrawBuffer = new QImage(m_width, m_height, QImage::Format_ARGB32);
        m_BackBuffer = new QImage(m_width, m_height, QImage::Format_ARGB32);
        m_Window = w;
    }
    
    STHBITMAP STCreateBitmap(int nWidth, int nHeight, t_sgaColorFormat format, const void* lpvBits) {
        int i;
        unsigned long r;
        unsigned long g;
        unsigned long b;
        unsigned short* shortdata;
        unsigned long* longdata;
        unsigned char* pdata = new unsigned char[nWidth * nHeight * 4];
    
        shortdata = (unsigned short*)lpvBits;
        longdata = (unsigned long*)pdata;
        if (format.bufferFmt == SGA_PIX_FORMAT_RGB16) {        
            for (i = 0; i < nWidth * nHeight; i ++) {
                r = shortdata[i] >> 11;
                g = (shortdata[i] &0x7e0) >> 5;
                b = shortdata[i] & 0x1f;
                longdata[i] = 0xFF000000 | (r << 16) | (g << 8) | b;
            }
        }
        else if (format.bufferFmt == SGA_PIX_FORMAT_ARGB24){
            memcpy(pdata, lpvBits, nWidth * nHeight * 4);
        }
        QImage* pimage = new QImage(pdata, nWidth, nHeight, 4 * nWidth, QImage::Format_ARGB32);
        return (STHBITMAP)pimage;
    }
    
    int addImage( int x0, int ly0, int x1, int ly1, STHBITMAP pSrc, float nXSrc, int nYSrc, STROP dwRop) {
        ImageInfo* pInfo = new ImageInfo;
        pInfo->pImg = (QImage*)pSrc;
        pInfo->scissorrect.setX(g_GE->GetScissorX());
        pInfo->scissorrect.setY(g_GE->GetScissorY());
        pInfo->scissorrect.setWidth(g_GE->GetScissorW());
        pInfo->scissorrect.setHeight(g_GE->GetScissorH());
        pInfo->rect.setX(x0);
        pInfo->rect.setY(ly0);
        pInfo->rect.setWidth(x1 - x0);
        pInfo->rect.setHeight(ly1 - ly0);
        pInfo->type = _gedraw;
        g_GE->GetImageArray()->insert(g_GE->GetImageArray()->size(), pInfo);
        return 0;
    }
    
    int STFinish(STHDC hDC) {
    #if 1
        QRect target;
        QPainter* pait = new QPainter;
        pait->begin(g_GE->GetDrawBuffer());
        pait->setRenderHint(QPainter::Antialiasing, true);
        pait->setBackgroundMode(Qt::TransparentMode);
        g_GE->SetisDraw(true);
        while(g_GE->GetImageArray()->size()) {
            ImageInfo* pInfo = g_GE->GetImageArray()->at(0);
            g_GE->GetImageArray()->pop_front();
            if (pInfo->type == _gedraw) {
                target = pInfo->rect;
                pait->drawImage(target, *(pInfo->pImg), pInfo->pImg->rect());
            }
    }
        pait->end();
        delete pait;
        g_GE->SetisDraw(false);
    #endif
        return 0;
    }
    

  • Lifetime Qt Champion

    Taking a look at it, it seems you might be over-engineering some things.

    Can you explain the C interface you are using ?
    Is it something public that can be looked at ?
    Why do you need that global object ?



  • @SGaist Because I need use a device, its library is written by C. But I already fix this bug.
    QImage need fill first.


Log in to reply