Открытие PDF-файла, хранящегося в папке ресурсов, вызывает исключение - PullRequest
0 голосов
/ 05 июля 2019

Я написал программу, в которой PDF-файл должен быть открыт для события Action (вы можете посмотреть мой код ниже).

menuElementHilfe.addActionListener(new ActionListener() {   
    public void actionPerformed(ActionEvent arg0) {
        File hilfe = new File ("src\\resources\\Hilfe.pdf");
        try {
            java.awt.Desktop.getDesktop().open(hilfe);
        } catch (IOException e) {
            e.printStackTrace();
        }       
    }   
});

Если я запускаю программу через Eclipse, все работает, но после экспорта в качестве исполняемого фляги я получаю следующее исключение:

Исключение в потоке "AWT-EventQueue-0" java.lang.IllegalArgumentException: файл: src \ resources \ Hilfe.pdf не существует.

Любая обратная связь приветствуется

Ответы [ 2 ]

0 голосов
/ 05 июля 2019

Ресурс может быть упакован в jar приложения, следовательно, Файл (файл физического диска) невозможен.Скопируйте его во временный файл, чтобы его мог открыть рабочий стол.

menuElementHilfe.addActionListener(evt -> {   
    Path tmp = Files.createTempFile("hilfe-", ".pdf");
    Files.copy(getClass().getResourceAsStream("/Hilfe.pdf"), tmp);
    try {
        Desktop.getDesktop().open(tmp.toFile());
        tmp.toFile().deleteOnExit();
    } catch (IOException e) {
        e.printStackTrace();
    }       
});

Другое отличие - косая черта, и путь к ней чувствителен к регистру, а не к файлу Windows.


После проблем

menuElementHilfe.addActionListener(evt ->
        SwingUtilities.invokeLater(() -> {
            Path tmp = Files.createTempFile("hilfe-", ".pdf");
            Logger.getLogger(getClass().getName()).log(Level.INFO, "actionPerformed "
                    + tmp + "; event: " + evt);
            Files.copy(getClass().getResourceAsStream("/resources/Hilfe.pdf"), tmp);
            try {
                Desktop.getDesktop().open(tmp.toFile());
                //tmp.toFile().deleteOnExit();
            } catch (IOException e) {
                Logger.getLogger(getClass().getName()).log(Level.WARN, "Error with " + tmp,
                        e);
            }       
        }));
  • Я не удалил, поэтому доступ Desktop может жить дольше, чем в Java-приложении.
  • Я сделал invokeLater, чтобы на actionPerformed не было замороженного графического интерфейса.
  • Я добавил ведение журнала, чтобы видеть каждый вызов actionPerformed
0 голосов
/ 05 июля 2019

Проблема в том, как вы получаете ресурсы. попробуйте это:

menuElementHilfe.addActionListener(new ActionListener() {   
    public void actionPerformed(ActionEvent arg0) {
    File hilfe = new File(getClass().getResource("/resources/Hilfe.pdf").getFile());
        try {
        java.awt.Desktop.getDesktop().open(hilfe);
        } catch (IOException e) {
            e.printStackTrace();
        }       
    }   
});

При работе в Eclipse вы нацеливаетесь на файл в вашем пути сборки. При запуске из JAR / WAR, URL отличается и выглядит как "jar: file: /your-path/your-jar.jar! /Hilfe.pdf" , который вы не задаете при вызове new Файл (...) Таким образом, чтобы получить правильный URL для внутренних ресурсов, вы должны использовать такие методы, как getResource или getResourceAsStream, в зависимости от ваших потребностей.

Проверьте следующие пояснения для получения дополнительной информации :) https://docs.oracle.com/javase/8/docs/technotes/guides/lang/resources.html

[EDIT]

Я предполагаю, что вы работаете над некоторым приложением Swing, но я не знаю, знаете ли вы, что выполнение таких задач в потоке AWT-EventQueue заморозит ваш пользовательский интерфейс. Чтобы предотвратить это, вы должны запускать вещи, не связанные с пользовательским интерфейсом, в другом потоке.

Это сделано с использованием метода SwingUtilities.invokeLater (Java 5 и более ранних версий) и / или класса SwingWorker (начиная с Java 6).

как указано в этом ответе

Вы должны поместить предыдущее решение в нечто вроде этого:

 SwingUtilities.invokeLater(new Runnable() {
    public void run() {
       // Your UI unrelated code here
    }
 });
...