Here’s a simple example of the problem. I use a JSplitPane in this example. I think it’s pretty clear that the Animator threads, or maybe the GLCanvas’es, are competing for some resource. When two Animator threads are created, then either a deadlock will occur, or one of the threads starve and nothing gets rendered in that panel.
One interesting observation… If you don’t create an Animator for the GLCanvas, and then if you play around with the JSplitPane to force the two panes to repaint, then they both repaint without any trouble. I’ve tried adding a thread that continuously calls repaint() on the panels, but that doesn’t work.
import net.java.games.jogl.*;
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import javax.swing.*;
import javax.swing.event.*;
public class Main extends javax.swing.JFrame {
private JMenuBar menubar;
private JMenu fileMenu;
private JMenuItem fileExit;
private JPanel leftPanel, rightPanel;
private JSplitPane splitPane;
private TestPanel panel1, panel2;
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
public void run() {
new Main().setVisible(true);
}
});
}
public Main() {
// This call ensures that the JMenuBar will render over the GLCanvas.
JPopupMenu.setDefaultLightWeightPopupEnabled(false);
// Create components.
splitPane = new JSplitPane();
leftPanel = new JPanel();
rightPanel = new JPanel();
menubar = new JMenuBar();
fileMenu = new JMenu();
fileExit = new JMenuItem();
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
leftPanel.setLayout(new BorderLayout());
leftPanel.setPreferredSize(new Dimension(400, 600));
splitPane.setLeftComponent(leftPanel);
rightPanel.setLayout(new BorderLayout());
splitPane.setRightComponent(rightPanel);
getContentPane().add(splitPane, BorderLayout.CENTER);
fileMenu.setText("File");
fileExit.setText("Exit");
fileExit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
fileExitActionPerformed(evt);
}
});
fileMenu.add(fileExit);
menubar.add(fileMenu);
setJMenuBar(menubar);
panel1 = new TestPanel();
panel2 = new TestPanel();
leftPanel.add(panel1, BorderLayout.CENTER);
rightPanel.add(panel2, BorderLayout.CENTER);
pack();
setSize(800, 600);
// Start the animation on panel 1.
panel1.start();
/******************************************************
// When we attempt to start the animation on panel 2, the
// program will either lock up or the program will run but
// panel2 won't render. It's clear that the two animator
// threads are competing for some resource, causing a
// deadlock or causing the second thread to starve.
******************************************************/
panel2.start();
}
private void fileExitActionPerformed(ActionEvent evt) {
System.exit(0);
}
public class TestPanel extends JPanel {
GLCanvas canvas;
Animator animator;
public TestPanel() {
// The JPanel must use the Border layout manager.
setLayout(new java.awt.BorderLayout());
// Create the GLCanvas.
canvas = GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities());
canvas.addGLEventListener(new TestRenderer());
// Create an animator thread for the canvas.
animator = new Animator(canvas);
// Add the canvas to the center of the JPanel.
add(canvas);
// We need to create a Dimension object for the JPanel minimum size to fix a GLCanvas resize bug.
// The GLCanvas normally won't recieve resize events that shrink a JPanel controled by a JSplitPane.
setMinimumSize(new Dimension());
}
public void start(){
animator.start();
}
public void stop(){
animator.stop();
}
class TestRenderer implements GLEventListener {
private GL gl;
private GLDrawable gldrawable;
float angle = 0;
public void init(GLDrawable drawable) {
gl = drawable.getGL();
this.gldrawable = drawable;
}
public void reshape(GLDrawable drawable, int x, int y, int width, int height) {
gl. glViewport(0, 0, width, height);
}
public void display(GLDrawable drawable) {
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
gl.glRotatef(angle, 0f, 0f, 1f);
angle += 2;
gl.glBegin(GL.GL_POLYGON);
gl.glVertex2f(-0.5f, -0.5f);
gl.glVertex2f(-0.5f, 0.5f);
gl.glVertex2f(0.5f, 0.5f);
gl.glVertex2f(0.5f, -0.5f);
gl.glEnd();
}
public void displayChanged(GLDrawable drawable, boolean modeChanged, boolean deviceChanged) {}
}
}
}