GUI freezes when drawing Wave from animation on JPanel though i used Swing Timer

后端 未结 2 1405
情深已故
情深已故 2020-12-19 23:33

plese look at my code snippets , wha is wrong with it , it frrezes GUI when the Swing timer stats which is repeteadly paints on the jpnael ??

class WaveformP         


        
相关标签:
2条回答
  • 2020-12-20 00:00

    I'm guessing that your wave drawing code, which is being called from within a paintComponent(...) method is taking longer than you think and is tying up both Swing painting and the EDT.

    If this were my code, I'd consider drawing my waves to BufferedImages once, making ImageIcons from these images and then simply swapping icons in my Swing Timer.

    0 讨论(0)
  • 2020-12-20 00:12

    The java.swingx.Timer calls the ActionPerformed within the EDT. The question then is, what's taking the time to render. It could be the call to captureThread.getTempBuffer it could be the construction of the help, but I suspect it's just the share amount of data you are trying to paint.

    Having playing with this recently, it takes quite a bit of time to process the waveform.

    One suggestion might be to reduce the number of samples that you paint. Rather then painting each one, maybe paint every second or forth sample point depending on the width of the component. You should still get the same jest but without all the work...

    UPDATED

    All samples, 2.18 seconds

    AllSamples

    Every 4th sample, 0.711 seconds

    enter image description here

    Every 8th sample, 0.450 seconds

    enter image description here

    Rather then paint in response to the timer, maybe you need to paint in response to batches of data.

    As your loader thread has a "chunk" of data, may be paint it then.

    As HoverCraftFullOfEels suggested, you could paint this to a BufferedImage first and then paint that to the screen...

    SwingWorker might be able to achieve this for you

    UPDATED

    This is the code I use to paint the above samples.

    // Samples is a 2D int array (int[][]), where the first index is the channel, the second is the sample for that channel
    if (samples != null) {
    
        Graphics2D g2d = (Graphics2D) g;
    
        int length = samples[0].length;
    
        int width = getWidth() - 1;
        int height = getHeight() - 1;
    
        int oldX = 0;
        int oldY = height / 2;
        int frame = 0;
    
        // min, max is the min/max range of the samples, ie the highest and lowest samples
        int range = max + (min * -2);
        float scale = (float) height / (float) range;
    
        int minY = Math.round(((height / 2) + (min * scale)));
        int maxY = Math.round(((height / 2) + (max * scale)));
    
        LinearGradientPaint lgp = new LinearGradientPaint(
                new Point2D.Float(0, minY),
                new Point2D.Float(0, maxY),
                new float[]{0f, 0.5f, 1f},
                new Color[]{Color.BLUE, Color.RED, Color.BLUE});
        g2d.setPaint(lgp);
        for (int sample : samples[0]) {
    
            if (sample % 64 == 0) {
    
                int x = Math.round(((float) frame / (float) length) * width);
                int y = Math.round((height / 2) + (sample * scale));
    
                g2d.drawLine(oldX, oldY, x, y);
    
                oldX = x;
                oldY = y;
    
            }
    
            frame++;
    
        }
    
    }
    

    I use an AudioStream stream to load a Wav file an produce the 2D samples.

    0 讨论(0)
提交回复
热议问题