Drawing data on Qwidget



  • Hi,

    i am new to Qt. i want to draw some points on a frame it could be Qwidget or preferably Qcanvas.
    i have never used Qt before. any kind of suggestions will be appreciated regarding where to start
    thanks



  • use QPainter ;
    @
    //example of a rectangle !!
    painter.drawRect(30,50,700,980);

    //example of a Text ;
    painter.drawText(QRectF(650,75,100,75),"Hello Qt");

    //example of a Line ;
    painter.drawLine(QLine(365,190,365,490));
    @



  • i am using Qpainter in this way which yield nothing on the widget...

    @
    void paintEvent(QPaintEvent *event)
    {
    Qpainter painter(this);

    for (int x=0; x< 100; x++){
    for (int y=0; y< 100; y++)
    {
    pinter.drawpoint(x,y);
    }
    }
    @

    it doesnt draw anything on widget and also the application get crashed after some seconds....
    i dont know what i am doing wrong....

    [EDIT: code formatting, please wrap in @-tags, Volker]



  • btw thanks for replying.....



  • Your code generates a rectangular shape and it works. Check if you are subclassing QWidget if your are trying to paint a QWidget.

    For more examples regardiing painting you can refer "here":http://www.voidrealms.com/viewtutorial.aspx?id=35 you can also check other tutorials related to painting. "Basic drawing":http://qt-project.org/doc/qt-4.8/painting-basicdrawing.html
    This/your code works

    @void Widget::paintEvent(QPaintEvent *event)
    {
    QPainter painter(this);

    for (int x=0; x< 100; x++){
    
        for (int y=0; y< 100; y++)
        {
            painter.drawPoint(x,y);
        }
    }
    

    }@



  • ok thanks..That helps much but let me be more specific about the problem i am working on.
    i want to display a 2d map in any kind of widget dont care but it should be real time.
    i am getting some data which dimensions is 4000 x 4000 pixels. and i got some occupancy values that is 0,100 and -1. 0 for unoccupied, 100 for occupied and -1 for unexplored.
    so these values are getting updated after every 4 seconds and comes new data.
    what i thought that solution would be as below. i check the data and see if it is 0,100 or -1 and change the color of pen and drawing point at that pixel so in that way at the end i should get the map.

    unfortunately it is very slow and doesnt update itself very quickly. secondly on my screen i dont know how to make the frame of 4000x4000 pixels size. since it gets away from my screen so i cant see whether i am getting some other color except that occupied one.

    Any kind of help or pointers will be appreciated. if anyone suggest some other way to solve it would be welcome too. Thanks

    @@void MainWindow::paintEvent(QPaintEvent *e)
    {
    QPainter painter(this);
    QPen pen1(Qt::black);
    QPen pen2(Qt::blue);
    QPen pen3(Qt::red);
    for(unsigned int y = 0; y < 4000; y++) {

        for(unsigned int x = 0; x < 4000; x++) {
    
          unsigned int i = x + (4000 - y - 1) * 4000;
    

    if (mg1.data11[i] == 0) {

     painter.setPen(pen1);
    

    }
    else if (mg1.data11[i] == 100) {

    painter.setPen(pen2);
    }
    else {
    painter.setPen(pen3);
    }
    //Actual painting
    painter.drawPoint(x,y);
    }
    }
    }@@



  • I notice that your class name is MainWindow, does it subclass of QMainWindow.

    If so your will fail to see the things drawn on it, as there will be some other things on top of it. such as QToolBar, QStatusBar, CentralWidget, DockWidgets, ...



  • Well of course it's slow, you're looping through 16 million pixels on every single paint event, what do you expect?
    Where does this data come from? Even assuming just 16 bit integers, that's 30 MiB every 4 seconds. Are you loading this from disk?

    Here are my suggestions:

    • Reduce the data that needs to be updated in a smart way. Don't always draw all 16 million pixels, but find an algorithm that just repaints the areas that have changed (have a look at the theory behind quadtrees)
    • Don't use QPainter but create a QImage and write directly to its memory in low-level code, see QImage::scanLine. Then blit the image to the screen in paint events.
    • Dive into programming your GPU with shader programs and let the GPU do the work, not the CPU.

    About your screen size problem: Yeah I'd have problems displaying a 4000*4000 pixel matrix, too ;). That's why scrollbars were invented.



  • Thanks. i am getting this data from my robot which explores the world through laser scanner and gives values which later on computed through particle filtering to generate the occupancy grid values. . i am reading on the topics as u suggested but mean time further information on it will be much appreciated. btw i want to get something like this at the end on my GUI. "The image":http://www.google.se/imgres?um=1&hl=sv&sa=N&biw=1272&bih=635&tbm=isch&tbnid=SF38TvU5fLM8mM:&imgrefurl=http://www.cs.bilkent.edu.tr/~culha/ee780/&docid=3yKvannqzefFRM&imgurl=http://www.cs.bilkent.edu.tr/~culha/ee780/21.JPG&w=339&h=339&ei=ObTET4TLMobV4QT8iLWHCg&zoom=1&iact=hc&vpx=863&vpy=4&dur=3501&hovh=225&hovw=225&tx=98&ty=92&sig=105272935870739764116&page=3&tbnh=143&tbnw=143&start=39&ndsp=22&ved=1t:429,r:4,s:39,i:165
    !
    [quote author="DerManu" date="1338256880"]Well of course it's slow, you're looping through 16 million pixels on every single paint event, what do you expect?
    Where does this data come from? Even assuming just 16 bit integers, that's 30 MiB every 4 seconds. Are you loading this from disk?

    Here are my suggestions:

    • Reduce the data that needs to be updated in a smart way. Don't always draw all 16 million pixels, but find an algorithm that just repaints the areas that have changed (have a look at the theory behind quadtrees)
    • Don't use QPainter but create a QImage and write directly to its memory in low-level code, see QImage::scanLine. Then blit the image to the screen in paint events.
    • Dive into programming your GPU with shader programs and let the GPU do the work, not the CPU.

    About your screen size problem: Yeah I'd have problems displaying a 4000*4000 pixel matrix, too ;). That's why scrollbars were invented.[/quote]



  • Every time the laser scanner performs one measurement, you have four data to process: x, y (scanner position), phi (angle) and r (measured distance). This results in a single straight line starting at (x,y) with direction phi and length r, and a black dot at the end, as shown in the images. Everything else in the image stays the same. This is easily doable, also with QPainter. Just create a buffer QPixmap which is initially filled gray once. Then, at every scanner iteration, use drawLine and drawEllipse to draw the line and black dot respectively. These two operations are extremely fast, much faster than painting 16 million pixels individually.
    In the paint event of your widget, create a QPainter(this) as you did previously, and now use drawPixmap to draw the visible portion (->scrollbars) of the pixmap onto your widget surface. This, too, is very fast.

    That should solve your problem.

    Further I suggest you don't fix your coordinate system to 40004000 but adjust its size dynamically. What would you do when the area the scanner sees is very narrow but longer than 4000 pixels? Or why waste so much memory when the area it sees in one run is maybe just 500500?


Log in to reply
 

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