PDA

View Full Version : paint in the viewport of a scrollarea



franco.amato
25th March 2010, 05:29
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:


void WaveDisplay::paintEvent( QPaintEvent* pe )
{
if( m_waveCachePixmap.isNull() )
{
updateWave();
}

QPainter p( this );
p.setRenderHint( QPainter::Antialiasing, true );
QPen pen = QPen( Qt::darkRed, 1 );

// wave
p.drawPixmap( 0, 0, m_waveCachePixmap );

// timeline
pen.setColor(Qt::darkRed);
pen.setStyle(Qt::SolidLine);
p.setPen( pen );
p.drawLine( m_CurrentTimePosition, 0, m_CurrentTimePosition, height() );

// elapsed time
QWidget* widget = area->viewport(); //HOW CAN I USE THE VIEW PORT
setElapsedTime( m_CurrentSoundPosition );
QFont font = p.font();
font.setPointSize( 24 );
p.setFont( font );
p.drawText( QPoint(20, 20), m_elapsedTimeString ); //THE TEXT DISAPPEAR

QWidget::paintEvent(pe);
}

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

aamer4yu
25th March 2010, 05:52
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 -

ScrollArea::paintEvent(*event)
{
QScrollArea::paintEvent(event); // call the base class first.
QPainter painter(this);
painter.drawText(..); // draw your text.
}

franco.amato
25th March 2010, 06:10
Yes WaveDisplay is the widget I attached to a scrollarea so:



/* scroll area */
sa = new QScrollArea;
sa->setWidgetResizable(true);
QScrollBar* scrollBar = sa->horizontalScrollBar();
scrollBar->setSliderDown( true );
sa->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff) ;
sa->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn );

m_WaveDisplay = new WaveDisplay(sa, sa->viewport());
m_WaveDisplay->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Ignored);
sa->setWidget( m_WaveDisplay );


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

aamer4yu
25th March 2010, 06:24
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.

franco.amato
25th March 2010, 16:48
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:



#ifndef __SCROLLAREA_H__
#define __SCROLLAREA_H__

#include <QScrollArea>

class ScrollArea : public QScrollArea
{
public:
ScrollArea( QWidget* parent = 0 );
~ScrollArea();

protected:
virtual void paintEvent(QPaintEvent *);

private:
};
#endif //__SCROLLAREA_H__



and I implemented the paintEvent as you said:

#include "ScrollArea.h"
#include <QPainter>

ScrollArea::ScrollArea( QWidget* parent /* = 0 */ ): QScrollArea(parent)
{
}

ScrollArea::~ScrollArea()
{
}

void ScrollArea::paintEvent(QPaintEvent *event)
{
QScrollArea::paintEvent(event); // call the base class first.
QPainter painter(this);
painter.drawText(20,50, "Just a test"); // draw your text.
}

Now I attached WaveDisplay to the ScrollArea instead of QScrollArea:

/* scroll area */
//sa = new QScrollArea;
sa = new ScrollArea;
sa->setWidgetResizable(true);
QScrollBar* scrollBar = sa->horizontalScrollBar();
scrollBar->setSliderDown( true );
sa->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff) ;
sa->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn );

m_WaveDisplay = new WaveDisplay(sa, sa->viewport());
m_WaveDisplay->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Ignored);
sa->setWidget( m_WaveDisplay );


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

franco.amato
25th March 2010, 20:01
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

wysota
25th March 2010, 20:22
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.

franco.amato
25th March 2010, 21:30
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

wysota
25th March 2010, 21:45
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.

franco.amato
25th March 2010, 22:06
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

wysota
26th March 2010, 00:05
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...

franco.amato
29th March 2010, 18:19
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.

wysota
29th March 2010, 23:34
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.


#include <QtGui>
#include <cmath>

