Adding heavyweight components on top of AWTGLCanvas (Doesn't work on Mac)

Started by kps, December 02, 2010, 12:10:05

Previous topic - Next topic

kps

Hi all :)

LWJGL is a brilliant library. Thanks for working on it.

My goal is to display a Swing JTextField on top of a AWTGLCanvas. I am aware that Swing and heavyweight components don't mix nicely on Java 1.5 so I thought I could fix that by showing a heavyweight Panel on top of the AWTGLCanvas and adding the JTextField to that heavyweight Panel.

It works on Windows (Java 1.5& 1.6) and Linux 1.6 (Not tested 1.5).

However, it doesn't work on Mac.

I have put together some test code which demonstrates this issue.

Is this a known issue? Heavyweight components cannot be placed on top of a AWTGLCanvas on Mac?

Thanks for any information regarding this.
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Panel;

import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.AWTGLCanvas;
import org.lwjgl.opengl.GL11;

public class Test {

    public static void main(final String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                final JFrame frame = new JFrame();

                final Component canvas = createAWTGLCanvas();
                final Component panel = createHeavyWeightPanel();

                final Container contentPane = new Container() {

                    @Override
                    public void doLayout() {
                        canvas.setBounds(0, 0, 2 * getWidth() / 3, 2 * getHeight() / 3);
                        panel.setBounds(getWidth() / 3, getHeight() / 3, 2 * getWidth() / 3, 2 * getHeight() / 3);
                    }
                };

                contentPane.add(panel);
                contentPane.add(canvas);

                contentPane.setComponentZOrder(canvas, 0);
                contentPane.setComponentZOrder(panel, 1);

                contentPane.setPreferredSize(new Dimension(640, 480));
                frame.setContentPane(contentPane);
                frame.pack();
                frame.setVisible(true);
            }
        });
    }

    private static Component createHeavyWeightPanel() {
        final JTextField textField = new JTextField();

        final Panel heavyWeightPanel = new Panel() {

            @Override
            public void doLayout() {
                final int p = 20;
                textField.setBounds(p, p, getWidth() - 2 * p, getHeight() - 2 * p);
            }
        };
        heavyWeightPanel.add(textField);
        heavyWeightPanel.setBackground(Color.RED);
        return heavyWeightPanel;
    }

    private static Component createAWTGLCanvas() {
        try {
            return new AWTGLCanvas() {

                @Override
                protected void paintGL() {
                    GL11.glClearColor((float) Math.random(), (float) Math.random(), (float) Math.random(), 1.0f);
                    GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
                    try {
                        swapBuffers();
                    } catch (final LWJGLException e) {}
                }
            };
        } catch (final LWJGLException e) {
            throw new IllegalStateException();
        }
    }
}



Matthias

When you need a text field just use TWL :) It's much easier to use then trying to mix non GL widgets on a GL canvas.

kps

Quote from: Matthias on December 02, 2010, 12:27:15
When you need a text field just use TWL :) It's much easier to use then trying to mix non GL widgets on a GL canvas.

Yeah I agree that the mixing isn't ideal. I just tried the TWL webstart demo. Unfortunately its text field widget doesn't seem to handle international input (Chinese etc) as well as JTextField does. This is somthing we really need for the product I'm working on.

Matthias

It does - you only need to generate a bitmap font (using the TWL Theme editor) which has Chinese characters in it. The demo uses a font which only has basic Latin-1 and some Greek and Russian characters.

kps

Quote from: Matthias on December 02, 2010, 12:45:26
It does - you only need to generate a bitmap font (using the TWL Theme editor) which has Chinese characters in it. The demo uses a font which only has basic Latin-1 and some Greek and Russian characters.

When entering Japanese text into the JTextField, the text is added to the JTextField as you type.

When doing the same into a TWL text field, a floating black text box appears and the text is entered in that text box instead of the TWL text field. The text is added to the TWL one when you press return.

I'm not entirely sure but I think this could be fixed in the TWL library by using Java's InputMethod API (http://download.oracle.com/javase/1.5.0/docs/guide/imf/api-reference.html).

Matthias

LWJGL's Display/Keyboard class don't use AWT for input handling. SO not sure what is causing this box to appear but I'm sure it would be very complicated to use AWT input methods together with LWJGL's Keyboard class.

You could always use an AWTGLCanvas and use these AWT input classes to provide the keyboard events to TWL. Look at the de.matthiasmann.twl.input.Input interface.

It is also possible to not use a polling based input approach by not using GUI.update but by calling it's methods separately.