Results 1 to 15 of 15

Thread: paint in the viewport of a scrollarea

  1. #1
    Join Date
    Nov 2007
    Location
    Italy
    Posts
    691
    Thanks
    59
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default paint in the viewport of a scrollarea

    Hi to all,
    I attached a QWidget to a scrollarea. The widget is scrolled automatically and I draw a text on the position 20, 20.
    The problem is that when the widget is scrolled the text disappear. I draw the text in the paint event so:

    Qt Code:
    1. void WaveDisplay::paintEvent( QPaintEvent* pe )
    2. {
    3. if( m_waveCachePixmap.isNull() )
    4. {
    5. updateWave();
    6. }
    7.  
    8. QPainter p( this );
    9. p.setRenderHint( QPainter::Antialiasing, true );
    10. QPen pen = QPen( Qt::darkRed, 1 );
    11.  
    12. // wave
    13. p.drawPixmap( 0, 0, m_waveCachePixmap );
    14.  
    15. // timeline
    16. pen.setColor(Qt::darkRed);
    17. pen.setStyle(Qt::SolidLine);
    18. p.setPen( pen );
    19. p.drawLine( m_CurrentTimePosition, 0, m_CurrentTimePosition, height() );
    20.  
    21. // elapsed time
    22. QWidget* widget = area->viewport(); //HOW CAN I USE THE VIEW PORT
    23. setElapsedTime( m_CurrentSoundPosition );
    24. QFont font = p.font();
    25. font.setPointSize( 24 );
    26. p.setFont( font );
    27. p.drawText( QPoint(20, 20), m_elapsedTimeString ); //THE TEXT DISAPPEAR
    28.  
    29. QWidget::paintEvent(pe);
    30. }
    To copy to clipboard, switch view to plain text mode 

    I read about the viewport but I don't know how use it for my purpose.
    I would always draw at a position of the viewport of my scrollarea.

    regards
    Franco Amato

  2. #2
    Join Date
    Oct 2006
    Location
    New Delhi, India
    Posts
    2,467
    Thanks
    8
    Thanked 334 Times in 317 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: paint in the viewport of a scrollarea

    I guess WaveDisplay is the widget you are adding to the scroll area. To draw on the scroll area, you will need to override the paint event of the scroll area, not the widget.

    If your text had been constant, you could have used some image as background. But in your case it seems more proper to override paintevent of scroll area.Something like -
    Qt Code:
    1. ScrollArea::paintEvent(*event)
    2. {
    3. QScrollArea::paintEvent(event); // call the base class first.
    4. QPainter painter(this);
    5. painter.drawText(..); // draw your text.
    6. }
    To copy to clipboard, switch view to plain text mode 

  3. #3
    Join Date
    Nov 2007
    Location
    Italy
    Posts
    691
    Thanks
    59
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: paint in the viewport of a scrollarea

    Yes WaveDisplay is the widget I attached to a scrollarea so:

    Qt Code:
    1. /* scroll area */
    2. sa = new QScrollArea;
    3. sa->setWidgetResizable(true);
    4. QScrollBar* scrollBar = sa->horizontalScrollBar();
    5. scrollBar->setSliderDown( true );
    6. sa->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    7. sa->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
    8.  
    9. m_WaveDisplay = new WaveDisplay(sa, sa->viewport());
    10. m_WaveDisplay->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Ignored);
    11. sa->setWidget( m_WaveDisplay );
    To copy to clipboard, switch view to plain text mode 

    sorry but I don't inherited any class from scrollarea so how can I reimplement the paintEvent?
    Franco Amato

  4. #4
    Join Date
    Oct 2006
    Location
    New Delhi, India
    Posts
    2,467
    Thanks
    8
    Thanked 334 Times in 317 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: paint in the viewport of a scrollarea

    but I don't inherited any class from scrollarea
    You will need to ! Because you want the text to stay visible in the viewport.. if you draw it on widget, it will move with the widget when you scroll.

  5. #5
    Join Date
    Nov 2007
    Location
    Italy
    Posts
    691
    Thanks
    59
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: paint in the viewport of a scrollarea

    Quote Originally Posted by aamer4yu View Post
    You will need to ! Because you want the text to stay visible in the viewport.. if you draw it on widget, it will move with the widget when you scroll.
    I created a very simple class inherited from QScrollArea just for test:

    Qt Code:
    1. #ifndef __SCROLLAREA_H__
    2. #define __SCROLLAREA_H__
    3.  
    4. #include <QScrollArea>
    5.  
    6. class ScrollArea : public QScrollArea
    7. {
    8. public:
    9. ScrollArea( QWidget* parent = 0 );
    10. ~ScrollArea();
    11.  
    12. protected:
    13. virtual void paintEvent(QPaintEvent *);
    14.  
    15. private:
    16. };
    17. #endif //__SCROLLAREA_H__
    To copy to clipboard, switch view to plain text mode 


    and I implemented the paintEvent as you said:
    Qt Code:
    1. #include "ScrollArea.h"
    2. #include <QPainter>
    3.  
    4. ScrollArea::ScrollArea( QWidget* parent /* = 0 */ ): QScrollArea(parent)
    5. {
    6. }
    7.  
    8. ScrollArea::~ScrollArea()
    9. {
    10. }
    11.  
    12. void ScrollArea::paintEvent(QPaintEvent *event)
    13. {
    14. QScrollArea::paintEvent(event); // call the base class first.
    15. QPainter painter(this);
    16. painter.drawText(20,50, "Just a test"); // draw your text.
    17. }
    To copy to clipboard, switch view to plain text mode 

    Now I attached WaveDisplay to the ScrollArea instead of QScrollArea:
    Qt Code:
    1. /* scroll area */
    2. //sa = new QScrollArea;
    3. sa = new ScrollArea;
    4. sa->setWidgetResizable(true);
    5. QScrollBar* scrollBar = sa->horizontalScrollBar();
    6. scrollBar->setSliderDown( true );
    7. sa->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    8. sa->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
    9.  
    10. m_WaveDisplay = new WaveDisplay(sa, sa->viewport());
    11. m_WaveDisplay->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Ignored);
    12. sa->setWidget( m_WaveDisplay );
    To copy to clipboard, switch view to plain text mode 

    The paintEvent of the WaveDisplay is not changed as I draw other stuffs but I never see the "just for test" string at position 20, 50 of the viewport. I set a breakpoint in the paintEvent of the ScrollArea and seems that it never enter in such routine

    Where I'm wrong?

    Regards
    Last edited by franco.amato; 25th March 2010 at 17:08.
    Franco Amato

  6. #6
    Join Date
    Nov 2007
    Location
    Italy
    Posts
    691
    Thanks
    59
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: paint in the viewport of a scrollarea

    I think there is a simpler solution calculating the relative position of the viewport and adding the coordinates where I would write.
    Something as

    QWidget* w = area->viewport();
    int x = w->x_position() //this doesn't exists

    painter.draw(20 + x, y, "text");

    How can I implement this?

    Regards
    Franco Amato

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

    Default Re: paint in the viewport of a scrollarea

    For the last time - I suggest you switch from using QScrollArea to QAbstractScrollArea. And really - that's the final time I'm suggesting it to you. If you still fail to realize you should do it, go back, read every response of mine to each of your posts on the wave widget and try to understand why I'm continuously and consistantly suggesting it. Let me stress this one more time - holding to the idea of having the "wavewidget" as a widget brings more and more complications to your code all of which could have been solved by using QAbstractScrollArea instead of QScrollArea and making an abstract mechanism of rendering a sound wave to any available painter with arbitrary size/resolution.
    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.


  8. #8
    Join Date
    Nov 2007
    Location
    Italy
    Posts
    691
    Thanks
    59
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: paint in the viewport of a scrollarea

    Quote Originally Posted by wysota View Post
    For the last time - I suggest you switch from using QScrollArea to QAbstractScrollArea. And really - that's the final time I'm suggesting it to you. If you still fail to realize you should do it, go back, read every response of mine to each of your posts on the wave widget and try to understand why I'm continuously and consistantly suggesting it. Let me stress this one more time - holding to the idea of having the "wavewidget" as a widget brings more and more complications to your code all of which could have been solved by using QAbstractScrollArea instead of QScrollArea and making an abstract mechanism of rendering a sound wave to any available painter with arbitrary size/resolution.
    My WaveWidget works perfectly also with arbitrary size/resolution.
    My only problem is to keep a text visible in the viewport nothing more. Yes it's right you suggested lots of time to use QAbstractScrollArea but without writing 1 line of code as example. Remember that I'm not at your level.

    Regards,
    Franco
    Franco Amato

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

    Default Re: paint in the viewport of a scrollarea

    Quote Originally Posted by franco.amato View Post
    My WaveWidget works perfectly also with arbitrary size/resolution.
    I didn't say it doesn't. I say the problem is it is a widget.

    My only problem is to keep a text visible in the viewport nothing more.
    This is your problem now. In a week you will have another one.
    Yes it's right you suggested lots of time to use QAbstractScrollArea but without writing 1 line of code as example.
    First take a look at the examples and demos that come with Qt then take a look at source code of existing QAbstractScrollArea subclasses in Qt itself and only when it is not enough, ask for clarifications.

    Remember that I'm not at your level.
    True but you are not trying to increase your level hard enough. You are afraid to make this one big step forward and dive into deep waters of unknown. If you only learn by examples you will never go beyond them. You can't stop at the first sight of an obstacle. Always aim one step further than you can actually go otherwise you will not be going forward. And he who doesn't makes a step forward, makes a step backwards.
    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.


  10. #10
    Join Date
    Nov 2007
    Location
    Italy
    Posts
    691
    Thanks
    59
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: paint in the viewport of a scrollarea

    Quote Originally Posted by wysota View Post
    I didn't say it doesn't. I say the problem is it is a widget.


    This is your problem now. In a week you will have another one.


    First take a look at the examples and demos that come with Qt then take a look at source code of existing QAbstractScrollArea subclasses in Qt itself and only when it is not enough, ask for clarifications.


    True but you are not trying to increase your level hard enough. You are afraid to make this one big step forward and dive into deep waters of unknown. If you only learn by examples you will never go beyond them. You can't stop at the first sight of an obstacle. Always aim one step further than you can actually go otherwise you will not be going forward. And he who doesn't makes a step forward, makes a step backwards.
    Principally I have a WaveWidget : QGroupBox that contains many controls:
    many buttons and a WaveDisplay as you can see in the attached image.
    The WaveDisplay is where I render the audio wave and where I would draw the text and keep it visible in the viewport.
    WaveDisplay is attached to a scroll area. I don't know which widget should I derive from QAbstractScrollArea.
    WaveWidget or WaveDisplay? In the wavedisplay the wave can shift as I implemented a zoom

    Regards
    Attached Images Attached Images
    Franco Amato

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

    Default Re: paint in the viewport of a scrollarea

    You still fail to grasp what I'm talking about, don't you? Treat your wave as a stamp you can place anywhere you want - as part of any widget or any other paintable canvas (like a printer, an image, a graphics item, whatever)

    If you then derive your "scene" from a QAbstractScrollArea, you get a canvas with a horizontal and vertical scrollbar where you can paint anything you want and this something can move right or left and up or down depending solely on the values of the scrollbars. This "anything" you can paint can be your wave stamp, text or anything else (but not a widget, hence your "wave widget" can't be a widget). Scrolling is taken care of by the scrollbars, zooming is taken care of by changing the range of the scrollbars (thus changing the size of the canvas) and painting your "scene" elements with appropriate zoom levels.

    Now if you derive from QScrollArea then basically you get a widget that contains another (main) widget that can be moved right/left and up/down. You can place other widgets on this (main) widget and manipulate their positions by using QWidget::move() or QWidget::setGeometry(). You can also paint on this widget directly by overriding its paint event. So basically you can "draw" on it in two ways - either by the widget's paint event or by placing child widgets on it and manipulating their positions. Scrolling is taken care of by the scrollbars, for zooming you have to resize the main widget, resize all the child widgets and reposition them on the main widget plus at the same time you have to cope with recalculating and redrawing everything you want drawn in the paint event of the main widget. Basically you have to deal with two mechanisms at the same time, synchronizing them and making sure they don't interfere with each other.

    Now you answer yourself which is easier and gives more space to manuver.

    I really fail to see why you made your "wave" a widget in the first place... I just see no benefit of that especially that there is no situation when you want to display it as a separate entity in a layout or a top-level window. And even if you wanted to, you still don't have to make it a widget (i.e. you could render the wave to a pixmap and set that on a QLabel). The next question is why didn't you use Graphics View to display your "scene" (the answer comes down to "because the wave thing is a widget that won't cope well with GraphicsView being zoomed").

    QAbstractScrollArea gives you soooo many more options and capabilities... You can easily scroll just your sound wave without scrolling the text or any other elements that might end up in the viewport of the scroll area. With QScrollArea you are just constantly looking for workarounds. QScrollArea was simply not meant for the thing you are trying to use it for. QAbstractScrollArea was. I could replicate your widget in a matter of minutes (without drawing the actual sound wave, of course) but then you would not learn from it, just copy it to your program and halt at the next step when you have to do something with the architecture you are not sure you understand (or you misunderstand regardless of what you think).

    There is literally one method you need to reimplement for QAbstractScrollArea and that is the paint event where you just paint what you need considering the offsets based on values of scroll bars. Just stop thinking in terms of "my sound wave has to be a widget".

    By the way - the Lazarus extension to Firefox saved my butt when writing this post. Just so that all you people know...
    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.


  12. #12
    Join Date
    Nov 2007
    Location
    Italy
    Posts
    691
    Thanks
    59
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: paint in the viewport of a scrollarea

    Quote Originally Posted by wysota View Post
    You still fail to grasp what I'm talking about, don't you? Treat your wave as a stamp you can place anywhere you want - as part of any widget or any other paintable canvas (like a printer, an image, a graphics item, whatever)

    If you then derive your "scene" from a QAbstractScrollArea, you get a canvas with a horizontal and vertical scrollbar where you can paint anything you want and this something can move right or left and up or down depending solely on the values of the scrollbars. This "anything" you can paint can be your wave stamp, text or anything else (but not a widget, hence your "wave widget" can't be a widget). Scrolling is taken care of by the scrollbars, zooming is taken care of by changing the range of the scrollbars (thus changing the size of the canvas) and painting your "scene" elements with appropriate zoom levels.

    Now if you derive from QScrollArea then basically you get a widget that contains another (main) widget that can be moved right/left and up/down. You can place other widgets on this (main) widget and manipulate their positions by using QWidget::move() or QWidget::setGeometry(). You can also paint on this widget directly by overriding its paint event. So basically you can "draw" on it in two ways - either by the widget's paint event or by placing child widgets on it and manipulating their positions. Scrolling is taken care of by the scrollbars, for zooming you have to resize the main widget, resize all the child widgets and reposition them on the main widget plus at the same time you have to cope with recalculating and redrawing everything you want drawn in the paint event of the main widget. Basically you have to deal with two mechanisms at the same time, synchronizing them and making sure they don't interfere with each other.

    Now you answer yourself which is easier and gives more space to manuver.

    I really fail to see why you made your "wave" a widget in the first place... I just see no benefit of that especially that there is no situation when you want to display it as a separate entity in a layout or a top-level window. And even if you wanted to, you still don't have to make it a widget (i.e. you could render the wave to a pixmap and set that on a QLabel). The next question is why didn't you use Graphics View to display your "scene" (the answer comes down to "because the wave thing is a widget that won't cope well with GraphicsView being zoomed").

    QAbstractScrollArea gives you soooo many more options and capabilities... You can easily scroll just your sound wave without scrolling the text or any other elements that might end up in the viewport of the scroll area. With QScrollArea you are just constantly looking for workarounds. QScrollArea was simply not meant for the thing you are trying to use it for. QAbstractScrollArea was. I could replicate your widget in a matter of minutes (without drawing the actual sound wave, of course) but then you would not learn from it, just copy it to your program and halt at the next step when you have to do something with the architecture you are not sure you understand (or you misunderstand regardless of what you think).

    There is literally one method you need to reimplement for QAbstractScrollArea and that is the paint event where you just paint what you need considering the offsets based on values of scroll bars. Just stop thinking in terms of "my sound wave has to be a widget".

    By the way - the Lazarus extension to Firefox saved my butt when writing this post. Just so that all you people know...
    Wysota please give to me some help, I don't want you write the full code for me, only give to me some hints.
    Franco Amato

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

    Default Re: paint in the viewport of a scrollarea

    Please don't quote whole posts

    Anyway... what help exactly do you want?

    Here is a simple implementation of a QAbstractScrollArea drawing a sine curve in part of the viewport and displaying the visible range of horizontal coordinates on the left and right side of the graph.

    Qt Code:
    1. #include <QtGui>
    2. #include <cmath>
    3.  
    4. class SineScroller : public QAbstractScrollArea {
    5. public:
    6. explicit SineScroller(QWidget *parent = 0) : QAbstractScrollArea(parent){
    7.  
    8. }
    9. protected:
    10. void paintEvent(QPaintEvent *pe) {
    11. QPainter p(viewport());
    12. QRect visibleRect = QRect(100, 10, viewport()->width()-200, viewport()->height()-20);
    13. p.drawRect(visibleRect);
    14. p.drawText(5, 50, QString::number(horizontalScrollBar()->value()*0.25, 'f', 2));
    15. p.drawText(viewport()->rect().right()-95, 50, QString::number((horizontalScrollBar()->value()+viewport()->width()-200)*0.25, 'f', 2));
    16.  
    17. // draw Horizontal axis
    18. int voffset = verticalScrollBar()->value();
    19. // voffset := the value of yCoord at top edge of visibleRect
    20. // we want to draw at 360
    21. if(voffset<360 && voffset+visibleRect.height() > 360) {
    22. p.save();
    23. p.setPen(Qt::red);
    24. p.drawLine(visibleRect.left(), 370-voffset, visibleRect.right(), 370-voffset);
    25. p.restore();
    26. }
    27.  
    28. // draw Sine curve
    29. double startValInDeg = horizontalScrollBar()->value()*0.25;
    30. double stopValInDeg = startValInDeg + visibleRect.width()*0.25;
    31. p.save();
    32. p.setPen(Qt::blue);
    33. p.setClipRect(visibleRect); // crude but effective
    34. p.setClipping(true);
    35. int curX = visibleRect.left();
    36. QPolygon poly;
    37. for(double valInDeg = startValInDeg; valInDeg<=stopValInDeg; valInDeg += 0.25) {
    38. double valInRad = valInDeg * M_PI / 180;
    39. double sineVal = sin(valInRad);
    40. poly << QPoint(curX++, 370-voffset-360*sineVal);
    41. }
    42. p.setRenderHint(QPainter::Antialiasing);
    43. p.drawPolyline(poly);
    44. p.restore();
    45. }
    46. void resizeEvent(QResizeEvent *re) {
    47. QAbstractScrollArea::resizeEvent(re);
    48. int visibleWidth = viewport()->width() - 200;
    49. int visibleHeight = viewport()->height() - 20;
    50. QScrollBar *h = horizontalScrollBar();
    51. QScrollBar *v = verticalScrollBar();
    52. h->setRange(0, qBound(0, 1440-visibleWidth, 1440));
    53. v->setRange(0, qBound(0, 720-visibleHeight, 720));
    54. }
    55. };
    56.  
    57.  
    58. int main(int argc, char **argv) {
    59. QApplication app(argc, argv);
    60. SineScroller scroller;
    61. scroller.show();
    62. return app.exec();
    63. }
    To copy to clipboard, switch view to plain text mode 
    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.


  14. #14
    Join Date
    Nov 2007
    Location
    Italy
    Posts
    691
    Thanks
    59
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: paint in the viewport of a scrollarea

    Thank you very much for the code. I'll try it immediately
    Franco Amato

  15. #15
    Join Date
    Nov 2007
    Location
    Italy
    Posts
    691
    Thanks
    59
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: paint in the viewport of a scrollarea

    I have a problem with paintEvent.

    I have created the class

    Qt Code:
    1. class WaveDisplay : public QAbstractScrollArea
    2. {
    3. Q_OBJECT
    4.  
    5. public:
    6. WaveDisplay( QWidget* parent = 0 );
    7. virtual ~WaveDisplay();
    8.  
    9. void closeSoundFile( QString soundName_ );
    10.  
    11. void setWave( SoundData* );
    12. void playSound(int vol_ );
    13. void stopSound();
    14.  
    15. ...code...
    16.  
    17. public slots:
    18. ...code...
    19.  
    20. private slots:
    21. void setElapsedTime( uint soundPos );
    22. void fitToWindow();
    23.  
    24. signals:
    25. void soundPositionChanged( uint );
    26. void zoomFactorChanged( float );
    27.  
    28. protected:
    29. /* paint event */
    30. virtual void paintEvent( QPaintEvent* event );
    31. ...more code...
    32.  
    33. private:
    34. void updateWave();
    35. void drawStandardPCM16(QPainter&, int);
    36. void drawStandardPCM8(QPainter&);
    37.  
    38. QPixmap m_waveCachePixmap;
    39. SoundData* m_wave;
    40. ...more code...
    41. };
    To copy to clipboard, switch view to plain text mode 

    and I mainly would implement the paintEvent.

    So I changed a bit the paintEvent of my last class
    Qt Code:
    1. /*****************************************/
    2. /* Paint event */
    3. /*****************************************/
    4. void WaveDisplay::paintEvent( QPaintEvent* pe )
    5. {
    6. QAbstractScrollArea::paintEvent( pe );
    7.  
    8. // Update the ev->rect area with the wave from the rendered QPixmap here
    9. if( m_waveCachePixmap.isNull() )
    10. {
    11. updateWave();
    12. }
    13.  
    14. QPainter p( viewport() );
    15. p.setRenderHint( QPainter::Antialiasing, true );
    16. QPen pen = QPen( Qt::darkRed, 1 );
    17.  
    18. // wave
    19. p.drawPixmap( 0, 0, m_waveCachePixmap );
    20.  
    21. // timeline
    22. pen.setColor(Qt::darkRed);
    23. pen.setStyle(Qt::SolidLine);
    24. p.setPen( pen );
    25. p.drawLine( m_CurrentTimePosition, 0, m_CurrentTimePosition, height() );
    26.  
    27. // elapsed time
    28. setElapsedTime( m_CurrentSoundPosition );
    29. QFont font = p.font();
    30. font.setPointSize( 24 );
    31. p.setFont( font );
    32. p.drawText( QPoint(20, 50), m_elapsedTimeString );
    33. }
    To copy to clipboard, switch view to plain text mode 

    and the updateWave
    Qt Code:
    1. void WaveDisplay::updateWave()
    2. {
    3. int h = this->height();
    4. int w = this->width();
    5.  
    6. // I want another width and height here.
    7. // Also, you might to clear the cache at resize events
    8. QPixmap temp = QPixmap( w, h );
    9.  
    10. QPainter p( &temp );
    11. //p.setRenderHint( QPainter::Antialiasing, true );
    12. p.fillRect( temp.rect(), bgColor );
    13.  
    14. // timeline
    15. QPen pen(Qt::black);
    16. pen.setWidthF( 1.0 );
    17. pen.setStyle(Qt::SolidLine);
    18. p.setPen(pen);
    19. p.drawLine( 0.0, 0.0, (qreal)w, 0.0 );
    20.  
    21. // Draw the waveform or load no data image
    22. if( m_wave )
    23. {
    24. pen.setColor( wfColor ); // darkCyan solid line, 1 pixels wide
    25. pen.setStyle(Qt::SolidLine);
    26. p.setPen( pen );
    27.  
    28. void* soundStream = m_wave->getSoundStream();
    29. unsigned int numSamples = m_wave->getSamples();
    30. int channels = m_wave->getChannels();
    31. FMOD_SOUND_TYPE soundType = m_wave->getSoundType();
    32. FMOD_SOUND_FORMAT soundFormat = m_wave->getSoundFormat();
    33. unsigned int dur = m_wave->getLengthMSeconds();
    34.  
    35. float* minValue = new float[channels];
    36. float* maxValue = new float[channels];
    37.  
    38. //int sampleSize = channels * ( soundFormat == PCM8 ) ? 1 : 2;
    39. int sampleSize = channels; //<-- questo concetto non funziona, io lo chiamerei step
    40.  
    41. int maxHeight = (h / 2) / channels;
    42. int increment = (h / 2);
    43.  
    44. switch( soundFormat )
    45. {
    46. case PCM8: //8 bits mono
    47. {
    48. //..to implement
    49. break;
    50. }
    51. case PCM16: //16 bits stereo (LRLRLRLR...LRLR)
    52. {
    53. drawStandardPCM16( p, 1 );
    54.  
    55. qreal samplePerPixel = m_wave->getSamples() / width();
    56. // qua disegno le tacchette temporali
    57. if(!m_timePosition.isEmpty())
    58. {
    59. pen.setColor( Qt::black );
    60. p.setPen(pen);
    61.  
    62. QList<uint>::const_iterator it;
    63. qreal widgetPos = 0;
    64.  
    65. for( it = m_timePosition.constBegin(); it != m_timePosition.constEnd(); ++it )
    66. {
    67. /* trasformo il valore temporale in valore di coordinata x del widget */
    68. widgetPos = *it / samplePerPixel;
    69. p.drawLine( widgetPos, 0, widgetPos, 10 );// from 0 to 10 for the seconds
    70. }
    71. }
    72. //markers
    73. if( !m_ListaMarcatori.isEmpty() )
    74. {
    75. pen.setColor(Qt::yellow);
    76. pen.setStyle( Qt::DashLine );
    77. p.setPen(pen);
    78. QList<uint>::const_iterator it;
    79. qreal widgetPos = 0;
    80. for(it = m_ListaMarcatori.constBegin(); it != m_ListaMarcatori.constEnd(); ++it)
    81. {
    82. /* from time value to widget value */
    83. widgetPos = *it / samplePerPixel;
    84. p.drawLine( widgetPos, 0, widgetPos, height() );
    85. }
    86. }
    87. break;
    88. }
    89. default:
    90. {
    91. qDebug("Undefined sound type");
    92. break;
    93. }
    94. }
    95. }
    96. else
    97. {
    98. p.drawImage( rect(), QImage(":/images/logo/nodata.jpg") );
    99. }
    100.  
    101. m_waveCachePixmap = temp;
    102. }
    To copy to clipboard, switch view to plain text mode 

    and finally the drawStandardPCM16

    Qt Code:
    1. /************************************************************************/
    2. /* drawStandardPCM16: spostarlo nel sounddata */
    3. /************************************************************************/
    4. void WaveDisplay::drawStandardPCM16( QPainter& painter, int numSamples )
    5. {
    6. int h = height();
    7. int w = width();
    8.  
    9. // Calculate magical constants that should be left untouched unless dealing with
    10. // other variants of PCM-Streams.
    11. int channels = m_wave->getChannels();
    12. int bits = m_wave->getBits();
    13. int pcm_length = m_wave->getPcmLength();
    14. int freq = m_wave->getFrequency();
    15.  
    16. int sample_size = channels * bits / 8;
    17.  
    18. int samples = pcm_length / sample_size; //pcm_length bytes totali del sound
    19. int maxHeight = (h / 2) / channels;
    20. int increment = (h / 2);
    21. float modifier = (float)maxHeight / 0x0000FFFF * 2;
    22. int* minValues = new int[channels];
    23. int* maxValues = new int[channels];
    24.  
    25. //Adjust these values to obtain a different drawing scheme. Offset defines the initial sample
    26. //where to begin drawing (it takes into account channel, sample size, bit size etc). maxSamplesOnscreen
    27. //defines the amount of samples displayed on the screen.
    28. int startOffset = 0;
    29. int maxSamplesOnscreen = samples;
    30.  
    31. // Calculate the starting position in the stream where start fetching our data. And calculate
    32. // the width between samples. By default the width truncated to the nearest integer for drawing.
    33. // Note: doubles are needed for this calculation due floating point in-precision. Floating point
    34. // operations have the same speed either so it's quite valid.
    35. char* stream = (char*)m_wave->getSoundStream() + (startOffset * sample_size);
    36. double samplesInc = 1.0f / ( maxSamplesOnscreen / (double)w);
    37. double samplesCur = 0.0f;
    38.  
    39. //Correct the maximum samples displayed on the screen, if this step is not done we'ld be
    40. //drawing outside the boundaries of the data stream.
    41. maxSamplesOnscreen = (samples - startOffset) > maxSamplesOnscreen ? maxSamplesOnscreen : (samples - startOffset);
    42.  
    43. "Creating waveform...",
    44. "Abort process",
    45. 0,
    46. maxSamplesOnscreen,
    47. this);
    48.  
    49. if( !m_soundLoaded )
    50. progress->setWindowModality( Qt::WindowModal );
    51.  
    52. //Iterate over each sample that lies withing the lower and upper boundaries that we precomputed. For
    53. //every sample we draw the maximum value, and minimum value. Store the value in a temp. array and process that
    54. //array once we detect our x is changed.
    55. for( int i = startOffset, maxI = i + maxSamplesOnscreen, oldX = 0, x = 0; i < maxI; i++, stream += sample_size, samplesCur += samplesInc, x = samplesCur)
    56. {
    57. if( i % (60 * freq) == 0 ) //ogni minuto
    58. {
    59. // aggiungo un marcatore del tempo alla lista
    60. //m_timePosition.append(i);// qua dovrei anche aggiungere i minuti, magari con una map
    61. m_timePosition.append(i);// qua dovrei anche aggiungere i minuti, magari con una map
    62. }
    63. //Analyze the raw stream of data to determine the min and max amplitude of the sound.
    64. for( int k = 0, j = 0; k < channels; k++, j += 2 )
    65. {
    66. signed short* value1 = reinterpret_cast<signed short*>(stream + j);
    67. int y = *value1 * modifier;
    68. maxValues[k] = y > maxValues[k] ? y : maxValues[k];
    69. minValues[k] = y < minValues[k] ? y : minValues[k];
    70. }
    71.  
    72. //Early out of x is the same
    73. if( oldX == x)
    74. continue;
    75. oldX = x;
    76.  
    77. if( !m_soundLoaded )
    78. progress->setValue(i);
    79.  
    80. //Draw the peaks from midpoint to upper peak, and from midpoint to lower peaks
    81. for( int k = 0, startY = maxHeight; k < channels; k++ )
    82. {
    83. QPoint midPoint = QPoint(x, startY);
    84. painter.drawLine( midPoint, QPoint(x, startY + maxValues[k]) );
    85. painter.drawLine( midPoint, QPoint(x, startY + minValues[k]) );
    86. maxValues[k] = minValues[k] = 0;
    87. startY += increment;
    88. }
    89. }
    90.  
    91. if( !m_soundLoaded )
    92. {
    93. progress->setValue( maxSamplesOnscreen );
    94. progress->deleteLater();
    95. }
    96.  
    97.  
    98. //Draw a mid-based line for each channel around, so there is always 'signal displayed' used against
    99. //double point in-precision.
    100. for( int k = 0, startY = maxHeight; k < channels; k++ )
    101. {
    102. painter.drawLine( QPoint(0, startY), QPoint(w, startY) );
    103. startY += increment;
    104. }
    105.  
    106. //Clean up the outline tables for min and max values.
    107. delete minValues;
    108. delete maxValues;
    109.  
    110. m_soundLoaded = true;
    111. }
    To copy to clipboard, switch view to plain text mode 

    In brief if no sound is loaded I show an image, if a sound is loaded I draw the waveform of the sound.
    If the sound is not loaded It correctly display the "NO SOUND" image. When I load a sound It doesn't draw nothing.
    I paint in a cache in the updateWave and I draw the cache content in the paintEvent but nothing is displayed.

    Where my code is wrong? Is the first time that I derive from QAbstractScrollArea and for me is not easy.
    I need help to improve my knoledge please.

    Regards
    Franco Amato

Similar Threads

  1. ScrollArea:AutoScroll to setfocus'ed control
    By BalaQT in forum Qt Programming
    Replies: 4
    Last Post: 26th October 2009, 05:39
  2. Autoscroll in ScrollArea
    By BalaQT in forum Qt Programming
    Replies: 2
    Last Post: 26th October 2009, 05:37
  3. QTableView restrict ScrollArea
    By hoshy in forum Qt Programming
    Replies: 2
    Last Post: 6th April 2009, 08:54
  4. scrollArea not updating
    By user in forum Qt Programming
    Replies: 9
    Last Post: 3rd October 2007, 08:17
  5. QTreeWidget without the ScrollArea?
    By Paalrammer in forum Newbie
    Replies: 5
    Last Post: 13th February 2007, 19:06

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.