JMenus вызывал мерцание холста JOGL GLCanvas

Щелчок по параметрам JMenu вызывает мерцание моего JOGL GLCanvas.

В JMenu для setDefaultLightWeightPopupEnabled установлено значение false. Я не хочу использовать JGLPanel, потому что он работает медленнее (приложение должно работать в полноэкранном режиме).

Интересно, мерцание прекращается, если я устанавливаю sun.java2d.opengl=true в командной строке. Однако тот факт, что sun не включает это по умолчанию, заставляет меня беспокоиться о том, что у моих пользователей могут возникнуть проблемы с аппаратной несовместимостью.

Видят ли другие люди мерцание с кодом ниже при нажатии на меню?

Я пробовал всевозможные вещи, такие как игра с параметрами двойной буферизации для JFrame и для холста, но мне не удалось заставить холст не мерцать.

Может ли кто-нибудь заставить это не мерцать при просмотре пунктов меню?

Спасибо!

-Дэн

import javax.media.opengl.*;
import javax.swing.*;

public class FlickerTest extends JFrame {
    private GLCapabilities m_caps = new GLCapabilities();

    public FlickerTest() {
        super("FlickerTest");

        GLCanvas canvas = new GLCanvas(m_caps);
        add( canvas );
        canvas.addGLEventListener( new MyGLEventListener() );

        setSize( 640, 480 );
        setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

        // false lets the JMenuBar appear on top of the remote image openGL canvas
        JPopupMenu.setDefaultLightWeightPopupEnabled(false);

        setJMenuBar( getMyMenuBar() );
        setVisible( true );
    }

    public static void main(String[] args) {
        new FlickerTest();
    }

    private static JMenuBar getMyMenuBar() {
        JMenuBar menuBar = new JMenuBar();
        JMenu fileMenu = new JMenu("File");
        JMenuItem quitMenuItem = new JMenuItem( "Quit" );
        JMenuItem doSomething = new JMenuItem("Do Something");
        fileMenu.add( quitMenuItem );
        fileMenu.add( doSomething );

        menuBar.add( fileMenu );
        return menuBar;
    }

    private class MyGLEventListener implements GLEventListener {
        private MyGLEventListener() {
        }

        public void init(GLAutoDrawable drawable) {
            GL gl = drawable.getGL();
            gl.glClearColor(1,1,0,0);
            gl.glBlendFunc(GL.GL_ONE,GL.GL_ONE);
            gl.glEnable(GL.GL_BLEND);
        }

        public synchronized void display( GLAutoDrawable p_glAutoDrawable ) {
            GL gl = p_glAutoDrawable.getGL();

            gl.glClear(GL.GL_COLOR_BUFFER_BIT);

            gl.glColor3f(0,0,1);
            gl.glRectf(-.5f,-.5f,.5f,.5f);
            gl.glFlush();
        }

        public void reshape(GLAutoDrawable p_drawable, int x, int y, int w, int h) {
        }

        public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {
        }
    }
}

person user41762    schedule 05.01.2009    source источник


Ответы (3)


Это вызвано тем, что AWT стирает GLCanvas каждый раз перед тем, как JOGL перерисует его, и это можно обойти, вставив следующую строку в ваш метод main():

System.setProperty("sun.awt.noerasebackground", "true");

Хотя это решает данную проблему, возможны побочные эффекты в других областях приложения, например видимые артефакты при изменении размера окна. Я использую это во всех своих приложениях JOGL, хотя без каких-либо проблем.

person cgull    schedule 06.02.2009
comment
Если вы не хотите делать это на уровне приложения, вы можете избежать очистки области просмотра в коде рисования JOGL. - person DJClayworth; 17.02.2011


Вы можете добавить аниматор. Холст может мерцать, потому что JFrame недостаточно быстро обновляет его.

FPSAnimator = new FPSAnimator(GLCanvas,int TARGET_FPS, boolean);
person wusher    schedule 07.01.2009
comment
Нет, он мерцает только при выборе/отмене выбора меню. Это не зависит от аниматора, что имеет значение только тогда, когда вы отображаете разные изображения с течением времени. - person user41762; 09.01.2009