JOGL холст в JavaFX - PullRequest
       23

JOGL холст в JavaFX

0 голосов
/ 09 октября 2018

У меня проблемы с получением JOGL canvas / panel в сцене JavaFX.Я предположил, что если JOGL GLCanvas придерживается контракта для awt.Canvas, не должно быть проблем с его размещением в сцене JFX.

Я собрал следующий код (все фрагменты находятся внутри JFX Application :: start).

Первое создание JOGL "Привет, мир" (пульсирующий фон, чтобы увидеть, как все движется и движется):

GLCanvas glCanvas = new GLCanvas();
glCanvas.setSize(size-10, size-10);
glCanvas.addGLEventListener(new GLEventListener() {
    private final long t0 = System.currentTimeMillis();
    @Override
    public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {}
    @Override
    public void init(GLAutoDrawable drawable) {
        new Thread(() -> {while (true) glCanvas.display();}).start();
    }
    @Override
    public void dispose(GLAutoDrawable drawable) {}
    @Override
    public void display(GLAutoDrawable drawable) {
        GL4 gl = drawable.getGL().getGL4();
        float t = (float)(Math.sin((System.currentTimeMillis()-t0)/1000f)+1)/2f;
        gl.glClearColor(t, 1-t, 0, 1);
        gl.glClear(GL4.GL_COLOR_BUFFER_BIT);
    }
});

GLJPanel glPanel = new GLJPanel();
glPanel.add(glCanvas);
glPanel.setBackground(Color.BLUE);

Альтернативный привет, мир (не двигаясь, это явно работает):

Canvas awtCanvas = new Canvas() {
    @Override
    public void paint(Graphics g) {g.fillRect(0, 0, getWidth(), getHeight());}
};
awtCanvas.setSize(size-10, size-10);

JPanel swingPanel = new JPanel();
swingPanel.add(awtCanvas);
swingPanel.setBackground(Color.BLUE);

И тестовый код, объединяющий вещи:

if (jfx) {
    SwingNode swingNode = new SwingNode();
    swingNode.setContent(swingPanel);
    primaryStage.setScene(new Scene(new Group(swingNode), size, size+30));
    primaryStage.show();
} else {
    JFrame frame = new JFrame();
    frame.setSize(size, size+30);
    frame.add(swingPanel);
    frame.setVisible(true);
}

Эталонные решения JFrame (Panel (Canvas ())) , JFrame (JPanel (GLCanvas)())) и JFrame (GLJPanel (GLCanvas ())) работает должным образом (вроде как, GLPanel , похоже, игнорирует настройку цвета фона).

Когда я пытаюсь использовать не-JOGL оболочку Stage (Scene (Group (JPanel (Canvas ()))) * , работает должным образом (работает JFX).

Теперь для JOGL, оболочка Stage (Scene (Group (JPanel (GLJPanel (GLCanvas ())))) создает черный цвет там, где должно быть содержимое холста. Wrapper Stage (Scene (Group (JPanel (GLCanvas ()))) * (пропуская использование GLJPanel) не будет производить черный квадрат для содержимого холста, а я получаю только синий квадрат для JPanel.

Единственные упоминанияВ интернете я обнаружил, что в 2012/2013 гг. Кажется, что это не работает (но, похоже, SwingNode не существовал в то время), а также в 2016 г. на форумах JOGL, которые ссылаются на неработающую ссылку в bugzzila.

1 Ответ

0 голосов
/ 11 октября 2018

Из чистого отчаяния попытался использовать GLJPanel вместо GLCanvas, и это работает.Вроде.

Существует проблема с изменением размера SwingNode - в нем есть ошибка, которая не позволяет легко изменить размер ( OracleJDK имеет ошибку в течение достаточно долгого времени, OpenJDK кажетсячтобы решить эту проблему)

Предлагаемое решение проблемы изменения размера - поместить слушатель свойства width / height в Scene и повторно вставлять холст при каждом изменении размера:

Dimension dim = new Dimension((int)scene.getWidth(), (int)scene.getHeight());
ChangeListener<Number> stageSizeListener = (obs, prev, next) -> {
    dim.setSize(scene.getWidth(), scene.getHeight());
    component.setSize(dim);
    swingNode.setContent(swingPanel);
};
scene.heightProperty().addListener(stageSizeListener);
scene.widthProperty().addListener(stageSizeListener);

Это работает с кодом ввопрос, но каждый триггер повторной вставки dispose (GL) и init (GL) цикл, который может быть в порядке для некоторых приложений, не в моем случае.

Решилсделайте небольшой хак, сделав размер GLJPanel максимально допустимым разрешением (скажем, 4K, я все равно рендерину в буфер вне экрана), рендеринг в желаемом разрешении, перетащите результат в верхний левый угол панели и обрежьте панельв сцене JFX с тем же разрешением.

Как уже упоминалось tomsontom , производительность не совсем велика, GLJPanel намного медленнее, чем GLCanvas сам по себе (от 800FPS до 40FPS при 4K), а в SwingNode становится еще хуже (17FPS при 4K).Отложит использование JFX, насколько это возможно, и, надеюсь, они либо исправят SwingNode в предстоящем отделении от JDK, либо даже получат DirectRenderingNode .

...