JavaFX Freeze on Desktop.open(файл), Desktop.browse(uri)

Я запускаю некоторый код на Java в Ubuntu 12.04 LTS 64 Bit (с Gnome Shell), используя Oracle JDK 1.8.0_05 через NetBeans8.0.

Следующая функция отлично работает при вызове либо в Main, либо в другом пустом Java-проекте, однако при вызове из любого приложения JavaFX она приводит к зависанию окна и прекращению ответа (хотя проект полностью соответствует требованиям), требуя принудительного закрытия.

Может ли кто-нибудь предложить какие-либо проблемы с тем, что я написал, что может вызвать проблему или цикл?

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

Любые предложения с благодарностью принимаются, спасибо заранее.

   public static void desktopTest(){

            Desktop de = Desktop.getDesktop();

            try {
                de.browse(new URI("http://stackoverflow.com"));
            }
            catch (IOException | URISyntaxException e) {
                System.out.println(e);
            }

            try {
                de.open(new File("/home/aaa/file.ext"));
            }
            catch (IOException e){
                System.out.println(e);
            }
            try {
                de.mail(new URI("mailto:[email protected]"));
            }
            catch (URISyntaxException | IOException e){
                System.out.println(e);
            }
}

person Wren    schedule 19.04.2014    source источник


Ответы (5)


У меня также была такая же проблема, и это решение работает для меня:

if( Desktop.isDesktopSupported() )
{
    new Thread(() -> {
           try {
               Desktop.getDesktop().browse( new URI( "http://..." ) );
           } catch (IOException | URISyntaxException e1) {
               e1.printStackTrace();
           }
       }).start();
}
person Alex K    schedule 23.12.2015
comment
Важная часть здесь Desktop.isDesktopSupported(). Кажется, происходит какая-то инициализация. Без этого не работает. Эти ответы должны быть помечены как принятый ответ. - person ST-DDT; 06.09.2016
comment
Что заставило меня работать, так это создание новой темы - это кажется необходимым. - person Josh Larson; 11.02.2017
comment
Кажется, Desktop.open() имеет ту же проблему и решение. Спасибо, Алекс :). - person jamie; 06.05.2017

Я решил проблему с...

 public static void abrirArquivo(File arquivo) {
    if (arquivo != null) {
        if (arquivo.exists()) {
            OpenFile openFile = new OpenFile(arquivo);
            Thread threadOpenFile = new Thread(openFile);
            threadOpenFile.start();
        }
    }
}

private static class OpenFile implements Runnable {

    private File arquivo;

    public OpenFile(File arquivo) {
        this.arquivo = arquivo;
    }

    private void abrirArquivo(File arquivo) throws IOException {

        if (arquivo != null) {
            java.awt.Desktop.getDesktop().open(arquivo);
        }

    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        try {
            abrirArquivo(arquivo);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}
person Douglas    schedule 11.06.2015

У меня тоже такая же проблема. Я обнаружил, что если я вызову метод Desktop.open() из нового потока, файл откроется после закрытия окна приложения JavaFX, но это мало помогает.

Если вы положите

SwingUtilities.invokeLater(() -> System.out.println("Hello world"));

в ваш основной метод после вызова launch(args), он также не будет вызываться до тех пор, пока вы не закроете приложение JavaFX.

Похоже, что между приложением JavaFX и Swing существует какая-то проблема параллелизма.

В Ubuntu вы можете попробовать

xdg-open filename

из вашего приложения JavaFX.

Насколько я могу судить, ваш код должен работать.

person user3577819    schedule 27.04.2014
comment
Спасибо за это, приятно знать, что я не схожу с ума - я знаю о xdg-open, и он отлично работает, но я использую Java только для обеспечения легкой кросс-платформенной работы... лицо на данный момент - могу я спросить, в какой среде вы работаете? Спасибо! - person Wren; 02.05.2014

В JavaFX есть новый способ справиться с этим. Единственный недостаток, который я вижу, заключается в том, что вам нужно создать экземпляр HostServicesDelegate с помощью синглтона Application.

HostServicesDelegate hostServices = HostServicesFactory.getInstance(appInstance);
hostServices.showDocument("http://www.google.com");
person Gabriel Féron    schedule 13.08.2014
comment
Использование com.sun API, таких как com.sun.deploy.uitoolkit.impl.fx.HostServicesFactory, не рекомендуется, так как не гарантируется их доступность в будущих версиях JavaFX. Вместо этого используйте общедоступный Application::getHostServices() API. - person jewelsea; 23.06.2015

Инкапсулируйте его в системный поток:

    final String url = "www.google.com";
    final Hyperlink hyperlink = new Hyperlink("Click me");
        hyperlink.setOnAction(event -> new Thread(() -> {
            try {
                Desktop.getDesktop().browse(new URI(url));
            } catch (IOException | URISyntaxException e1) {
                e1.printStackTrace();
            }
        }).start());
person Pascual Lorente Arencibia    schedule 23.06.2015
comment
Можете ли вы предоставить дополнительные пояснения? Что вызывает проблему? Почему это решение работает? - person Jon Surrell; 23.06.2015
comment
Я уверен, что поток JavaFX блокируется с помощью Destktop.getDesktop().browse(), но я не знаю причины. Поток JavaFX следует использовать только для коротких задач, связанных с представлением (включить/отключить кнопки, добавить элементы в списки, изменить вкладки). Инкапсуляция команды browse в системный поток позволит потоку JavaFX продолжать обновлять представление приложения, в то время как другой поток может свободно открывать браузер, не прерывая графический интерфейс. (Извините за столь поздний ответ) - person Pascual Lorente Arencibia; 24.07.2015