2014-10-05 38 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進行測試,因爲這似乎是該問題最初發布時提供的最新版本。