2 Stimmen

Beschleunigung von 2D-Bildern in Java *ohne* Störung der JMenus

Bereits implementierte Leistungssteigerungen : - Kompatibles Bild der GraphicsConfiguration zum Zeichnen abrufen - Aktivieren der OpenGL-Pipeline in 1.5: Nicht möglich wegen starker Artefakte

Bisher geht es mir gut, der größte profilierte Engpass des Programms ist das Zeichnen eines Bildes mit mehreren tausend Kacheln. Leider ist es nicht regelmäßig, sonst könnte ich einfach Pixel setzen und skalieren. Ich habe das Bild mit VolatileImages und eigenen Rendering-Routinen (Repaint ignorieren und es selbst mit einem Timer zeichnen) akzentuiert. Das Ergebnis war ansprechend und würde ausreichen, ABER: Wenn man ein JMenu auswählt, das normal über dem Teil des Bildes schwebt, wird das stark gestört, weil das JMenu überzeichnet ist. Inakzeptabel und das Layout konnte nicht geändert werden.

Ich habe das GLJPanel von JOGL ausprobiert, aber es gibt keine sichtbare Leistungsverbesserung. Gibt es also eine Möglichkeit, VolatileImages (oder andere zugehörige leichtgewichtige Komponenten wie GLCanvas) zu verwenden und trotzdem die normale JMenu-Anzeige zu erhalten und wenn ja, wie?

2voto

Roland Schneider Punkte 3575

Sie könnten versuchen, die Popups auf nicht leichtgewichtig einzustellen. Ich bin mir nicht ganz sicher, ob es funktioniert, aber es könnte, weil das Popup dann eine native Komponente ist und nicht überzeichnet wird. Popups auf schwergewichtig setzen: JPopupMenu.setDefaultLightWeightPopupEnabled(false)

Weitere Informationen: Mischen von schweren und leichten Komponenten

1voto

Hier ist ein Beispielcode:

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());
        }
    }
}

Ändern Sie die Größe des Fensters so, dass die JMenuBar sichtbar. Versuchen Sie, einen Menüpunkt auszuwählen. Sehen Sie?

0voto

Rastislav Komara Punkte 1711

Nun, ich bin mir nicht sicher, ob ich Ihr Problem vollständig verstehe, aber es scheint, dass das Hauptproblem mit der Neufärbung des Feldes ist, wo das Bild angezeigt wird. Sollten Sie bitte Ihre Zeichenroutine zur Verfügung stellen, die das Bild auf dem Panel zeichnet?

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X