Mit Jogl auf einem JPanel zeichen

Hausgeist

Grünschnabel
Hallo Leute!

Das ist mein erster Beitrag also erstmal ein freundliches hallo an alle :)

Also ich habe folgende Frage:
Ich habe ein Programm gemacht, welches das Mandelbrot-Fraktal auf ein JPanel zeichnet, was auch wunderbar funktioniert. Nur ist das ganze ziemlich langsam und ich wollte das mit JOGL beschleunigen. Zu Testzwecken habe ich zunächst erstmal versucht, ein rotes Rechteck auf das Panel zu zeichnen. Leider sehe ich aber nur die weiße Hintergrundfarbe.

Gedacht ist das ganze so:
Ich leite mir eine eigene Panelklasse von JPanel ab, die den GLEventListener implementiert. Diese abgeleitete Klasse wird dann dem Hauptfenster hinzugefügt.

Hier ist noch der Code:

Code:
//MandelPanel.java

import javax.swing.*;
import java.awt.*;
import javax.media.opengl.*;
import javax.media.opengl.glu.*;

/**
 * Konstruktor
 */
public class MandelPanel extends JPanel implements GLEventListener{
	static final long serialVersionUID = 2;
	
	private GL gl;
	//private GLU glu;
	
	/**
	 * Initialisiert OpenGL
	 * @param arg
	 */
	public void init(GLAutoDrawable arg){
		System.out.println("Initialisiere OpenGL...");
		gl = arg.getGL();
		//glu = new GLU();
		
		gl.glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
		
		gl.glMatrixMode(GL.GL_PROJECTION);
		gl.glOrtho(0, 1024, 0, 768, -10, 10);
		
		gl.glMatrixMode(GL.GL_MODELVIEW);
	}
	
	public void reshape(GLAutoDrawable arg0, int arg1, int arg2, int arg3, int arg4){
		
	}
	
	/**
	 * Wird aufgerufen, wenn die Auflösung geändert wird
	 */
	public void displayChanged(GLAutoDrawable arg0, boolean arg1, boolean arg2){
		
	}

	/**
	 * Methode, in der Gerendert wird
	 */
	public void display(GLAutoDrawable arg0){
		System.out.println("Zeichne...");

		gl.glClear(GL.GL_COLOR_BUFFER_BIT);
		
		gl.glColor3f(1.0f, 0.0f, 0.0f);
	        gl.glRectf(0.0f, 0.0f, 500.0f, 500.0f);
	}
	
	/**
	 * Standardkonstruktor
	 */
	MandelPanel(){
		super();
		this.setLayout(null);
	}
	
}

Code:
//MandelWindow.java

public class MandelWindow extends JFrame implements ActionListener, WindowListener{
	static final long serialVersionUID = 2;
	
	private Container cp = this.getContentPane();
	private MandelPanel pGraphic = new MandelPanel();
	private GLCapabilities glcaps = new GLCapabilities();
        
        private GLCanvas canvas = new GLCanvas(glcaps);
    
    
	/**
	 *Implementierung von WindowListener und ActionListener 
	 */
	public void windowClosing(WindowEvent e){ System.exit(0); } 
	public void windowClosed(WindowEvent e){ /*Empty*/ } 
	public void windowDeiconified(WindowEvent e){ /*Empty*/ } 
	public void windowIconified(WindowEvent e){ /*Empty*/ } 
	public void windowActivated(WindowEvent e){ /*Empty*/ } 
	public void windowDeactivated(WindowEvent e){ /*Empty*/ } 
	public void windowOpened(WindowEvent e){ /*Empty*/ }
	
	public void actionPerformed(ActionEvent e){
	
	}
	
	/**
	 * Konstruktor
	 */
	MandelWindow(){
		super("Mandelbrot");
		this.setLayout(null);
		this.setResizable(false);
		this.setSize(new Dimension(1152,864));
		Init();
	}
	
	/**
	 * Initialisierung aller Komponenten des Fensters
	 */
	private void Init(){
		cp.add(pGraphic);
		pGraphic.setBounds(5, 5, 1024, 768);
		pGraphic.setBackground(new Color(255,255,255));
		cp.add(canvas);
		canvas.addGLEventListener(pGraphic);
		
	}
}

Code:
//MandelApplication.java

public class MandelApplication {

	/**
	 * Programmstartpunkt
	 * @param args
	 */
	public static void main(String[] args) {
		MandelWindow w1 = new MandelWindow();
		w1.setVisible(true);
	}

}

So das wäre es glaub ich. Etwas auskommentierten Code hab ich entfernt. Also der geht gar nicht in die Methoden init und display rein. Da scheint wohl irgendwas mit dem EventListener noch nicht zu stimmen. In einer Version, in der ich das Rechteck direkt auf dem Frame zeichne ohne das Panel geht alles wunderbar.

Also wenn jemand eine Idee hätte, wäre das super :)

MfG Der Hausgeist
 
Also da es immer noch keine Antwort gibt, will ich mal meine momentane Lösung vorstellen und hoffe, dass diese jemand anderen mit einem ähnlichen Problem helfen kann.

