[Qt-interest] Problem drawning in the GUI Thread with Data from another Thread

O Caldas caldaz.sheep at gmail.com
Fri Jul 3 02:49:24 CEST 2009


ive tyed this

void PopGraph::paintEvent(QPaintEvent*){
    QPainter painter2(this);
    buffer2 = buffer;
    painter2.drawImage(QPoint(0,0), *buffer2);
}

and also tryed this

void PopGraph::paintEvent(QPaintEvent*){
    QPainter painter2(this);
    temp = buffer2;
    buffer2 = buffer;
    buffer = temp;
    painter2.drawImage(QPoint(0,0), *buffer2);

}

and in the two methods the program still crashs
and btw, the calculation part is correct, the application only crash when is
drawning the graphic


2009/7/2 Malyushytsky, Alex <alex at wai.com>

> I am not sure I correctly followed your design.
> I assume graphUpdate is called  from the working thread (through signal
> slot mechanics or directly).
> In this case you have to make sure graphUpdate is not running when
> painter2.drawImage(QPoint(0,0), *buffer);
> is executed.
> Otherwise for example buffer may be deleted when drawImage is still
> drawing. This means application crash or termination (well exception
> handling would be great any way).
>
> QMutex or other thread safety mechanics can be a friend here.
>
> The simplest approach would be to lock  paintEvent and graphUpdate with
> mutex, but I would suggest to add some code make them actually run
> simultaneously, in order to allow graphUpdate to draw into its buffer while
> Widget is painting.
>
> In this case 2 buffers are required. One buffer is used to draw from the
> paintEvent. Another buffer is used by graphUpdate to draw into.
>
> Widget itself paints from the buffer any time it needs an update (no matter
> who caused the update).
> graphUpdate is always drawing into second buffer, but when it finish
> drawing and the image is ready to be shown, it swaps the buffers (it means
> just changing pointers) and then forces Widget update (through thread safe
> procedures, like Queued connection).
>
> You still will need to guard the pointers when swapping them and in the
> paintEvent, but this operations is very fast.
>
> Hope this helps,
>     Alex
>
>
>
>
>
>
>
> From: qt-interest-bounces at trolltech.com [mailto:
> qt-interest-bounces at trolltech.com] On Behalf Of O Caldas
> Sent: Thursday, July 02, 2009 4:33 PM
> To: qt-interest at trolltech.com
> Subject: Re: [Qt-interest] Problem drawning in the GUI Thread with Data
> from another Thread
>
> oh, and here is the code of the paintEvent() method:
>
> void PopGraph::paintEvent(QPaintEvent*){
>    QPainter painter2(this);
>    painter2.drawImage(QPoint(0,0), *buffer);
>
> }
>
> buffer is an atribute QImage* of the class
> 2009/7/2 O Caldas <caldaz.sheep at gmail.com>
> hi, my application draws a horizontal graphics of the data generated by the
> thread. it uses vectors that are directly modified by the worker thread.
> ive
> tryed to send the vectors in the signal but it stays the same.
>
> here is the code that create the image that will be draw :
>
> void PopGraph::graphUpdate(){
>    delete(buffer);
>    buffer = new QImage(size(), QImage::Format_ARGB32);
>    QSize d = size();
>    long long nMax = (int)ceil(log10(_d->getPopulationMax()));
>    double yscale = d.height()/(double)nMax;
>    int tickscale = 1;
>
>    // draw horizontal tick marks
>    Qt::PenStyle style = Qt::PenStyle(Qt::SolidPattern);
>    Qt::PenCapStyle cap = Qt::PenCapStyle(Qt::FlatCap);
>    Qt::PenJoinStyle join = Qt::PenJoinStyle(Qt::MiterJoin);
>    QPainter painter(buffer);
>    painter.fillRect(rect(), Qt::white);
>
>    painter.setPen(QPen(Qt::black, 1, style ,cap,join));
>    for (int i=0; i<=nMax; i++) {
>        int y = size().height()-(int)(i*yscale);
>        painter.drawLine(0, y, d.width(), y);
>        char st[6] = "10^";
>        strcat(st, intToStr(i));
>        painter.drawText(0, y, QString(st));//("10^" + String.valueOf(i), 0,
> y);
>    }
>    // draw vertical (date) tick marks
>    long long lastday = -1;
>    vector<long long> hours = _d->getPopulationHours();
>    int end = d.width();
>    if (hours.size()<d.width())
>        end = hours.size();
>    for (int i=0; i<end; i++) {
>        if (lastday != hours[hours.size()-i-1]/24) {
>            lastday = hours[hours.size()-i-1]/24;
>            painter.drawLine(d.width()-i, 0, d.width()-i, d.height());
>            painter.drawText(d.width()-i+1, 11, QString(
> intToStr(lastday+1)));
>        }
>    }
>    // draw antigen level curves
>    vector<Antigen*>* pops = _d->getAntigens();
>    vector<QColor> popcolors = _d->getAntigenColors();
>    int s = _d->getAntigenLevels().size();
>
>    for (int j=0; j<s; j++) {
>        painter.setPen(popcolors[j]);
>        // draw legend
>        painter.drawText(0,
> painter.fontMetrics().ascent()*(j+1),QString(pops->at(j)->getName()->data()));
>
>        // draw curves
>        vector< long long > data = _d->getAntigenLevels()[j];
>        end = d.width();
>        if (data.size()<(unsigned )d.width())
>            end = data.size();
>        for (int i=0; i<end; i+=2)  // just plot every other hour
>            if (data[data.size()-i-1]>0){
>
>                painter.drawRect(d.width()-i-1,
>                        d.height()-1-(int)
>                        (log10(data[data.size()-i-1])*yscale),
>                        2,
>                        2);
>            }
>    }
>    // draw T cell level curves
>    s = _d->getTCellColors().size();
>    for (int j=0; j<s; j++) {
>        painter.setPen(_d->getTCellColors()[j]);
>        // draw legend
>        if (_d->getTCells()->size()<10)
>            painter.drawText(0,
> painter.fontMetrics().ascent()*(j+1+(_d->getAntigens()->size())),
> QString(_d->getTCells()->at(j)->getName()->data()));
>        // draw curves
>        vector<long long> data = _d->getTCellLevels()[j];
>        end = d.width();
>        if (data.size()<(unsigned )d.width()) end = data.size();
>        for (int i=0; i<end-1; i++){
>            if ((data[data.size()-i-1]>0) && (data[data.size()-i-2]>0)){
>                painter.drawLine(d.width()-i-1,
>                        d.height()-(int)
>                        (log10(data[data.size()-i-2])*yscale),
>                        d.width()-i,
>                        d.height()-(int)
>                        (log10(data[data.size()-i-1])*yscale));
>
>            }
>        }
>
>    }
> //    if(contador == 1){
> //        contador =0;
>        update();
>
> //    }
>
> }
>
> thanks for your help!
> 2009/7/2 Sean Harmer <sean.harmer at maps-technology.com>
>
> On Thursday 02 Jul 2009 06:27:05 O Caldas wrote:
> > Hi, im working on a project where I have two threads, one Worker thread,
> > that do some calculations,
> > and one GUI Thread, that draw some graphics in a QWidget.
> >
> > The Worker thread is a class that inherits from QThread, and the GUI
> Thread
> > is the main thread obviously.
> >
> > Im geting the worker thread to send a signal every end of calculation
> step,
> > and connecting this signal
> > to the method that draws the graphic in the GUI Thread
> >
> > like this:
> >
> > connect(calculator, SIGNAL(calculated(),this,
> >             SLOT(updateView()));
> >
> > The problem is, when the calculation gets to fast, the GUI thread just
> bugs
> > and the program terminates.
> > It seems that the calculator thread starts sending too much signals and
> the
> > GUI thread cant handle it,
> > or something like this.
> >
> > i've tryed to use Qt::BlockingQueuedConnection but it is too slow.
> >
> > if someone knows what im doing wrong, or the right way to build a program
> > like that please help!
> It sounds like you are taking the right general approach. What does your
> app
> have to do in order to visualise the results? How do you get the data to
> the
> main thread as I notice your signal does not marshall any data across to
> it?
>
> If the visualisation in the main thread really is very expensive to perform
> then maybe you should only visualise every n'th frame. You could maybe make
> this an option that the user can set depending upon the performance of
> their
> graphics subsystem.
>
> Sounds like you have identified the bottle neck in your app. If you provide
> some more information we might be able to help you improve it.
>
> Cheers,
>
> Sean
>
> _______________________________________________
> Qt-interest mailing list
> Qt-interest at trolltech.com
> http://lists.trolltech.com/mailman/listinfo/qt-interest
>
>
>
> --
> Daniel Mendes Caldas
>
>
>
> --
> Daniel Mendes Caldas
>
>
>
> ---------------------------------------------------------------------------------------------------
> Weidlinger Associates, Inc. made the following annotations.
>
> "This message and any attachments are solely for the intended recipient and
> may contain confidential or privileged information. If you are not the
> intended recipient, any disclosure, copying, use, or distribution of the
> information included in this message and any attachments is prohibited. If
> you have received this communication in error, please notify us by reply
> e-mail and immediately and permanently delete this message and any
> attachments. Thank you."
>
> "Please consider our environment before printing this email."
>
> _______________________________________________
> Qt-interest mailing list
> Qt-interest at trolltech.com
> http://lists.trolltech.com/mailman/listinfo/qt-interest
>



-- 
Daniel Mendes Caldas
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.qt-project.org/pipermail/qt-interest-old/attachments/20090702/01bb718c/attachment.html 


More information about the Qt-interest-old mailing list