class SineScroller : public QAbstractScrollArea {
public:
explicit SineScroller(QWidget *parent = 0) : QAbstractScrollArea(parent){

}
protected:
void paintEvent(QPaintEvent *pe) {
QPainter p(viewport());
QRect visibleRect = QRect(100, 10, viewport()->width()-200, viewport()->height()-20);
p.drawRect(visibleRect);
p.drawText(5, 50, QString::number(horizontalScrollBar()->value()*0.25, 'f', 2));
p.drawText(viewport()->rect().right()-95, 50, QString::number((horizontalScrollBar()->value()+viewport()->width()-200)*0.25, 'f', 2));

// draw Horizontal axis
int voffset = verticalScrollBar()->value();
// voffset := the value of yCoord at top edge of visibleRect
// we want to draw at 360
if(voffset<360 && voffset+visibleRect.height() > 360) {
p.save();
p.setPen(Qt::red);
p.drawLine(visibleRect.left(), 370-voffset, visibleRect.right(), 370-voffset);
p.restore();
}

// draw Sine curve
double startValInDeg = horizontalScrollBar()->value()*0.25;
double stopValInDeg = startValInDeg + visibleRect.width()*0.25;
p.save();
p.setPen(Qt::blue);
p.setClipRect(visibleRect); // crude but effective
p.setClipping(true);
int curX = visibleRect.left();
QPolygon poly;
for(double valInDeg = startValInDeg; valInDeg<=stopValInDeg; valInDeg += 0.25) {
double valInRad = valInDeg * M_PI / 180;
double sineVal = sin(valInRad);
poly << QPoint(curX++, 370-voffset-360*sineVal);
}
p.setRenderHint(QPainter::Antialiasing);
p.drawPolyline(poly);
p.restore();
}
void resizeEvent(QResizeEvent *re) {
QAbstractScrollArea::resizeEvent(re);
int visibleWidth = viewport()->width() - 200;
int visibleHeight = viewport()->height() - 20;
QScrollBar *h = horizontalScrollBar();
QScrollBar *v = verticalScrollBar();
h->setRange(0, qBound(0, 1440-visibleWidth, 1440));
v->setRange(0, qBound(0, 720-visibleHeight, 720));
}
};


int main(int argc, char **argv) {
QApplication app(argc, argv);
SineScroller scroller;
scroller.show();
return app.exec();
}

franco.amato
30th March 2010, 00:05
Thank you very much for the code. I'll try it immediately

franco.amato
30th March 2010, 03:22
I have a problem with paintEvent.

I have created the class


class WaveDisplay : public QAbstractScrollArea
{
Q_OBJECT

public:
WaveDisplay( QWidget* parent = 0 );
virtual ~WaveDisplay();

void closeSoundFile( QString soundName_ );

void setWave( SoundData* );
void playSound(int vol_ );
void stopSound();

...code...

public slots:
...code...

private slots:
void setElapsedTime( uint soundPos );
void fitToWindow();

signals:
void soundPositionChanged( uint );
void zoomFactorChanged( float );

protected:
/* paint event */
virtual void paintEvent( QPaintEvent* event );
...more code...

private:
void updateWave();
void drawStandardPCM16(QPainter&, int);
void drawStandardPCM8(QPainter&);

QPixmap m_waveCachePixmap;
SoundData* m_wave;
...more code...
};

and I mainly would implement the paintEvent.

So I changed a bit the paintEvent of my last class


/*****************************************/
/* Paint event */
/*****************************************/
void WaveDisplay::paintEvent( QPaintEvent* pe )
{
QAbstractScrollArea::paintEvent( pe );

// Update the ev->rect area with the wave from the rendered QPixmap here
if( m_waveCachePixmap.isNull() )
{
updateWave();
}

QPainter p( viewport() );
p.setRenderHint( QPainter::Antialiasing, true );
QPen pen = QPen( Qt::darkRed, 1 );

// wave
p.drawPixmap( 0, 0, m_waveCachePixmap );

// timeline
pen.setColor(Qt::darkRed);
pen.setStyle(Qt::SolidLine);
p.setPen( pen );
p.drawLine( m_CurrentTimePosition, 0, m_CurrentTimePosition, height() );

// elapsed time
setElapsedTime( m_CurrentSoundPosition );
QFont font = p.font();
font.setPointSize( 24 );
p.setFont( font );
p.drawText( QPoint(20, 50), m_elapsedTimeString );
}

