質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
JavaFX

JavaFXとは、Java仮想マシン上で動作するリッチインターネットアプリケーション (RIA) のGUIライブラリです。Swingとは異なり、FXMLと呼ばれる XMLとCSSを併用してデザインを記述します。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

5回答

10147閲覧

Eclipse上で実行した時と、実行可能JARで実行した時の違いについて

serona

総合スコア25

JavaFX

JavaFXとは、Java仮想マシン上で動作するリッチインターネットアプリケーション (RIA) のGUIライブラリです。Swingとは異なり、FXMLと呼ばれる XMLとCSSを併用してデザインを記述します。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2017/06/28 07:07

編集2017/07/04 06:12

###前提・実現したいこと
Macのパソコンで、Eclipseを使ってJavaの開発を行っています。

Eclipse上で実行するときと、
実行可能JARファイル(生成されるJARに必須ライブラリーをパッケージ)としてエクスポートし、
ダブルクリックで実行する時の動作が異なります。

できれば、Eclipse上で実行しているときと全く同じように
実行可能JARファイルでもアプリケーションを動かしたいのですが
そのためにどうすればいいのか分からない状況です。

あと、Macのターミナルから、「java -jar ○○.jar」で実行した時と
直接JARファイルをダブルクリックして実行したときも、また動作が違うようです。
「java -jar ○○.jar」で実行すれば、MainFormのところに書いた件以外は
Eclipseで実行していたときと同じように動きます。

症状については以下の通りです。
WebEngine(WebView?)の動作に差があるようなので、それをなんとかしたいのですが
何か原因や、解決策にお心当たりはないでしょうか…
拙い文章で申し訳ありませんが、アドバイス頂けますと幸いです><

###MainForm
ここの、
<content><fx:include fx:id="childTest1" source="application/Test1Form.fxml" /></content>
について、
Eclipseで実行する時は、「source="Test1Form.fxml"」 でないと「java.lang.reflect.InvocationTargetException」が発生して起動できないのに、
実行可能JARとして出力した時は、下記のように「application/」がついていないと起動できません。

今のところ、この症状については、実行可能JARとしてエクスポートする際に
「application/」を追記することで解決はしています。

Xml

1<?xml version="1.0" encoding="UTF-8"?> 2 3<?import javafx.scene.paint.*?> 4<?import javafx.scene.text.*?> 5<?import javafx.geometry.*?> 6<?import javafx.scene.*?> 7<?import javafx.scene.control.*?> 8<?import javafx.scene.web.*?> 9<?import java.lang.*?> 10<?import javafx.scene.layout.*?> 11<?import javafx.scene.layout.BorderPane?> 12 13<BorderPane focusTraversable="true" xmlns="http://javafx.com/javafx/8" 14 xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.MainController"> 15 <center> 16 <AnchorPane focusTraversable="true" prefHeight="600.0" 17 prefWidth="600.0" BorderPane.alignment="CENTER"> 18 <children> 19 <TabPane layoutY="75.0" prefHeight="525.0" prefWidth="600.0" 20 tabClosingPolicy="UNAVAILABLE" AnchorPane.bottomAnchor="0.0" 21 AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" 22 AnchorPane.topAnchor="75.0"> 23 <tabs> 24 <Tab fx:id="tabMain" text="テスト1"> 25 <content> 26 <fx:include fx:id="childTest1" source="application/Test1Form.fxml" /> 27 </content> 28 </Tab> 29 <Tab fx:id="tabSkip" text="テスト2"> 30 <content> 31 <fx:include fx:id="childTest2" source="application/Test2Form.fxml" /> 32 33

###MainController
結構略しています… getElementsByClassName("☆")の☆部分には、どちらも同じクラス名が入っています

WebView(webviewTest)、ProgressIndicator(progressTest)、Label(lblTest)があるとして、
Workerが、Worker.State.SUCCEEDEDになったら、progressTestを非表示にする、というようにしたいのですが
Eclipseで実行した時と、実行可能JARファイルとしてエクスポート後に実行した時とで、WebEngineの動作が違うらしく
実行可能JARとして実行すると、Workerがほぼ全く「SUCCEEDED」になりません。(SCHEDULEDかRUNNINGになっているようです)
これを何とか、Eclipseで実行していたときと同じような動作にしたいのです。

Java

