0

I have a JFrame with an JLabel that houses an ImageIcon containing a BufferedImage. The BufferedImage's graphis are drawn on with several different graphics calls, such as drawOval(), drawRectangle(), etc, with many drawn shapes on it. As time passes ,or the user pans/zooms on the panel, the graphics are redrawn, so we could be redrawing several times per second.

Before attempting to add double buffering, the image repaint was slow, but my JComponents would render OK. The image would redraw multiple times as second as the user could drag and resize the label. I decided to attempt double buffering.

With my current double-buffered implementation below, the JLabel/Graphics redraw and show very smooth. However, The JFrame has other controls (JMenuBar, JSlider, JComboBox, etc.) that do not render properly and flicker a lot. I have to manually repaint() them, but then they flicker. What am I doing wrong with Double buffering? How can I get my image to repaint smoothly, but also allow my JComponetns to not flicker?

The view sets himself up to do double buffering. I also tried setting setIgnoreRepaint(true) as a way to fix my issue.

this.createBufferStrategy(2);

...

m_graphicsLabel.setIcon(new ImageIcon(bufferedImage));  

This method below is called by the helper class when new graphics are available. I am manually repainting the JComponents, otherwise they wouldn't show up at all. But they flicker as this method can be called multiple times per second.

public void newViewGraphicsAvailable() {    

    m_xAxisZoomSlider.repaint();
    m_yAxisZoomSlider.repaint();
    lblZoom.repaint();
    lblYZoom.repaint();
    m_comboBox.repaint();
    m_menuBar.repaint();
    m_layersMenu.repaint(); 
}

This is the helper class that manipulates the graphics object with calls to graphics.drawOval() etc.

private void drawGraphics(){
    BufferedImage blankImage = createBlankImage();      
    Graphics g = null;
    try {
        g = m_bufferedStrategy.getDrawGraphics();       
        g.drawImage(blankImage, 0, 0, null);
        m_imageDrawer.draw((Graphics2D) g);     
    } finally {
        g.dispose();        
    }   
    m_bufferedStrategy.show();

    Toolkit.getDefaultToolkit().sync();
    view.newGraphicsAvailable();
}



private BufferedImage createBlankImage()
{
    short[] backgroundPixels = new short[Width * Height];
    for(int index = 0; index < backgroundPixels.length; index++) {
        backgroundPixels[index] = 0;
    }

    DataBuffer dbuf = new DataBufferUShort(backgroundPixels, WaterfallHeight * WaterfallWidth, 0);
    int bitMasks[] = new int[]{0xFFFF};
    SampleModel sampleModel = new SinglePixelPackedSampleModel(
                    DataBuffer.TYPE_USHORT, WaterfallWidth, WaterfallHeight, bitMasks);
    WritableRaster raster = Raster.createWritableRaster(sampleModel, dbuf, null);   

    return new BufferedImage(m_indexColorModel, raster, false, null);                       
}
Stealth Rabbi
  • 10,156
  • 22
  • 100
  • 176
  • 1
    For better help sooner, post an [SSCCE](http://sscce.org/). – Andrew Thompson Oct 16 '13 at 15:16
  • Swing components are by default double buffered. You're messing swing's drawing mechanism quite badly by accessing the graphics directly. – kiheru Oct 16 '13 at 15:17
  • @kiheru I need to access the graphics directly for drawing the image I'm building. Are you referring to doing the repainting of the other components? I agree that this is not a good idea, it's just an attempt at fixing the issue and to get them to display by default. – Stealth Rabbi Oct 16 '13 at 15:19
  • I'm referring to `createBufferStrategy()` and related. I don't mind how you create images. (Though for painting in single color `fillRect()` would be more appropriate). – kiheru Oct 16 '13 at 15:27
  • Is the image really big or something? You shouldn't need buffer strategies and rasters and stuff to just paint an icon. Are you drawing stuff on the image? Where is drawGraphics? In paintComponent? If all you are doing is drawing on an image once and then setting it to the icon you don't need to do any of all that stuff. That is the point of a BufferedImage. Draw to it once then just draw the image in paintComponent. – Radiodef Oct 19 '13 at 02:33
  • The icon is not static. I'm using a BufferedImage to draw a lot of sprites in the graphic, which is 400x400 or larger. The graphics are moved up in a timeflow as time passes, so the image is changing several times as a second as the user pans/zooms around the image. Sorry I didn't make that clear in the question. – Stealth Rabbi Oct 21 '13 at 12:46

0 Answers0