and the updateWave

void WaveDisplay::updateWave()
{
int h = this->height();
int w = this->width();

// I want another width and height here.
// Also, you might to clear the cache at resize events
QPixmap temp = QPixmap( w, h );

QPainter p( &temp );
//p.setRenderHint( QPainter::Antialiasing, true );
p.fillRect( temp.rect(), bgColor );

// timeline
QPen pen(Qt::black);
pen.setWidthF( 1.0 );
pen.setStyle(Qt::SolidLine);
p.setPen(pen);
p.drawLine( 0.0, 0.0, (qreal)w, 0.0 );

// Draw the waveform or load no data image
if( m_wave )
{
pen.setColor( wfColor ); // darkCyan solid line, 1 pixels wide
pen.setStyle(Qt::SolidLine);
p.setPen( pen );

void* soundStream = m_wave->getSoundStream();
unsigned int numSamples = m_wave->getSamples();
int channels = m_wave->getChannels();
FMOD_SOUND_TYPE soundType = m_wave->getSoundType();
FMOD_SOUND_FORMAT soundFormat = m_wave->getSoundFormat();
unsigned int dur = m_wave->getLengthMSeconds();

float* minValue = new float[channels];
float* maxValue = new float[channels];

//int sampleSize = channels * ( soundFormat == PCM8 ) ? 1 : 2;
int sampleSize = channels; //<-- questo concetto non funziona, io lo chiamerei step

int maxHeight = (h / 2) / channels;
int increment = (h / 2);

switch( soundFormat )
{
case PCM8: //8 bits mono
{
//..to implement
break;
}
case PCM16: //16 bits stereo (LRLRLRLR...LRLR)
{
drawStandardPCM16( p, 1 );

qreal samplePerPixel = m_wave->getSamples() / width();
// qua disegno le tacchette temporali
if(!m_timePosition.isEmpty())
{
pen.setColor( Qt::black );
p.setPen(pen);

QList<uint>::const_iterator it;
qreal widgetPos = 0;

for( it = m_timePosition.constBegin(); it != m_timePosition.constEnd(); ++it )
{
/* trasformo il valore temporale in valore di coordinata x del widget */
widgetPos = *it / samplePerPixel;
p.drawLine( widgetPos, 0, widgetPos, 10 );// from 0 to 10 for the seconds
}
}
//markers
if( !m_ListaMarcatori.isEmpty() )
{
pen.setColor(Qt::yellow);
pen.setStyle( Qt::DashLine );
p.setPen(pen);
QList<uint>::const_iterator it;
qreal widgetPos = 0;
for(it = m_ListaMarcatori.constBegin(); it != m_ListaMarcatori.constEnd(); ++it)
{
/* from time value to widget value */
widgetPos = *it / samplePerPixel;
p.drawLine( widgetPos, 0, widgetPos, height() );
}
}
break;
}
default:
{
qDebug("Undefined sound type");
break;
}
}
}
else
{
p.drawImage( rect(), QImage(":/images/logo/nodata.jpg") );
}

m_waveCachePixmap = temp;
}

and finally the drawStandardPCM16