1webEngine = webviewTest.getEngine(); 2 3webEngine.getLoadWorker().stateProperty() 4 .addListener(new javafx.beans.value.ChangeListener<Worker.State>() { 5 @Override 6 public void changed(ObservableValue<? extends State> observable, State oldValue, State newValue) { 7 if (webEngine.getLoadWorker().getState().equals(State.SUCCEEDED)) { 8 progressTest.setVisible(false); 9 if (webEngine.getLocation().equals("http://○○○○")) { 10 if ((boolean) webEngine.executeScript( 11 "( document.getElementsByClassName(\"☆\").item(0) != null );")) { 12 String testUrl = (String) webEngine.executeScript( 13 "var $el = document.getElementsByClassName(\"☆\"); $el[0].href;"); 14 lblTest.setText(testUrl); 15 } 16 } 17 } else { 18 progressTest.setVisible(true); 19 } 20 }); 21

##追記
調べてみたところ、どうやら、
起動の仕方?によってWebEngineのUserAgentが違っているようです。
webEngine.getUserAgent();を出力したところ、

Eclipseから起動した時は、

Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/538.19 (KHTML, like Gecko) JavaFX/8.0 Safari/538.19

実行可能JARとしてエクスポートして、ダブルクリックで起動した時は

Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/602.1 (KHTML, like Gecko) JavaFX/8.0 Safari/602.1

となっている事に気が付きました!!
これも何か関係あるのかな、と思っています。

webEngine.setUserAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/538.19 (KHTML, like Gecko) JavaFX/8.0 Safari/538.19")

こちらを記述して書き換えてみても、状況は変わらないようですが…
解決は難しいのでしょうか…?><
自分でも調べながら気長に待っておりますので、どなたかご回答頂けるとうれしいです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答5

0

実行可能JARとして出力した時は、下記のように「application/」がついていないと起動できません。

これについて自分なりに確認してみましたが。fx:includeのパスを相対(ドキュメントベース相対)としたとき、状況によって書き換えるようなことは必要ありませんでした。
確認ですがfxmlをロードする際のURLの指定はgetResource()により指定されているでしょうか?自分はそうしています。

java

1// cbissue.MyApp.java 2package cbissue; 3...import省略... 4public class MyApp extends Application { 5 public void start(Stage stage) throws Exception { 6 Parent root = FXMLLoader.load(getClass().getResource("Main.fxml")); 7 stage.setScene(new Scene(root)); 8 ... 9 } 10}

Main.fxml(MyAppと同一パッケージにおいてあります。Sub.fxmlも同様です)

xml

1<?xml version="1.0" encoding="UTF-8"?> 2...import省略... 3 4<VBox prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.60" 5 xmlns:fx="http://javafx.com/fxml/1" fx:controller="cbissue.MainController"> 6 <children> 7 <Button ... /> 8 <fx:include fx:id="sub" source="Sub.fxml" /> 9 </children> 10</VBox>

実行可能JARとして実行すると、Workerがほぼ全く「SUCCEEDED」になりません。

WebEngineへのloadの引数が相対URLになっていて、実行環境によるドキュメントベース/コードベースの違いが原因でロードに失敗しているのだと思います。ロードに失敗するとWorkerの状態はFAILEDで終わります。

実行環境によるコードベース・ドキュメントベースの違いについてはHostServiceのリファレンスに以下の記載があります。

HostService

public final String getCodeBase()

このアプリケーションのコード・ベースURIを取得します。アプリケーションがJNLPファイルを介して起動された場合、このメソッドはJNLPファイルで指定されているコードベース・パラメータを返します。アプリケーションがスタンドアロン・モードで起動された場合、このメソッドはアプリケーションのjarファイルが含まれるディレクトリを返します。アプリケーションがjarファイルにパッケージ化されていない場合、このメソッドは空の文字列を返します。

public final String getDocumentBase()

このアプリケーションのドキュメント・ベースURIを取得します。アプリケーションがブラウザに埋め込まれている場合、このメソッドはアプリケーションを含むWebページのURIを返します。アプリケーションがwebstartモードで起動された場合、このメソッドはJNLPファイルで指定されているコードベース・パラメータを返します(ドキュメント・ベースおよびコード・ベースはこのモードでは同じです)。アプリケーションがスタンドアロン・モードで起動された場合、このメソッドは現在のディレクトリのURIを返します。


追記:指摘し忘れていましたが、ロードが成功しても失敗してもダイアログは閉じるべきだと思います。上の回答に書いた「ドキュメントベースやコードベース」の話とは別に、Workerの状態がSUCCEEDEDあるはFAILEDになった時点で閉じるようにすればよいでしょう。


JDK 1.8.0_131

投稿2017/07/01 05:08

編集2017/07/03 01:39
KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

serona

2017/07/03 05:49

ご回答ありがとうございます!!いつもお世話になっていますm(._.)m まず、fxmlをロードする際については、 public class Main extends Application {  @Override  public void start(Stage primaryStage) {  BorderPane root = (BorderPane) FXMLLoader.load(getClass().getResource("Test1Form.fxml"));  Scene scene = new Scene(root, 800, 600);  primaryStage.setScene(scene);  primaryStage.show();  …  } } このように書いていました。 KSwordOfHasteさんが書いてくださったものと 同じ形式に直して書いてみましたが、症状に変化はありませんでした… (fxmlの、source="application/….fxml"から「application/」を削除し、  @Overrideの削除、throws Exceptionの追記、  BorderPane root = (BorderPane) FXMLLoader.load(getClass().getResource("Test1Form.fxml"));  の部分を  Parent root = FXMLLoader.load(getClass().getResource("Test1Form.fxml"));  に修正して、実行可能JARとしてエクスポートし、起動を試しましたが、直ぐに終了してしまいます) また、WebEngineへのloadの引数が相対URLになっているため失敗している、とのことですが URLの一部を定数にして  final static String TEST_URL = "https://…/";  …  webEngine.load(TEST_URL + "2017/07/01/"); というような感じで書いていました。 webEngine.loadの引数は、全く外部のWebサイトのURLなのですが ここの書き方に原因があるのでしょうか…? HostServiceのリファレンスの内容については まだちょっと理解できていないので、もう少し読み込んで調べてみます。 重ね重ね、質問ばかりで申し訳ないのですが 追記の、ロードが成功しても失敗してもダイアログは閉じるべき、というお話について お教え頂いたように修正したいと思うのですが、 ダイアログというのは、なにを指しているのでしょうか? すみませんが、お手隙の際に、またご回答頂けるとうれしいです;; 何卒よろしくお願いします。
KSwordOfHaste

2017/07/03 06:19

> まず、fxmlをロードする際については...このように書いていました。 いたって素直な書き方をされているのでなぜ動かないのか自分にはわからないです。スミマセン><。何か自分が知らない要因があるような気がします。 > ダイアログというのは、なにを指しているのでしょうか? 失礼、私の方がぼけていたようです。とりあえず忘れてください。あらためて伺いたいのですが、RUNNINGのままになっているのは確実でしょうか?FAILEDで失敗もせずRUNNINGのままですか?
KSwordOfHaste

2017/07/03 06:59

もう1点気づきました。 > FXMLLoader.load(getClass().getResource("Test1Form.fxml")); としていますが、Test1Form.fxmlはメインのFXMLファイルからincludeしているファイルなのでMainクラスからloadしているのは別のFXMLファイルなのでは?
serona

2017/07/03 09:03

ご返信ありがとうございます!何度もすみません;; まず、ご指摘頂いた  FXMLLoader.load(getClass().getResource("Test1Form.fxml")); この部分ですが、これは私の記入ミスでした… 実際のコードでは、「Test1Form.fxml」ではなく「MainForm.fxml」と書いています。 大変失礼しました(;;) fxmlのロードの件については、了承しました。 とんでもないです!一緒に考えていただき、ありがとうございます。 これについては、自分で引き続き調べてみます! また、Worker.Stateについて、 webEngine.getLoadWorker().stateProperty().addListener(new javafx.beans.value.ChangeListener<Worker.State>() {  @Override  public void changed(ObservableValue<? extends State> observable, State oldValue, State newValue) {  ※※※  …  } }); この、※※※の部分に、newValue.toString()を記録するようなコードを書いて検証していますが 「RUNNING」と記入された後は、10分以上放置してもそれ以降更新がありません。 「FAILED」が記入されることもないので、失敗もしていないのかなと思います。 try catch文で、エラーが発生した場合も記録するようにしましたが 特にエラーが発生しているわけでもないようで…。 ちなみにですが、WebViewに実際に表示されているWebページは、 数秒後には読み込み終わっているように見えます(というか、普通に表示されているので多分終わってます…)。 読み込みが終わらない、というよりは 読み込みが終わっても「SUCCEEDED」や「FAILED」にならない、という症状なのかな?と思いました。 Worker.Stateの確認のタイミングが間違っているのでしょうか…? 以上、恐れ入りますが、よろしくお願いします。m(TT)m
KSwordOfHaste

2017/07/03 09:36

> Worker.Stateの確認のタイミングが間違っているのでしょうか…? 間違っているとは思えないのですが、自分はWebアプリに詳しいとはとても言えないのではっきりとは言えません。
KSwordOfHaste

2017/07/03 09:50

一つ言い忘れてました。自分のテストコードではロード時のChangeListener内でDOMアクセスはしていませんので、そこに条件の違いがあるといえばあるかも知れません。とはいえ、あまり関係しそうな気がしないのですが。
guest

0

eclipseのウィンドウ>設定>Java>インストール済のJRE

投稿2017/07/07 04:11

kurokoba

総合スコア276

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

serona

2017/07/07 04:16

度々ご回答ありがとうございます!短文でしたので、まとめてのコメント返信で失礼しますm(._.)m ターミナルの「java -version」で表示される件、 環境変数なのかなと思ってはいたのですが、やはり、そういうことなんですね… eclipseのJREの設定方法については、存じております! ただ、そこに設定するための最新のバージョン(1.8.0_131)のjavaのディレクトリがわからなかったので、 これについては改めて、調べてみようと思います! ありがとうございました!
guest

0

ターミナルの"java -version"で表示されるバージョンは環境変数から見るのに対し、eclipseのjavaのバージョンはeclipseで設定したディレクトリのjavaを参照します。

投稿2017/07/07 04:06

kurokoba

総合スコア276

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kurokoba

2017/07/07 04:14

すみません、コメントに入力したつもりが新に回答立ててしまいました...。申し訳ない。
serona

2017/07/07 04:19

いえいえ!!とんでもないです!ありがとうございます(*^^*)
guest

0

JavaFX詳しくないのですが、stateの比較ってコールバックで渡ってくるもの使わなくて良いのでしょうか?

Java

1//× 2 if (webEngine.getLoadWorker().getState().equals(State.SUCCEEDED)) { 3//〇 ちなみにenum比較は==が良いと思う 4if (newValue==State.SUCCEEDED) {

投稿2017/06/29 05:04

kurokoba

総合スコア276

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KSwordOfHaste

2017/07/01 05:12

webEngineのloadWorkerプロパティーの実体が状況に応じて変化する場合はkurokobaさんの推測が当たりだと思い実際にやってみました。その結果JDK8のWebViewのエンジンではloadWorkerはずっと同じインスタンスのまま変化しないようです。一般的にはkurokobaさんがおっしゃるようにChangeListenerのnewValueを参照したほうが簡便であると思いますが、本件に関しては質問者さんのコードであっても動作上は同じになるようです。
serona

2017/07/03 05:47

ご回答ありがとうございます!返信が遅くなってしまいすみません>< 仰る通りですね…!! 動作自体は以前と変わらずで、問題の解決には繋がらなかったのですが こちらのほうがコードとして良いので、教えて頂いたように修正しました。 ご指摘感謝です!!(*´∀`*)
guest

0

自己解決

完全に解決はしていませんが、原因がわかりました!
調べてみたところ、eclipse上、あるいはターミナルから「java -jar」のコマンドで起動した場合は
javaのバージョンが「1.8.0_111」となっているのに対し、
ダブルクリックで起動した場合は「1.8.0_131」となっていました!!
恐らくは、このjavaのバージョンの違いが、webViewなどの動作に影響しているんだと思います。

……ただ、既に1.8.0_131はインストールしており、javaコントロールパネルでは
最新のバージョン(Java8 Update131)がインストールされています、と表示されるのに対し
ターミナルから「java -version」と入力すると、「java version "1.8.0_111"」となります。
これは一体何なんでしょうか…(;・ω・)?

最新のバージョンに合わせて作成した方がいいのかな、とも思うのですが
探してみても131がどのディレクトリにあるのか分からず、eclipseで設定できない><
現在の仕様のまま、1.8.0_111で起動させるとしても
このアプリを使用するパソコン全てに、111のjavaがインストールされていないとだめだろうし…
何とか解決方法を調べてみますが、また分からなくなったらお世話になります…(TT)

一先ず、ご回答下さったKSwordOfHasteさん、kurokobaさん、ありがとうございました!

投稿2017/07/07 04:01

serona

総合スコア25

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kurokoba

2017/07/07 04:16

すみません、間違って回答として書いちゃったので重複しますが再掲。 ターミナルの"java -version"で表示されるバージョンは環境変数から見るのに対し、eclipseのjavaのバージョンはeclipseで設定したディレクトリのjavaを参照します。 eclipseのウィンドウ>設定>Java>インストール済のJRE
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問