views:

541

answers:

4

Already implemented performance boosters : - Get compatible image of GraphicsConfiguration to draw on - Enable OpenGL pipeline in 1.5: Not possible due to severe artifacts

So far I am fine, the main profiled bottleneck of the program is drawing an image with several thousand tiles. Unfortunately it is not regular, else I simply could set pixels and scale them. I accerelated the image with VolatileImages and own rendering routines (ignore repaint and draw it itself with a timer). The result was pleasing and would suffice, BUT: Choosing a JMenu which hovers normally over the part of the image is severely disturbed because the JMenu is overdrawn. Inacceptable and the layout couldn't be changed.

I tried the GLJPanel of JOGL, but there is no visible performance improvement. So is there a possibitlity to use VolatileImages (or other accerelated lightweighted components like GLCanvas) and still get normal JMenu display and if yes, how ?

A: 

Well, I'm not sure if I fully understand your problem but it seems that main problem is with repainting the panel where image is displayed. Should you please provide your drawing routine which draws image on panel?

Rastislav Komara
+2  A: 

You could try to set the popups to non-leightweight. I am not quite sure if it works but it could, because the popup is a native component then and will not be overdrawn. Setting Popups to heavyweight: JPopupMenu.setDefaultLightWeightPopupEnabled(false)

More Information: Mixing heavy and light components

Roland Schneider
+1  A: 

Here an example code:

import javax.swing.*;

import java.awt.*;

import java.awt.event.WindowAdapter;

import java.awt.event.WindowEvent;

import java.awt.image.BufferStrategy;

import java.awt.image.BufferedImage;

import java.awt.image.VolatileImage;

import java.io.File;

import java.io.IOException;

import java.util.Timer;

import java.util.TimerTask;

public final class FastDraw extends JFrame {

private static final transient double NANO = 1.0e-9;

private BufferStrategy bs;

private BufferedImage frontImg;

private BufferedImage backImg;

private int PIC_WIDTH, PIC_HEIGHT;

private Timer timer;

public FastDraw() {

timer = new Timer(true);

JMenu menu = new JMenu("Dummy");

menu.add(new JMenuItem("Display me !"));

menu.add(new JMenuItem("Display me, too !"));

JMenuBar menuBar = new JMenuBar();

menuBar.add(menu);

setJMenuBar(menuBar);

setIgnoreRepaint(true);

setVisible(true);

addWindowListener(new WindowAdapter() {

  public void windowClosing(WindowEvent evt) {

    super.windowClosing(evt);

    timer.cancel();

    dispose();

    System.exit(0);
  }
});

try {

  backImg = javax.imageio.ImageIO.read(new File(<insert a jpg picture here>));

  frontImg = javax.imageio.ImageIO.read(<here, too>));

}

catch (IOException e) {

  System.out.println(e.getMessage());

}

PIC_WIDTH = backImg.getWidth();

PIC_HEIGHT = backImg.getHeight();

setSize(PIC_WIDTH, PIC_HEIGHT);


createBufferStrategy(1); // Double buffering

bs = getBufferStrategy();

timer.schedule(new Drawer(),0,20);

}

public static void main(String[] args) {

new FastDraw();

}

private class Drawer extends TimerTask {

private VolatileImage img;

public void run() {

  long begin = System.nanoTime();

  Graphics2D  g  = (Graphics2D) bs.getDrawGraphics();

  GraphicsConfiguration gc = g.getDeviceConfiguration();

  if (img == null)

    img = gc.createCompatibleVolatileImage(PIC_WIDTH, PIC_HEIGHT);

  Graphics2D g2 = img.createGraphics();


  do {
    int valStatus = img.validate(gc);

    if (valStatus == VolatileImage.IMAGE_OK)

      g2.drawImage(backImg,0,0,null);

    else {

      g.drawImage(frontImg, 0, 0, null);
    }
    // volatile image is ready
    g.drawImage(img,0,50,null);

    bs.show();

  } while (img.contentsLost());
}

} }

Resize the window to make the JMenuBar visible. Try to select a menu point. See ?

A: 

Answer before helped me: I use now Menu, MenuBar, etc. instead of JMenu, JMenuBar etc.

These heavyweight components paint over own drawn "buffered" Graphics