LINUX.ORG.RU

Закрытие приложения Swing+JavaFX

 , ,


0

1

Привет! Столкнулся с такой проблемой.

Есть приложение, написано на JavaFX, но при этом есть кусок Swing-а, которое прикручено через SwingNode. Exit сделан так:

Platform.exit()
Т.е закрывается только FX треды всякие, а свинг продолжает жить, что логично - он же в EDT вроде как. В связи с этим вопрос, а как мне Правильно закрывать этот самый SwingNode? В самом SwingNode у меня лежит GLJPanel. Про вариант
System.exit(0)
знаю. Есть какой-нибудь способ другой? Знаю, что можно поставить
node.setDefaultCloseOperation(WindowClosingProtocol.WindowClosingMode.DISPOSE_ON_CLOSE);
Но это не помогает, все равно при закрытии приложения что-то висит в фоне. Прошу совета, так как сам не слишком разбираюсь в том, как с Swing правильно работать) Заранее спасибо за советы.

Есть какой-нибудь способ другой?

А для чего? Отловить событие выключение ты можешь и так.

Deleted ()
Ответ на: комментарий от cdshines

Это я читал, получаю я список Frame, которые активны, делаю для них dispose и все также висит.

Frame.getFrames.foreach(frame => frame.dispose())

Все равно у меня висит что-то после закрытия.

ЗЫ: После делаю снова

Frame.getFrames.foreach(println)
и тот же фрейм мне и отображается.

aarexer ()
Последнее исправление: aarexer (всего исправлений: 1)
Ответ на: комментарий от Deleted

Ну мне кажется закрывать System.exit - это не круто, хочется, чтобы все закрывалось как надо, а не обрывалось из-за того, что у меня рантайм выдернули..

aarexer ()
Ответ на: комментарий от Deleted

Т.е ты считаешь, что делать при закрытии System.exit(0) - это правильно?

aarexer ()
Ответ на: комментарий от Deleted

Хм, звучит убедительно.. Но вот я не пойму, а если я в файл пишу что-то в это время?Или у меня в фоне идет что-то, то по System.exit я вообще зашкварю свои файлы и файлы пользователя. А надо бы, чтобы все аккуратно чистилось.. Да и насколько я прочитал пока - все советуют использовать DISPOSE_ON_CLOSE, а он уже другую работу делает..

С другой стороны на такой случай надо addShutdownHook вешать...

aarexer ()
Последнее исправление: aarexer (всего исправлений: 1)
Ответ на: комментарий от cdshines

Чувак, а ты куда пропал? Как ты обычно закрываешь Swing?

aarexer ()
Ответ на: комментарий от aarexer

а если я в файл пишу что-то в это время?Или у меня в фоне идет что-то, то по System.exit я вообще зашкварю

Если ты все сам знаешь, пиши как тебе посоветовали выше.

Deleted ()
Ответ на: комментарий от Deleted

Дак я не знаю, я предполагаю. Я прошу совета, почему ты воспринимаешь так в штыки мои слова? Я тебе благодарен за твой совет, но высказал предположение про файлы, мне важно любое мнение.

aarexer ()
Последнее исправление: aarexer (всего исправлений: 1)
Ответ на: комментарий от aarexer

предположение

Предположение должно на чем-то основываться, не?

Deleted ()
Ответ на: комментарий от Deleted

Чуваааак, ну давай не будем вступать в битву титанов, тем более я не титан, я просто тебя спросил, что если я пишу в файл и делаю System.exit - то я теряю файл, как быть, вот и все.

aarexer ()
Ответ на: комментарий от aarexer

если я пишу в файл и делаю System.exit - то я теряю файл,

А я тебя спросил с чего ты это взял.

Deleted ()
Ответ на: комментарий от Deleted

О, вот это норм диалог уже! Ну как с чего, вроде как при System.exit я теряю рантайм, не закрывается ничего «по-правильному». По-крайней мере я так думал всегда, если я ошибаюсь - поправьте меня, буду благодарен.

aarexer ()
Ответ на: комментарий от znenyegvkby

Чувак, я это уже написал выше, не надо кидать маны не дочитав до конца дискуссию.

aarexer ()
Ответ на: комментарий от aarexer

Где, о чем ты писал? Я прочел все от корки до корки. Ты сказал

я просто тебя спросил, что если я пишу в файл и делаю System.exit - то я теряю файл, как быть, вот и все.

