Results 1 to 14 of 14

Thread: real time data display

  1. #1
    Join Date
    Jan 2009
    Posts
    4
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default real time data display

    Hello, I need to write an application that accepts a stream of data and display it on a graph in real time. I want to be able to append the new data to be displayed with the data already displayed, and when the graph reaches the end of the screen it wraps around, sort of like a rolling graph. The question is, is there a way to paint only the new data, without repainting everything? I want this to be pretty fast. What kind of facility should I use? I mean, QPainter and paintEvent in the QWidgets seemed like the right thing to use, but paintevent seems to clear the window before it draws, and I really need to avoid drawing everything every time.
    Thanks for the help.

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Thanks
    28
    Thanked 975 Times in 912 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: real time data display

    Take a look at QWidget::setAttribute(). Esp. the Qt::WA_NoSystemBackground and Qt::WA_OpaquePaintEvent attributes.

    You could paint everything on a pixmap and then just shift it and draw new stuff on exposed area. You can check out how Qwt does it.

  3. #3
    Join Date
    Aug 2009
    Posts
    10
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: real time data display

    i have the same problem of hammer256. do you resolve your problem?? can you help me please? thanks in advance!

  4. #4
    Join Date
    Jan 2009
    Posts
    4
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: real time data display

    Hey, I did solve my problem. I don't know if it's the right way to do it, but it's fast (especially with qt 4.5) and does what I want.

    Basically the idea is that the display widget has a back buffer (I use QPixmap) in which all my graph updates gets drawn on. In the function which actually generates the data and draws the data, I have a QPainter that draws to that back buffer. The paintEvent function for the display widget simply copies what's on the back buffer to the screen, but only for the area specified in the "event" parameter passed to it. So every time new data is generated, I call the Qpainter to draw on the back buffer, then, I call update on the display widget and pass a QRect parameter to it that specifies the area I want to update on, and I'm done.

    I don't have access to my code right now, (a little busy also) but if you need I can show you the code later.

  5. #5
    Join Date
    Aug 2009
    Posts
    10
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: real time data display

    thank you for the reply. it would be great if you can show me the code. i have no hurry. thank you a lot .hope the code will help me more.

  6. #6
    Join Date
    Jan 2009
    Posts
    4
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: real time data display

    This is the header file for my display widget. The backBuf and paintEvent are the ones to note here. I use a pointer for the backBuf so I can decide later what the size should be.
    Qt Code:
    1. #ifndef SIMDISPW_H
    2. #define SIMDISPW_H
    3.  
    4. #include <QtGui/QWidget>
    5. #include <QtGui/QPainter>
    6. #include <QtGui/QPaintEvent>
    7. #include <QtGui/QColor>
    8. #include <QtGui/QPixMap>
    9. #include <QtCore/QMutex>
    10. #include "ui_simdispw.h"
    11. #include "common.h"
    12. #include "globalvars.h"
    13.  
    14. //widget class to display realtime data generated by the simulator
    15. class SimDispW : public QWidget
    16. {
    17. Q_OBJECT //ignore
    18.  
    19. public:
    20. SimDispW(QWidget *parent = 0);
    21. ~SimDispW();
    22. //returns the pixmap buffer that should be drawn on
    23. QPixmap *getBackBuf();
    24.  
    25. private:
    26. Ui::SimDispWClass ui; //autogenerated by ui_simdispw.h, ignore
    27. QPixmap *backBuf; //the pixmap buffer that the widget updates from
    28.  
    29. protected:
    30. void paintEvent(QPaintEvent *); //custom paint event that paints the window
    31. };
    32.  
    33. #endif // SIMDISPW_H
    To copy to clipboard, switch view to plain text mode 

    the source file for the display widget. I have some threading stuff in there because my data generation function is in a different thread, so you can ignore it if you want.

    Qt Code:
    1. #include "../includes/simdispw.h"
    2. #include "../includes/moc_simdispw.h"
    3.  
    4. SimDispW::SimDispW(QWidget *parent)
    5. : QWidget(parent)
    6. {
    7. ui.setupUi(this);
    8. this->setAttribute(Qt::WA_DeleteOnClose); //when the window is closed, delete the object
    9. this->setFixedSize(2000, NUMMF);
    10. backBuf=new QPixmap(this->width(), this->height());
    11. backBuf->fill(QColor(0,0,0)); //sets the whole thing to black
    12.  
    13. }
    14.  
    15. SimDispW::~SimDispW()
    16. {
    17. delete backBuf;
    18. }
    19.  
    20. QPixmap *SimDispW::getBackBuf()
    21. {
    22. return backBuf;
    23. }
    24.  
    25.  
    26. void SimDispW::paintEvent(QPaintEvent * event)
    27. {
    28. QPainter p(this);
    29. p.setViewTransformEnabled(true);
    30. p.setWindow(0, 0, backBuf->width(), backBuf->height());
    31. p.setViewport(0, 0, this->width(), this->height());
    32. //p.setWorldMatrixEnabled(false);
    33.  
    34. bufLock.lock(); //for thread management, locks buffer mutex
    35. p.drawPixmap(event->rect(), *backBuf, event->rect());
    36. //cout<<event->rect().x()<<" "<<event->rect().y()<<" "<<event->rect().width()<<" "<<event->rect().height()<<endl;
    37. //p.drawPixmap(0,0, *backBuf);
    38. bufLock.unlock(); //unlocks when done
    39. }
    To copy to clipboard, switch view to plain text mode 

    And here is the data generation function.
    Qt Code:
    1. /*
    2.  * simthread.cpp
    3.  *
    4.  * Created on: Feb 16, 2009
    5.  * Author: wen
    6.  */
    7.  
    8. #include "../includes/simthread.h"
    9. #ifdef INTELCC
    10. #include <omp.h>
    11. #endif
    12.  
    13. SimThread::SimThread(QObject *parent, SimDispW *panel)
    14. :QThread(parent)
    15. {
    16. dispW=panel;
    17. }
    18.  
    19.  
    20. void SimThread::run()
    21. {
    22. if(dispW==NULL || !initialized)
    23. {
    24. return;
    25. }
    26. simLoop();
    27. }
    28.  
    29. void SimThread::simLoop()
    30. {
    31. QPixmap *buf;
    32. CRandomSFMT0 randGen(time(NULL));
    33. int trialTime;
    34.  
    35. bool *mfsAP=new bool[NUMMF];
    36. bool *granulesAP=new bool[NUMMF];
    37. bool *golgisAP=new bool[NUMMF];
    38.  
    39. if(dispW==NULL)
    40. {
    41. return;
    42. }
    43. buf=dispW->getBackBuf();
    44. if(buf==NULL)
    45. {
    46. return;
    47. }
    48.  
    49. while(true)
    50. {
    51. simStopLock.lock();
    52. if(simStop)
    53. {
    54. simStopLock.unlock();
    55. break;
    56. }
    57. simStopLock.unlock();
    58.  
    59. trialTime=time(NULL);
    60. for(int i=0; i<NUMMF; i++)
    61. {
    62. if(mossyFibers[i].getMFType()==MossyFiber::activeCS+1 || mossyFibers[i].getMFType()==MossyFiber::activeCS+5)
    63. {
    64. mossyFibers[i].setCSOn(1);
    65. }
    66. else
    67. {
    68. mossyFibers[i].setCSOn(0);
    69. }
    70. }
    71.  
    72. bufLock.lock();
    73. buf->fill(Qt::black);
    74. bufLock.unlock();
    75. dispW->update();
    76.  
    77. for(int i=0; i<TRIALTIME; i++)
    78. {
    79. bool tempAP;
    80. bool *drawAP;
    81.  
    82. simStopLock.lock();
    83. if(simStop)
    84. {
    85. simStopLock.unlock();
    86. break;
    87. }
    88. simStopLock.unlock();
    89.  
    90. simPauseLock.lock();
    91.  
    92. for(int j=0; j<NUMMF; j++)
    93. {
    94. //mossyFibers[j].setThresh(mossyFibers[j].getThresh()+(1-mossyFibers[j].getThresh())*MossyFiber::threshDecay);
    95.  
    96. // mfsSpike[j]=randGen.fRandom()<((int)(mossyFibers[j].getCSOn() && i>=mossyFibers[j].getCSStart() && i<mossyFibers[j].getCSEnd())*mossyFibers[j].getIncFreq()+mossyFibers[j].getbgFreqCont(MossyFiber::activeContext))*mossyFibers[j].getThresh();
    97. //
    98. // if(mfsSpike[j])
    99. // {
    100. // mossyFibers[j].setThresh(0);
    101. //
    102. // {
    103. // for(int k=0; k<mossyFibers[j].getNumSynGR(); k++)
    104. // {
    105. // granuleCells[mossyFibers[j].getConGRInd(k)].setExI(mossyFibers[j].getConGRDen(k),mfsSpike[j]);
    106. // }
    107. // }
    108. // }
    109. mfsAP[j]=mossyFibers[j].calcActivity(i, randGen);
    110. }
    111.  
    112. #ifdef INTELCC
    113. #pragma omp parallel shared(granuleCells, golgiCells)
    114. #endif
    115. {
    116. #ifdef INTELCC
    117. #pragma omp for schedule(static, NUMGR/16) nowait
    118. #endif
    119. for(int j=0; j<NUMGR; j++)
    120. {
    121. tempAP=granuleCells[j].calcActivity();
    122. if(j<NUMMF)
    123. {
    124. granulesAP[j]=tempAP;
    125. }
    126. }
    127. #ifdef INTELCC
    128. #pragma omp for schedule(static, NUMGO/16) nowait
    129. #endif
    130. for(int j=0; j<NUMGO; j++)
    131. {
    132. golgisAP[j]=golgiCells[j].calcActivity();
    133. }
    134. }
    135.  
    136. simDispTypeLock.lock();
    137. if(simDispType==0)
    138. {
    139. drawAP=mfsAP;
    140. }
    141. else if(simDispType==1)
    142. {
    143. drawAP=granulesAP;
    144. }
    145. else
    146. {
    147. drawAP=golgisAP;
    148. }
    149. simDispTypeLock.unlock();
    150.  
    151. bufLock.lock();
    152. p.begin(buf);
    153. p.setWindow(0,0, TRIALTIME, NUMMF);
    154. p.setViewport(0, 0, buf->width(), buf->height());
    155.  
    156. p.setPen(Qt::white);
    157. for(int j=0; j<NUMMF; j++)
    158. {
    159. if(drawAP[j])
    160. {
    161. p.drawPoint(i, j);
    162. }
    163. }
    164.  
    165. if(i>=MossyFiber::csOnset[MossyFiber::activeCS] && i<MossyFiber::csOnset[MossyFiber::activeCS]+MossyFiber::csDuration[MossyFiber::activeCS])
    166. {
    167. p.setPen(Qt::blue);
    168. }
    169. else
    170. {
    171. p.setPen(Qt::black);
    172. }
    173. for(int j=0; j<NUMMF; j++)
    174. {
    175. if(!drawAP[j])
    176. {
    177. p.drawPoint(i, j);
    178. }
    179. }
    180. p.scale((float)buf->width()/5000, (float)buf->height()/NUMMF);
    181.  
    182. QRect updateArea(p.worldTransform().mapRect(QRect(i, 0, 1, NUMMF)));
    183. if(updateArea.width()<1)
    184. {
    185. updateArea.setWidth(1);
    186. }
    187. p.end();
    188. bufLock.unlock();
    189.  
    190. dispW->update(updateArea);
    191.  
    192. simPauseLock.unlock();
    193. }
    194.  
    195. cout<<"trial run time: "<<time(NULL)-trialTime<<endl;
    196. }
    197.  
    198. // for(int i=0; i<NUMMF; i++)
    199. // {
    200. // delete &mfsAP[i];
    201. // delete &granulesAP[i];
    202. // delete &golgisAP[i];
    203. // }
    204. delete mfsAP;
    205. delete granulesAP;
    206. delete golgisAP;
    207. }
    To copy to clipboard, switch view to plain text mode 

    the really relevant part of that function is the following:
    Qt Code:
    1. bufLock.lock();
    2. p.begin(buf);
    3. p.setWindow(0,0, TRIALTIME, NUMMF);
    4. p.setViewport(0, 0, buf->width(), buf->height());
    5.  
    6. p.setPen(Qt::white);
    7. for(int j=0; j<NUMMF; j++)
    8. {
    9. if(drawAP[j])
    10. {
    11. p.drawPoint(i, j);
    12. }
    13. }
    14.  
    15. if(i>=MossyFiber::csOnset[MossyFiber::activeCS] && i<MossyFiber::csOnset[MossyFiber::activeCS]+MossyFiber::csDuration[MossyFiber::activeCS])
    16. {
    17. p.setPen(Qt::blue);
    18. }
    19. else
    20. {
    21. p.setPen(Qt::black);
    22. }
    23. for(int j=0; j<NUMMF; j++)
    24. {
    25. if(!drawAP[j])
    26. {
    27. p.drawPoint(i, j);
    28. }
    29. }
    30. p.scale((float)buf->width()/5000, (float)buf->height()/NUMMF);
    31.  
    32. QRect updateArea(p.worldTransform().mapRect(QRect(i, 0, 1, NUMMF)));
    33. if(updateArea.width()<1)
    34. {
    35. updateArea.setWidth(1);
    36. }
    37. p.end();
    38. bufLock.unlock();
    39.  
    40. dispW->update(updateArea);
    41.  
    42. simPauseLock.unlock();
    To copy to clipboard, switch view to plain text mode 

    I do some scaling coordinate transform stuff with the display, but you can ignore that if you don't need it. The code is a bit long and has a lot of irrelevant stuff in there for you, so feel free to ask if something doesn't make sense.

  7. #7
    Join Date
    Aug 2009
    Posts
    10
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: real time data display

    thanks a lot. i will take a look on it now. if i have question i won't renounce to ask
    Last edited by agostain; 11th August 2009 at 15:47.

  8. #8
    Join Date
    Aug 2009
    Posts
    10
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: real time data display

    what's the meaning of TRIALTIME and NUMMF ? do you write on x-axis from 0 to TRIALTIME ?

  9. #9
    Join Date
    Aug 2009
    Posts
    10
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: real time data display

    QWidget: Cannot create a QWidget when no GUI is being used

    i used your simDisp class and then i implemet my own thread.

    i got this error. do you know what's the problem?

  10. #10
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,364
    Thanks
    3
    Thanked 5,013 Times in 4,791 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: real time data display

    Just a side note - this code is not safe as it references a pixmap from a worker thread. It will probably fail sooner or later, especially on X11 systems.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  11. #11
    Join Date
    Jan 2013
    Posts
    21
    Thanks
    8
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: real time data display

    Hi, wysota
    I had met the same problems as hammer256. I am working on Windows XP. I have some questions.
    1. Why is it not safe to reference pixmap from worker thread? Would this cause big porblems on Windows.
    2. Please give me some advice if you have better solution.

  12. #12
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,364
    Thanks
    3
    Thanked 5,013 Times in 4,791 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: real time data display

    Quote Originally Posted by honestapple View Post
    1. Why is it not safe to reference pixmap from worker thread?
    Because QPixmap could potentially access GUI data.

    Would this cause big porblems on Windows.
    It might crash your app.

    2. Please give me some advice if you have better solution.
    Use a shared QImage instance and generate a pixmap from it in the main thread.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  13. #13
    Join Date
    Jan 2013
    Posts
    21
    Thanks
    8
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: real time data display

    I knew that there was a pwt library which is used to plot. Which is better between the pwt library and the solution you advised?

  14. #14
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,364
    Thanks
    3
    Thanked 5,013 Times in 4,791 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: real time data display

    I don't know what pwt is. I only know Qwt and it is hard to compare a home crafted solution with a library that has been on the market for years.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  15. The following user says thank you to wysota for this useful post:

    honestapple (25th March 2013)

Similar Threads

  1. Best way to display lots of data fast
    By New2QT in forum Newbie
    Replies: 4
    Last Post: 16th October 2008, 23:46
  2. Replies: 2
    Last Post: 29th September 2008, 01:08
  3. Display the camera frame in real time
    By alex_lue in forum Qt Programming
    Replies: 8
    Last Post: 27th July 2007, 11:31
  4. First attempt to display serial port data on GUI
    By ShaChris23 in forum Newbie
    Replies: 12
    Last Post: 4th May 2007, 10:14
  5. Displaying real time images
    By Sheetal in forum Qt Programming
    Replies: 9
    Last Post: 22nd February 2007, 12:29

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.