【问题标题】:How to attach opengl display to a JFrame and dispose of it properly?如何将 opengl 显示附加到 JFrame 并正确处理它?
【发布时间】:2014-10-05 04:07:30
【问题描述】:

如何将 OpenGL 显示附加到 JFrame,这样当我关闭 JFrame 时会破坏显示?到目前为止,这是我的代码:

package test.core;


import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;

import static org.lwjgl.opengl.GL11.*;

public class Main {



    private static CreateCanvas canvas;
    private static CreateFrame frame;

    private static int width = 800;
    private static int height = 600;

    public static void main(String[] args) throws InterruptedException {
        startFrames();

        startDisplay();

    }

    public static void cleanUp() {
        Display.destroy();
    }

    private static void startDisplay() {
        try
        {
            Display.setParent(canvas);
            Display.create();
        }catch(LWJGLException ex)
        {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    private static void startFrames()
    {
        Runnable r = new Runnable(){
            @Override
            public void run(){
                frame = new CreateFrame();
                JButton button = new JButton("BUTTON");
                canvas = new CreateCanvas();
                JPanel panel = frame.panel;

                panel.add(canvas);
                panel.add(button);
                frame.add(panel);

                canvas.setSize(300, 300);
                frame.setSize(width, height);

                frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

                WindowListener listen = new WindowAdapter(){
                    @Override
                    public void windowClosing(WindowEvent we){
                        int result = JOptionPane.showConfirmDialog(frame, "Do you want to quit the Application?");
                        if(result == JOptionPane.OK_OPTION){
                            frame.setVisible(false);
                            cleanUp();
                            frame.dispose();
                        }
                    }
                };

                frame.addWindowListener(listen);


                frame.setVisible(true);
            }

        };
        SwingUtilities.invokeLater(r);
    }

}

在执行可运行文件之前,我已将 opengl 显示附加到 JFrame。但是在添加可运行文件后,显示器现在显示的尺寸与我的屏幕尺寸相同。我已经尝试重新排列

canvas.setSize();

frame.setSize();

但没有任何改变,opengl 显示仍然是相同的大小,当我尝试先关闭 JFrame 而不是先关闭显示时,我收到此错误:

Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: From thread Thread[AWT-EventQueue-0,6,main]: Thread[main,5,main] already has the context current

它指向我的

Display.destroy();

我猜是哪个告诉我我没有正确处理显示器?谁能帮我将opengl显示附加到JFrame并修复上面的错误?

【问题讨论】:

    标签: java swing opengl jframe lwjgl


    【解决方案1】:

    您似乎在“主”线程中启动了显示(它为主线程提供了当前的 OpenGL 上下文),但您试图从另一个线程(在本例中为事件调度)销毁显示线程 (EDT)。 但是,在给定时间,只有一个线程可以拥有当前的 OpenGL 上下文。

    虽然可以更改哪个线程具有当前上下文,但我认为这不是你想要做的。

    然后我们要做的是在我们创建它的同一线程(具有当前 OpenGL 上下文的线程)上销毁显示。我见过的approach 是使用在EDT 上运行的CanvasaddNotify() 和removeNotify() 方法来设置一个标志,该标志在OpenGL 线程上检查以确定何时销毁显示器。

    另外,问题提到了设置显示大小的问题。由于 setSize() 和 LayoutManager 的工作方式,您的 JFrame 显示大小和显示大小未设置为您想要的。有关详细信息,请参阅Java tutorials 和文档。在以下示例中,我使用了一种方法来解决此问题。

    因此,这里有一个示例,试图与问题中发布的代码的意图保持一致:

    import java.awt.BorderLayout;
    import java.awt.Canvas;
    import java.awt.Dimension;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JOptionPane;
    import javax.swing.JPanel;
    
    import org.lwjgl.LWJGLException;
    import org.lwjgl.opengl.Display;
    import org.lwjgl.opengl.DisplayMode;
    
    public class LWJGLTester {
    
        private volatile boolean isRunning = false;
    
        /*
         * The question asker seemed to desire that the JFrame be 800x600 and
         * that the Display be 300x300.  Regardless of the desired sizes,
         * I think the important thing is to set the Canvas and Display to the same sizes.
         */
        private int frameWidth = 800;
        private int frameHeight = 600;
        private int displayWidth = 300;
        private int displayHeight = 300;
    
        private Thread glThread;
    
        public static void main(String[] args) {
            new LWJGLTester().runTester();
        }
    
        private void runTester() {
            final JFrame frame = new JFrame("LWJGL in Swing");
            frame.setSize(frameWidth, frameHeight);
            frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
            frame.addWindowListener(new WindowAdapter() {
                @Override
                public void windowClosing(WindowEvent we){
                    int result = JOptionPane.showConfirmDialog(frame, "Do you want to quit the Application?");
                    if(result == JOptionPane.OK_OPTION){
                        frame.setVisible(false);
                        frame.dispose(); //canvas's removeNotify() will be called
                    }
                }
            });
    
            JPanel mainPanel = new JPanel(new BorderLayout());
    
            JButton button = new JButton("BUTTON");
            JPanel buttonPanel = new JPanel();
            buttonPanel.add(button);
            mainPanel.add(buttonPanel, BorderLayout.NORTH);
    
            Canvas canvas = new Canvas() {
                @Override
                public void addNotify() {
                    super.addNotify();
                    startGL();
                }
    
                @Override
                public void removeNotify() {
                    stopGL();
                    super.removeNotify();
                }
            };
            canvas.setPreferredSize(new Dimension(displayWidth, displayHeight));
            canvas.setIgnoreRepaint(true);
    
            try {
                Display.setParent(canvas);
            } catch (LWJGLException e) {
                //handle exception
                e.printStackTrace();
            }
            JPanel canvasPanel = new JPanel();
            canvasPanel.add(canvas);
            mainPanel.add(canvasPanel, BorderLayout.SOUTH);
    
            frame.getContentPane().add(mainPanel);
    
            //frame.pack();
            frame.setVisible(true);
        }
    
        private void startGL() {
            glThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    isRunning = true;
                    try {
                        Display.setDisplayMode(new DisplayMode(displayWidth, displayHeight));
                        Display.create();
                    } catch (LWJGLException e) {
                        //handle exception
                        e.printStackTrace();
                    }
    
                    // init OpenGL here
    
                    while(isRunning) {
                        // render OpenGL here
                        Display.update();
                    }
    
                    Display.destroy();
                }
            }, "LWJGL Thread");
    
            glThread.start();
        }
    
        private void stopGL() {
            isRunning = false;
            try {
                glThread.join();
            } catch (InterruptedException e) {
                //handle exception
                e.printStackTrace();
            }
        }
    
    }
    

    注意:此示例已使用 lwjgl 版本 2.9.1 进行测试,因为这似乎是问题最初发布时可用的最新版本。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-02
      • 2014-02-17
      • 2014-12-24
      • 1970-01-01
      相关资源
      最近更新 更多