我试图将OpenGL上下文添加到jFrame。

当我这样做时它会起作用:

jframe.setVisible( true );
jframe.getContentPane().add( glcanvas, BorderLayout.CENTER );
jframe.revalidate();
jframe.repaint();


但是,如果我尝试在按钮上创建上下文,则单击,如下所示:

JButton startButton = new JButton("Start");
startButton.addActionListener(
    new ActionListener()
{
    @Override
    public void actionPerformed(ActionEvent e)
    {
            jframe.getContentPane().add( glcanvas, BorderLayout.CENTER );
        jframe.revalidate();
        jframe.repaint();
        }
});
jframe.add(startButton);


那什么也没发生如果我尝试对其进行调试,则程序将通过revalidate()和repaint()命令运行,但没有任何变化。

有人可以告诉我为什么会发生这种情况吗?当我尝试按按钮调用它时,为什么会有所不同?您还可以建议解决此问题的方法吗?我需要能够从菜单系统中打开上下文。

-
编辑:这是我的测试程序的完整代码

/* -- OpenGL -- */
import javax.media.opengl.GL2ES2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
import javax.media.opengl.awt.GLCanvas;
import javax.media.opengl.awt.GLJPanel;
import javax.swing.JComponent;

/* -- Swing -- */
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JLabel;

import javax.swing.JPanel;

/* -- jFrame Layouts -- */
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class Menu
{
public static void main(String[] args)
{

        GLProfile glprofile = GLProfile.getDefault();
        GLCapabilities glcapabilities = new GLCapabilities( glprofile );
        final GLCanvas glcanvas = new GLCanvas( glcapabilities );

        glcanvas.addGLEventListener( new GLEventListener()
        {
            @Override
            public void init( GLAutoDrawable glautodrawable )
            {
                System.out.println("INIT");
            }

            @Override
            public void reshape( GLAutoDrawable glautodrawable, int x, int y, int width, int height )
            {
                GL2ES2 gl = glautodrawable.getGL().getGL2ES2(); //Get OpenGL

                gl.glViewport( 0, 0, width, height );   //Set the viewport
            }

            @Override
            public void display( GLAutoDrawable glautodrawable )
            {
                GL2ES2 gl = glautodrawable.getGL().getGL2ES2();

                gl.glClearColor(+0.0f, +0.2f, +0.9f, +0.0f);  // Blue background

                //Clear the screen so that we can draw the new one
                gl.glClear(
                    GL2ES2.GL_STENCIL_BUFFER_BIT |
                    GL2ES2.GL_COLOR_BUFFER_BIT   |
                    GL2ES2.GL_DEPTH_BUFFER_BIT
                );
            }

            @Override
            public void dispose( GLAutoDrawable glautodrawable )
            {

            }

        }); /* Add GLEventListner to glCanvas */

        final JFrame jframe = new JFrame( "One Triangle Swing GLCanvas" );
        jframe.addWindowListener( new WindowAdapter()
        {
            public void windowClosing( WindowEvent windowevent )
            {
                jframe.dispose();
                System.exit( 0 );
            }
        });

        jframe.setSize( 800, 600 );
        jframe.setVisible( true );

        /* --- IF I ADD THE ContentPane HERE AND REVALIDATE/REPAINT IT WORKS --- */
        //jframe.getContentPane().add( glcanvas, BorderLayout.CENTER );
        //jframe.revalidate();
        //jframe.repaint();

        jframe.setLayout(new FlowLayout());

        JButton startButton = new JButton("Start");
        startButton.addActionListener(
            new ActionListener()
            {
                @Override
                public void actionPerformed(ActionEvent e)
                {
                    /* --- I NEED TO ADD THE ContentPane HERE, BUT IF I DO THIS THE REPAINT DOESN'T WORK --- */
                    jframe.getContentPane().add( glcanvas, BorderLayout.CENTER );
                    jframe.revalidate();
                    jframe.repaint();

                        /* -- I added this because I was told elsewhere that repainting
                         *    in a different thread would make it work, however I haven't
                         *    been successful in getting this to work. Included for information
                         */
                    //repaintThread(jframe);

            }
            });
        jframe.add(startButton);

}

private static void repaintThread(final JFrame jframe)
    {
    Thread thread = new Thread(new Runnable()
    {
        public void run()
        {
            for( int i = 0; i < 200; i++)
            {
                jframe.revalidate();
                jframe.repaint();


                    try
                    {
                        Thread.currentThread().sleep( 50 );
                    }
                    catch( Exception ex )
                    {
                        break;
                    }
            }
        }
    });

    thread.setPriority(Thread.NORM_PRIORITY);
    thread.start();
}

}

最佳答案

这是使一切混乱的行:

jframe.setLayout(new FlowLayout());


您要将布局更改为FlowLayout,然后在glcanvas旁边添加startButtonglcanvas的首选大小为0,因此尽管单击按钮时您可以看到startButton的轻微移动,但它不可见。

我认为设置FlowLayout不是故意的,因为您正在使用BorderLayout.CENTER约束来添加glcanvas。所以这是一个简单的解决方法:

注释掉:

//jframe.setLayout(new FlowLayout());


startButton添加到面板的NORTH而不是CENTER,因为glcanvas将转到CENTER。更改:

jframe.add(startButton);


至:

jframe.add(startButton, BorderLayout.NORTH);


这至少在Windows 7 Java 7上解决了重新验证问题。

另外,有关布局的更多详细信息和示例,请参见A Visual Guide to Layout Managers

关于java - revalidate()/repaint()在ActionListener中不起作用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23554726/

10-12 04:39