Dazu habe ich etwas "schummeln" müssen. Ich leite mein Bildfeld nämlich von einem JInternalFrame ab und lasse es wie ein Panel aussehen. Also nützlich hat sich auch noch ein kleines Tutorial erwiesen, das es hier gibt:
http://de.wikibooks.org/wiki/Java_Standard:_OpenGL

Code:
import javax.swing.*;
import java.awt.*;
import javax.media.opengl.*;

public class ImprovedMandelPanel extends JInternalFrame {
	
	private static final long serialVersionUID = 1L;
	
	public GLCanvas canvas;
	...
        ...
	...
	
	public ImprovedMandelPanel(){
		GLCapabilities glcap = new GLCapabilities();
		canvas = new GLCanvas(glcap);
		canvas.addGLEventListener(new SceneView());
		this.getContentPane().add(canvas);
		...
		...
		...
		this.setVisible(true);
		
		InitColorTable();
		Calculate();
	}
	
	public class SceneView implements GLEventListener {
		public void init(GLAutoDrawable arg0) {
			System.out.println("Initialisiere OpenGL...");
			GL gl = arg0.getGL();
	  
			gl.glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
	                  
			gl.glMatrixMode(GL.GL_PROJECTION);
			gl.glOrtho(0, 1024, 0, 768, -1, 1);
	  
			gl.glMatrixMode(GL.GL_MODELVIEW);
	    }

	    public void display(GLAutoDrawable arg0) {
	    	System.out.println("Zeichne...");
	    	GL gl = arg0.getGL();
	        float tmp = 1;
	        
	    	gl.glClear(GL.GL_COLOR_BUFFER_BIT);
	    	
	    	gl.glBegin(GL.GL_POINTS);
	    		for(int i=0;i<screenY;i++){		//für alle Zeilen
					for(int j=0;j<screenX;j++){	//für alle Spalte
						tmp = fractal[i][j];
						gl.glColor3f(tmp, tmp, tmp);
						gl.glVertex3f((float)j, (float)i, 0);
					}
				}
			gl.glEnd();
			
	    }

	    public void reshape(GLAutoDrawable arg0, int arg1, int arg2, int arg3, int arg4) {
	    }

	    public void displayChanged(GLAutoDrawable arg0, boolean arg1, boolean arg2) {	
	    }
	}
	
	/**
	 * Fraktalberechnung
	 */
	
	private void Calculate(){
		...
		...
		
	}
	
	private int Iterate(int aktScreenX, int aktScreenY){
                ...
                ...
		return iteration;
	}
	
	
	private float CalculateColor(int iter){
		...
                ...
		return col;
	}
	
	public void InitColorTable(){
		...
	}
	
}

Das Feld fractal[][] speichert die Farbwerte zu jedem Pixel des Bildes momentan noch in Graustufen.

Wird jetzt diese Klasse im Hauptfenster eingebunden wird tatsächlich etwas gezeichnet :)

Code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.basic.*;


public class MandelWindow extends JFrame implements ActionListener, WindowListener, ContainerListener{
	static final long serialVersionUID = 2;
	
	private Container cp = this.getContentPane();
	private ImprovedMandelPanel pGraphicIm = new ImprovedMandelPanel();
    
	/**
	 *Implementierung von WindowListener und ActionListener 
	 */
	public void windowClosing(WindowEvent e){ System.exit(0); } 
	public void windowClosed(WindowEvent e){ /*Empty*/ } 
	public void windowDeiconified(WindowEvent e){ /*Empty*/ } 
	public void windowIconified(WindowEvent e){ /*Empty*/ } 
	public void windowActivated(WindowEvent e){ /*Empty*/ } 
	public void windowDeactivated(WindowEvent e){ /*Empty*/ } 
	public void windowOpened(WindowEvent e){ /*Empty*/ }
	public void componentAdded(ContainerEvent arg0) { /*Empty*/ }
	public void componentRemoved(ContainerEvent arg0) { /*Empty*/ }
	
	/**
	 * Ereignissteuerung des Fensters
	 */
	public void actionPerformed(ActionEvent e){
		/**
		 * TODO Ereignissteuerung des Fensters Implementieren
		 */
	}
	
	/**
	 * Konstruktor
	 */
	MandelWindow(){
		super("Mandelbrot");
		this.setLayout(null);
		this.setResizable(false);
		this.setSize(new Dimension(1152,864));
		Init();
	}
	
	/**
	 * Initialisierung aller Komponenten des Fensters
	 */
	private void Init(){
		cp.add(this.pGraphicIm);
		this.pGraphicIm.setBounds(5, 5, 1024, 768);
		this.pGraphicIm.setBackground(new Color(255,255,255));
		((BasicInternalFrameUI) pGraphicIm.getUI()).setNorthPane(null);
		this.pGraphicIm.setBorder(null);
	}
}

Die Zeile ((BasicInternalFrameUI) pGraphicIm.getUI()).setNorthPane(null); lässt die Titelleiste des JInternalFrame verschwinden und sorgt dafür, dass selbiges nicht mehr verschoben werden kann. Dazu muss allerdings javax.swing.plaf.basic.* importiert werden.
Schließlich schalte ich in der letzten Zeile noch den Rahmen aus.
 
Zurück