使用Java *加速2D图像,而不会干扰JMenus

时间:2022-09-10 16:44:47

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

已经实现的性能提升器: - 获取要兼容的GraphicsConfiguration图像 - 在1.5中启用OpenGL管道:由于严重的工件而无法实现

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.

到目前为止,我很好,该程序的主要描述瓶颈是绘制一个有几千个瓷砖的图像。不幸的是,它不是常规的,否则我只需设置像素并缩放它们。我使用VolatileImages和自己的渲染例程加入了图像(忽略重绘并用计时器绘制它自己)。结果令人满意并且足够,但是:选择一个在图像部分正常悬停的JMenu会因为JMenu透支而受到严重干扰。不可接受,布局无法改变。

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 ?

我尝试了JOGL的GLJPanel,但没有明显的性能提升。那么是否有可能使用VolatileImages(或其他加速的轻量级组件,如GLCanvas),仍然可以获得正常的JMenu显示,如果是,如何?

3 个解决方案

#1


2  

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)

您可以尝试将弹出窗口设置为非轻量级。我不太确定它是否有效,但它可以,因为弹出窗口是一个原生组件,然后不会透支。将弹出窗口设置为重量级:JPopupMenu.setDefaultLightWeightPopupEnabled(false)

More Information: Mixing heavy and light components

更多信息:混合重型和轻型部件

#2


1  

Here is some 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?

调整窗口大小以使JMenuBar可见。尝试选择菜单点。看到?

#3


0  

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?

好吧,我不确定我是否完全理解你的问题,但似乎主要问题是重新绘制显示图像的面板。您是否应该提供在面板上绘制图像的绘图程序?

#1


2  

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)

您可以尝试将弹出窗口设置为非轻量级。我不太确定它是否有效,但它可以,因为弹出窗口是一个原生组件,然后不会透支。将弹出窗口设置为重量级:JPopupMenu.setDefaultLightWeightPopupEnabled(false)

More Information: Mixing heavy and light components

更多信息:混合重型和轻型部件

#2


1  

Here is some 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?

调整窗口大小以使JMenuBar可见。尝试选择菜单点。看到?

#3


0  

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?

好吧,我不确定我是否完全理解你的问题,但似乎主要问题是重新绘制显示图像的面板。您是否应该提供在面板上绘制图像的绘图程序?