problem with painting background in paintComponent.

Hi everyone,

What I'm trying to do is draw a waveform on a Jpanel. I created an inner class that extends JPanel. The inner class has a method called setData that accepts an array of bytes. This method converts the byte array to a set of x values and a set of y values. Then the repaint() method is called for each point. The problem is that it erases all the previous points. How do I prevent it doing that?

This is the code - might make it clearer.

publicvoid setData(byte []audioData)

{

yValues =newint[audioData.length];

xValues =newint[audioData.length];

started =true;

for(int i =0;i<audioData.length;i++)

{

yValues[i] = (int) audioData[i];

xValues[i]+=20;

this.repaint();

}

}

publicvoid paintComponent(Graphics g)

{

super.paintComponent(g);//paint background

this.setBackground(Color.green);

this.setForeground(Color.blue);

Graphics2D g2 = (Graphics2D)g;

if(started ==true)

{

int i =0;

i++;

x+=20;

g2.fillOval(x,yValues[i]+200, 5,5);

}

}

>

[1908 byte] By [CurtinR] at [2007-9-27 22:48:16]
# 1
There are 2 options:1. draw all the points every time in the paintComponent(..)2. create an image the first time the paintComponent is called, draw the point to this image and draw the image to the panel.Noah
noah.w at 2007-7-7 13:52:30 > top of Java-index,Archived Forums,New To Java Technology Archive...
# 2

Thanks for that! I think I'll go with the second option - I can't use the first option because I don't know the coordinates of the points in advance.

How do I go about adding the other points to an image that I've already created? Do I need to use memoryImageSource?

This is my code so far - I'm not sure if its right cos I'm not too familiar with graphics in Java:

wave = createImage(this.getWidth(),this.getHeight());

g.drawImage(wave,0,0, wave.getWidth(this),wave.getHeight(this),Color.green,this);

I had a look at some tutorials but couldn't really find any examples that used images in this way - if you could suggest any I'd really appreciate it.

Thanks,

CurtinR.

CurtinR at 2007-7-7 13:52:30 > top of Java-index,Archived Forums,New To Java Technology Archive...
# 3

You can use java.awt.image.BufferedImage for that.

BufferedImage bi = new BufferedImage(BufferedImage.TYPE_INT_ARGB, getSize().width, getSize().height);

Graphics2D g = bi.createGraphics();

double framesPerPixel = 5d; //The zoom

int nullLine = getSize().height, index;

int[] samples = getSamples(byteData);

for(int i=0; i<getSize().width-1; i++){

index = (int)(framesPerPixel * i);

if(index+1 > samples.length-1)

break;

g.drawLine(i, nullLine - samples[index],

i+1, nullLine - samples[index+1]);

}

But remember that you cannot simply cast the bytes to integers!

You would get wrong results using that method(except you have 8-bit data).

My code does not make a difference between mono and stereo, which is neccessary, too (except you're dealing only with mono)

Best regards,

Djamal

DOMO at 2007-7-7 13:52:30 > top of Java-index,Archived Forums,New To Java Technology Archive...
# 4
Thank you so much for that Djamal! It works now! Just one question - why can't you cast bytes to integers?Again thanks a million for your help!Roseanne.
CurtinR at 2007-7-7 13:52:30 > top of Java-index,Archived Forums,New To Java Technology Archive...
# 5

Of course you can, but there's no sense in doing that. ;)

Soundfiles are stored like this (16-bit, stereo, bigendian):

hl|hl hl|hl hl|hl hl|hl hl|hl hl|hl

where h is higher-byte and l lower-byte.

The | separates the channels left and right.

The spaces separate the frames.

Or (16-bit, stereo, littleendian:

lh|lh lh|lh lh|lh lh|lh lh|lh lh|lh

The two bytes are forming a sample. Many samples form the waveform. You have to make a difference between bytes and samples(except you're dealing with 8-bit only, because in that special case a byte is a sample)

If you have stereodata you have two samples in one frame.

In mono you have only one sample in a frame.

Bigendian is the order in which the bytes are interpreted as samples:

(I took only 4 bits, that's easier but the prinzip is exactly the same)

1 0 0 1 | 0 1 1 0 the bits in bigendian are:

7 6 5 4 | 3 2 1 0

1 0 0 1 | 0 1 1 0 the bits in littleendian are:

3 2 1 0 | 7 6 5 4

As you see the order in littleendian is reversed.

Now, if you cast the bytes to integers you just get not the right information, because you have to interprete the bytes. Your waveform will look like garbage, if you don't do that.

Bye,

Djamal

DOMO at 2007-7-7 13:52:30 > top of Java-index,Archived Forums,New To Java Technology Archive...