После этого опять сказал в этом же духе

Ну как с чего, вроде как при System.exit я теряю рантайм, не закрывается ничего «по-правильному».

Я тебя и отправил к shutdown-hooks. А как ты хотел? System.exit самый правильный метод завершения. Клиент может вызывать его в программе где захочет и когда захочет. А если ты сам не можешь уберечь свою программу от того чтобы «правильно закрывать что-то там» перед остановкой VM, тогда тебе и следует читать маны. Я что-то упустил? :)

znenyegvkby ()
Ответ на: комментарий от aarexer

Сделай тред-дамп послед того, как думаешь, что у тебя все закрыто. Если сам не осилишь, скинь сюда.

cdshines ★★★★ ()
Ответ на: комментарий от aarexer

И? Вы и там сначала согласились, но сразу же продолжаете

Но вот я не пойму, а если я в файл пишу что-то в это время?Или у меня в фоне идет что-то, то по System.exit я вообще зашкварю свои файлы и файлы пользователя.

Откуда вы это взяли-то?

Чет все за System.exit сегодня)

А у вас есть альтернативы? Все что вы используете из этих ваших фреймворков это не более чем еще один уровень абстракции над System.exit. Не все ли равно? Я не пишу гуйню, поэтому конкретно за swing не могу вам ничего сказать, но я думаю что вы так-же можете в этих ваших JFrame юзать внутренние классы наследуюясь от Thread (или как там сейчас в гуйне модно?) и в run уже завершать свое приложение как вам будет угодно. Можете перед его завершением даже письмо жене отправить что домой из офиса не вернетесь :)
Поэтому еще раз

Или у меня в фоне идет что-то, то по System.exit я вообще зашкварю свои файлы и файлы пользователя.

Почему вы что-либо зашкварить-то хотите? Или вы целенаправленно пытаетесь это сделать? :)

znenyegvkby ()
Ответ на: комментарий от znenyegvkby

Вы прочитайте до конца то. Я согласился с тем, что это рабочий вариант - но у меня остался вопрос, я его задал, откуда я взял вопрос?из головы.В моем понимании, если я пишу в файл что-то и в этот момент идет System.exit - я часть данных теряю.

Опять же повторюсь - если я не выставил addShutdownHook.

То, что вы пишите про уровни абстракции - это да, верно, но каждая обертка - она не просто обертка, она что-то добавляет, завершая что-то(может даже что-то свое, свинговое или fx-овое).

Зачем компьютер выключать, если можно штепсель выдернуть из розетки?Все в итоге сводится то к выключению.

ЗЫ: Тем более, я снова повторюсь, я не знаток Swing и FX, поэтому хочу спросить как надо делать. Потому что как можно(как будет работать) - вариантов то много можно напилить.

aarexer ()
Последнее исправление: aarexer (всего исправлений: 1)
Ответ на: комментарий от aarexer

Я не возвращался к комменту по новой, а прочел вашу переписку уже с час назад. Вы добавили к нему изменение, а я раньше прочел без приписки

С другой стороны на такой случай надо addShutdownHook вешать...

поэтому и отправил на man :)

То, что вы пишите про уровни абстракции - это да, верно, но каждая обертка - она не просто обертка, она что-то добавляет, завершая что-то(может даже что-то свое, свинговое или fx-овое).

Конечно, а я и не рекомендую использовать вам System.exit вместо DISPOSE_ON_CLOSE/EXIT_ON_CLOSE/etc. Если вы пишите в определенных рамках то нужно соблюдать «хороший тон», это подразумевается.

znenyegvkby ()
Ответ на: комментарий от znenyegvkby

Да мы про man уже забыли) Так вот я и не понимаю, как мне завершить верно мое приложение, поэтому и ищу совета. Завтра выложу threaddump

aarexer ()

Простите, а какой у Вас полный код?

У меня вот такой код (а упростил свой пример, выкинув все лишнее) работает корректно.

import javafx.application.*; 
import javafx.event.*; 
import javafx.stage.*; 
import javafx.scene.*;
import javafx.scene.layout.*;
import javax.swing.*;
import javafx.embed.swing.*;
import java.awt.event.*;

public class SwingFx8 extends Application {

         private JButton b = new JButton("Exit");

