2014-10-05 29 views
5

我如何将OpenGl显示器附加到JFrame上,以便在关闭JFrame时销毁显示器?这是我到目前为止的代码:如何将opengl显示附加到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并修复上面的错误?

回答

0

看起来你在“main”线程(它给主线程当前的OpenGL上下文)启动了Display,但是你试图从另一个线程中销毁显示,在这种情况下是Event调度线程(EDT)。然而,只有一个线程可以在给定的时间拥有当前的OpenGL上下文。

尽管可以更改哪个线程具有当前上下文,但我不认为这就是您想要在此处执行的操作。

然后我们要做的就是销毁与我们创建它相同的线程(当前OpenGL上下文的线程)上的显示。我见过的是使用在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进行测试,因为这似乎是该问题最初发布时提供的最新版本。