2014-05-09 25 views
0

我想添加一個OpenGL上下文到jFrame。重新驗證()/ repaint()在ActionListener中不工作

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(); 
} 

} 
+0

'setVisible(true);'應該是最後一個。 – BitNinja

+0

是的,我知道,但爲了測試,我想先讓框架可見,然後添加更多內容。在我的程序中,我必須首先使框架可見,才能顯示添加OpenGL上下文所需的按鈕。 – Francis

+2

1)爲了更快地獲得更好的幫助,請發佈[MCVE](http://stackoverflow.com/help/mcve)(最小完整和可驗證示例)。 2)對於一個空間中的許多組件,請使用['CardLayout'](http://docs.oracle.com/javase/7/docs/api/java/awt/CardLayout.html),如[簡單示例](http://stackoverflow.com/a/5786005/418556)。 –

回答

1

這是打亂了一切行:

jframe.setLayout(new FlowLayout()); 

你改變佈局FlowLayout和然後在startButton旁添加glcanvasglcanvas的首選大小爲0,因此它不可見,但單擊該按鈕時可以看到startButton的輕微移動。

我認爲設置FlowLayout不是故意的,因爲您正在使用BorderLayout.CENTER約束來添加glcanvas。因此,這裏是一個簡單的解決方法:

註釋掉:

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

添加startButton到面板,而不是CENTERNORTH因爲glcanvas會去CENTER。變化:

jframe.add(startButton); 

到:

jframe.add(startButton, BorderLayout.NORTH); 

那固定的再驗證的問題,至少在Windows 7上的Java 7

另外,請參閱A Visual Guide to Layout Managers有關佈局的更多細節和例子。

+1

好的答案......他應該像我們在大多數示例中那樣使用動畫師。 – gouessej

+1

謝謝,這確實可以解決問題。 – Francis

+0

@ user3378157我很高興它幫助:) – tenorsax