         @Override
         public void start(Stage stage) {
             final SwingNode swingNode = new SwingNode();
             createAndSetSwingContent(swingNode);
             StackPane pane = new StackPane();
             pane.getChildren().add(swingNode);
             stage.setScene(new Scene(pane, 300, 100));
             stage.setTitle("Swing exit test");
             stage.show();
         }

         private void createAndSetSwingContent(final SwingNode swingNode) {
             b.addActionListener(e -> System.exit(0)); 
             SwingUtilities.invokeLater(() -> {swingNode.setContent(b); });
         }
 
         public static void main(String[] args) {
             launch(args);
         }
}
Bioreactor ★★★★★ ()
Последнее исправление: Bioreactor (всего исправлений: 1)
Ответ на: комментарий от Bioreactor

У меня там большая простыня, сюда код и не скинешь..Дамп выложил выше, после завершения.

aarexer ()
Ответ на: комментарий от Bioreactor

Когда я делаю System.exit - у меня тоже все нормально:)Я же писал об этом выше) Проблема в том, что я не уверен, что так выходить из приложения - правильно.

aarexer ()
Ответ на: комментарий от aarexer

Не знаю, как там AWT работает, но ты говоришь, что у тебя AWT-треды закрываются, а в дампе они висят.

cdshines ★★★★ ()
Ответ на: комментарий от cdshines

Ну да, именно что и висят. А как их закрывать? Делаю dispose явно на все Frames, но все равно висит все. Помогает только System.exit.

aarexer ()
Ответ на: комментарий от Bioreactor

Спасибо за фидбек! А если у меня, например, есть процесс в это время, например, система акторов или процесс пишет что-нибудь. Тогда делая System.exit - я обрываю его. Логичный ответ - надо завершать все, а потом делать exit. Но! Например, такой код на выход(утрировано)

akkaSystem.close()
System.exit(0)

Пока у меня акторы будут завершаться я уже рантайм убью. Как мне быть точно уверенным, что у меня все закончилось уже?Вопрос.

aarexer ()

А простейший тест у тебя работает?

package t;


import javafx.application.Application;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.embed.swing.SwingNode;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class FxAndSwing extends Application {

    private JFrame frame;

    @Override
    public void start(Stage stage) {
        final SwingNode swingNode = new SwingNode();
        createAndSetSwingContent(swingNode);

        StackPane pane = new StackPane();
        pane.getChildren().add(swingNode);


        stage.setOnCloseRequest(new EventHandler<WindowEvent>() {
            @Override
            public void handle(WindowEvent event) {
                frame.dispose();
            }
        });



        stage.setScene(new Scene(pane, 100, 50));
        stage.show();
    }

    private void createAndSetSwingContent(final SwingNode swingNode) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                final JButton button = new JButton("Click me!");
                addFrameShowListener(button);
                swingNode.setContent(button);
            }
        });
    }

    private void addFrameShowListener(JButton jButton) {
        if (frame != null) {
            return;
        }

        createFrame();

        jButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                frame.setVisible(true);
            }
        });
    }

    private void createFrame() {
        frame = new JFrame("Our JButton listener example");
        frame.getContentPane().setLayout(new FlowLayout());
        frame.add(new JButton("Frame button"));

        frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        frame.setPreferredSize(new Dimension(300, 200));
        frame.pack();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

anonymous ()
Ответ на: комментарий от anonymous

Так, у тебя же не просто Swing, а JOGL, там отдельная головная боль.

Про эту animator.stop() не забыл?

http://stackoverflow.com/questions/3094195/gracefully-shutting-down-a-java-op...

import java.awt.Frame;
import com.sun.opengl.util.Animator;

// ...

frame.addWindowListener(new WindowAdapter() {
        public void windowClosing(WindowEvent e) {
            exit();
        }
        });

// ...

public static void exit(){
    animator.stop();
    frame.dispose();
    // System.exit(0); // это есть на SO, но, ясен пень, лишнее
}
anonymous ()
Ответ на: комментарий от anonymous

И еще кое-что. Ребята из libgdx пару лет назад говорили о проблемах с многопоточностью, поэтому тоже выходили по System.exit(0). Не знаю, поправили они это или нет, но с JOGL проблема явно была и, может быть, есть.

Если ничего не помогает, то вместо простого System.exit(0); принудительно, своими функциями, заверши сохраниения и т.п., и потом с чистой совестью жестко exit-ь. Сама Java от этого не поломается, а твое приложение в твоих руках.

anonymous ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.