/************************************************** **********************/
/* drawStandardPCM16: spostarlo nel sounddata */
/************************************************** **********************/
void WaveDisplay::drawStandardPCM16( QPainter& painter, int numSamples )
{
int h = height();
int w = width();

// Calculate magical constants that should be left untouched unless dealing with
// other variants of PCM-Streams.
int channels = m_wave->getChannels();
int bits = m_wave->getBits();
int pcm_length = m_wave->getPcmLength();
int freq = m_wave->getFrequency();

int sample_size = channels * bits / 8;

int samples = pcm_length / sample_size; //pcm_length bytes totali del sound
int maxHeight = (h / 2) / channels;
int increment = (h / 2);
float modifier = (float)maxHeight / 0x0000FFFF * 2;
int* minValues = new int[channels];
int* maxValues = new int[channels];

//Adjust these values to obtain a different drawing scheme. Offset defines the initial sample
//where to begin drawing (it takes into account channel, sample size, bit size etc). maxSamplesOnscreen
//defines the amount of samples displayed on the screen.
int startOffset = 0;
int maxSamplesOnscreen = samples;

// Calculate the starting position in the stream where start fetching our data. And calculate
// the width between samples. By default the width truncated to the nearest integer for drawing.
// Note: doubles are needed for this calculation due floating point in-precision. Floating point
// operations have the same speed either so it's quite valid.
char* stream = (char*)m_wave->getSoundStream() + (startOffset * sample_size);
double samplesInc = 1.0f / ( maxSamplesOnscreen / (double)w);
double samplesCur = 0.0f;

//Correct the maximum samples displayed on the screen, if this step is not done we'ld be
//drawing outside the boundaries of the data stream.
maxSamplesOnscreen = (samples - startOffset) > maxSamplesOnscreen ? maxSamplesOnscreen : (samples - startOffset);

QProgressDialog *progress = new QProgressDialog(
"Creating waveform...",
"Abort process",
0,
maxSamplesOnscreen,
this);

if( !m_soundLoaded )
progress->setWindowModality( Qt::WindowModal );

//Iterate over each sample that lies withing the lower and upper boundaries that we precomputed. For
//every sample we draw the maximum value, and minimum value. Store the value in a temp. array and process that
//array once we detect our x is changed.
for( int i = startOffset, maxI = i + maxSamplesOnscreen, oldX = 0, x = 0; i < maxI; i++, stream += sample_size, samplesCur += samplesInc, x = samplesCur)
{
if( i % (60 * freq) == 0 ) //ogni minuto
{
// aggiungo un marcatore del tempo alla lista
//m_timePosition.append(i);// qua dovrei anche aggiungere i minuti, magari con una map
m_timePosition.append(i);// qua dovrei anche aggiungere i minuti, magari con una map
}
//Analyze the raw stream of data to determine the min and max amplitude of the sound.
for( int k = 0, j = 0; k < channels; k++, j += 2 )
{
signed short* value1 = reinterpret_cast<signed short*>(stream + j);
int y = *value1 * modifier;
maxValues[k] = y > maxValues[k] ? y : maxValues[k];
minValues[k] = y < minValues[k] ? y : minValues[k];
}

//Early out of x is the same
if( oldX == x)
continue;
oldX = x;

if( !m_soundLoaded )
progress->setValue(i);

//Draw the peaks from midpoint to upper peak, and from midpoint to lower peaks
for( int k = 0, startY = maxHeight; k < channels; k++ )
{
QPoint midPoint = QPoint(x, startY);
painter.drawLine( midPoint, QPoint(x, startY + maxValues[k]) );
painter.drawLine( midPoint, QPoint(x, startY + minValues[k]) );
maxValues[k] = minValues[k] = 0;
startY += increment;
}
}

if( !m_soundLoaded )
{
progress->setValue( maxSamplesOnscreen );
progress->deleteLater();
}


//Draw a mid-based line for each channel around, so there is always 'signal displayed' used against
//double point in-precision.
for( int k = 0, startY = maxHeight; k < channels; k++ )
{
painter.drawLine( QPoint(0, startY), QPoint(w, startY) );
startY += increment;
}

//Clean up the outline tables for min and max values.
delete minValues;
delete maxValues;

m_soundLoaded = true;
}

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