「*[JavaFX]」の検索結果を表示しています
2014-10-12 09:28

Try to build OpenJFX

Since I take this OpenJFX for Embedded Devices [CON3307] session at JavaOne2014, I wanted to try to build OpenJFX. The session was about Building the OpenJFX embedded stack for Linux desktop,but I use Mac at first.
Building the OpenJFX embedded stack for Linux desktop - OpenJFX - OpenJDK Wiki
Thanks to this article, it is not difficult to build openjfx.Building OpenJFX - OpenJFX - OpenJDK Wiki

Environments

Prerequisites

f:id:tomoTaka:20141011114156p:image

f:id:tomoTaka:20141011114606p:image
I installed Gradle by using GVM before, but it's version is 1.12.But because Gradle 1.8 is required, I installed Gradle 1.8.(F.Y.R seeGVM by gvmtool)

gvm install gradle 1.8

I did not know about QT at that time, then downloaded the latest version 5.3.Qt Project
f:id:tomoTaka:20141012073354p:image
After trying qmake command, the below error occurred.
f:id:tomoTaka:20141012075030p:image
Amending the first line of qdevice.pri file(macosx10.8 ->macosx10.9) to resolve this error.
f:id:tomoTaka:20141012075539p:image

Building OpenJFX

f:id:tomoTaka:20141012080125p:image

Making the openjfx folder, because I wanted to clone the source file in the openjfx folder.

mkdir openjfx
cd openjfx
hg clone http://hg.openjdk.java.net/openjfx/8u-dev/rt
cd rt
gralde tasks

It is takes time to execute tasks command for the first time.
f:id:tomoTaka:20141012082726p:image
f:id:tomoTaka:20141012082743p:image

gradle clean
gradle projects

f:id:tomoTaka:20141012083131p:image

gradle --profile

The error occurred.
f:id:tomoTaka:20141012085326p:image
Thanks to the article, the profile command worked.
Building OpenJFX on Mac OS X 10.9.2 / XCode 5.1 / XCode 4.3.3

sudo ln -s /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk

To check the html file under build/reports/profile directory.
f:id:tomoTaka:20141012085851p:image:w360

gradle

The build succeeded!

gradle base:test

The test succeeded.
To check the html file under modules/base/build/reports/tests directory.
f:id:tomoTaka:20141012091631p:image:w360
Anyway I am sooooooo happy to see how to build openJFX! ;-)

OpenJFXのビルドを試してみる

JavaOne2014で、OpenJFX for Embedded Devices [CON3307]のセッションを受けてちょっとOpenJFXのビルドを試してみました。2014-10-02 - tomoTakaの日記
セッションでは、embedded に関するお話だったのですが、とりあえずMacで挑戦してみました。Building the OpenJFX embedded stack for Linux desktop - OpenJFX - OpenJDK Wiki
基本的にすべてBuilding OpenJFX - OpenJFX - OpenJDK Wikiに書いています。

環境の確認(準備)

f:id:tomoTaka:20141011114156p:image

f:id:tomoTaka:20141011114606p:image
Gradleは以前にGVMを使ってインストール2014-05-02 - tomoTakaの日記してVersionが1.12だったので1.8を再度インストールしました。GVMはGVM by gvmtoolを参照。

gvm install gradle 1.8

QTQt Projectはいままで知らなかったです。とりあえず最新の5.3をdownload
f:id:tomoTaka:20141012073354p:image
ちょっと試してみると以下のエラーが発生
f:id:tomoTaka:20141012075030p:image
以下のファイルのバージョンが1.8になっていたので1.9に修正。
f:id:tomoTaka:20141012075539p:image

手順

以下の1行を追加
f:id:tomoTaka:20141012080125p:image

任意のフォルダを作成しsourceをclone

mkdir openjfx
cd openjfx
hg clone http://hg.openjdk.java.net/openjfx/8u-dev/rt

ここにも書いているようにtaskを確認。cloneすると「rt」フォルダが作成されているので「rt」に移動してからgraldeのコマンドを実施
(1回目はここで「rt」フォルダに移動しないでtaskコマンドがうまくいかなくて困っていました^^;;)

cd rt
gralde tasks

cloneして初めてtasksを実行すると少し時間がかかって無事成功
f:id:tomoTaka:20141012082726p:image
同じコマンドtasksを再度実行すると実行可能なコマンド一覧が表示
f:id:tomoTaka:20141012082743p:image

gradle clean
gradle projects

f:id:tomoTaka:20141012083131p:image

gradle --profile

エラー発生
f:id:tomoTaka:20141012085326p:image
Building OpenJFX on Mac OS X 10.9.2 / XCode 5.1 / XCode 4.3.3 を参考にして以下のコマンドを実行

sudo ln -s /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk

無事成功!「build/reports/profile」配下に作成されているhtmlファイルを確認
f:id:tomoTaka:20141012085851p:image:w360

gradle

成功!

gradle base:test

成功!「modules/base/build/reports/tests」配下に作成されているhtmlファイルを確認
f:id:tomoTaka:20141012091631p:image:w360
とりあえずテストが成功しました!

2014-07-12 08:40

よなよなJavaFX ~ミニ四駆動〜

昨日はよなよなJavaFX ~ミニ四駆動〜 - connpassに参加してきました。

@さん、すでにスライドがアップされてました。javafx-mini4wd, SlideSearchEngine.com
ミニ四駆のお話、すごく楽しく聞かせていただきました。そこからJavaFXシミュレータを作成するって、すごいです!
youtubeで拝見させていただいたのですが、すごいです!ミニ四駆シミュレーター v2014-05-22 - YouTube
物理演算は、やっぱり難しくてついていけなかったです、、、(汗)
JBullet - Java port of Bullet Physics LibraryJavaで作られたLibraryのお話とかとても勉強になります。
JavaFXでのミニ四駆シュミレータ、ぜひJavaOneにスピーカーとして参加、期待してます!
もちろんミニ四駆での活躍も応援しています!

@さん、まだ10代とお聞きして驚きました。しかもSwingJavaFXも勉強されていて頭の下がる思いです。
Javaビーム、楽しく新しい発想、勉強がさらに楽しくなっている様子がいいですよね〜。
若い方がJavaに、興味を持って勉強されているのは嬉しいです!

@さん、毎回そうなんですが、スラドがとっても綺麗で、オシャレで、すごく考えられていて、とにかくすごいです!
ITProでのJavaFXの連載Java技術最前線 - Java技術最前線:ITpro、終わってとても残念です。でも今はJavaSE8の連載、毎回写経して楽しく勉強させていただいています!
Bindのお話、ブログの記事で過去に勉強させていただいてますが、やっぱりお話をお聞きすることで理解が深まります。
Bindの機能をRule、validation、layoutに適用させるお話は、目からうろこです!
bindをアニメーションに使っているお話で@さんの絵描き歌を紹介されてました。
お話の進め方、スライドの作成、などなど、JavaFXだけでなくプレゼンの勉強にもなります!

私@の、JavaFXでのローカライズの紹介です。緊張していて何をお話したのが、よく覚えてないです、
とりあえずアップしました。tomoTaka01/JavaFX8Presenter ? GitHub
ローカライズは興味があるので、Javaでの数値、通貨のフォーマットなどいろいろ勉強していこうと思っています。

@さん、Typetalk(タイプトーク) - チームでのチャットはもっと楽しくなれるJavaFX、ScalaFXで作成したお話。
さらっと数日で作成したとの発言、すごいです!

参加者の皆様、お疲れ様でした。とても楽しく有意義な時間を過ごせました。
いろいろお世話してくださったスタッフの方々にも感謝です!!!

2014-07-04 08:52

JavaFX localization Sample

I just wanted to know how to make JavaFX Application for localization.
First of all, this code shows you only how to apply resource properties to the JavaFX Label control. And Java8 has 5 type of Chronology classes that easily fit to JavaFX DatePicker control.
FYI see http://docs.oracle.com/javafx/scenebuilder/1/user_guide/i18n-support.htm

f:id:tomoTaka:20140703073530p:image:w380

You can select Locale and Calendar in this screen.
When you click the locale ComboBox, you can see country and language(e.g. United States(English)).
But once you select the locale, this ComboBox displays the locale.toString???(e.g. en_US)
I have no idea how to fix this problem…
In the EntryStart.java(see code-2-2) shows you how to set locale to the comboBox and change the label using StringConverter.
You can get Calendars from Chronology#getAvailableChronologies method and put each Chronology to the RadioButton by setUserData method.
f:id:tomoTaka:20140703073601p:image:w300
f:id:tomoTaka:20140703073636p:image:w260

When you select the [United States(English)] and [ISO] by Label_en_US.properties
LocalizationInfoTitle.fxml(see code3-1)and Entry1.fxml(see code5-1) show you how to set the properties key using the present sign(%).
Thanks to the JavaFX, it is easy to set the resource properties to your application.
You just make properties file for each locale(see Figure 8), and use FXMLLoader with ResourceBundle class which is created with the properties file and locale.(see code3-2)
I think the NetBeans has very good editor for properties file(see Figure7).
f:id:tomoTaka:20140703073742p:image:w360

When you select the [Japan(Japanese)] and [Japanese Calendar] by Label_ja_JP.properties
I needed function, that has page transfer and localizations data(locale and calendar) transfer.
I found that The JavaFX custom control has this function.
In the code3-1,3-2 and 4 show you how to create Localization.java and Entry1.java(EntryBase.java) as a custom control.
F.Y.R http://docs.oracle.com/javafx/2/fxml_get_started/custom_control.htm
I got the hint from this web site(http://skrb.hatenablog.com/entry/2012/06/16/175920) which explain how to implement page transitions.
f:id:tomoTaka:20140703073801p:image:w360

When you select the [Taiwan(Chinese)] and [Minguo Calendar] by Label.properties(default)
f:id:tomoTaka:20140703073818p:image:w360

When you select the [Saudi Arabia(Arabic)] and [Islamic Umm al-aura Calendar] by Label_ar_SA.properties
JavaFX DataPicker has setChronology method, all you need is to use this method for the specific calendar.(see code5-2)
f:id:tomoTaka:20140703073858p:image:w360

When you select the [Thailamd(Thai)] and [Buddhist Calendar] by Label.properties(default)
f:id:tomoTaka:20140703082216p:image:w360

NetBean8 has properties editor
f:id:tomoTaka:20140703073937p:image:w360

The project files
f:id:tomoTaka:20140703080950p:image:w280

public class Main extends Application{
    private BorderPane root;
    private EntryStartController entryStartController; 
    private HBox bottomHBox;
    private Button startButton;
    private Button resetLocaleButton;
    private Button nextButton;
    private PresentInfo presentInfo;
    private int fxmlIx = 0;
    private ENTRY[] fxmls = ENTRY.values();

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

    @Override
    public void start(Stage stage) throws Exception {
        this.presentInfo = new PresentInfo();
        Locale.setDefault(Locale.US);
        this.root = new BorderPane();
        setEntryStart();
        this.bottomHBox = new HBox();
        this.bottomHBox.getStyleClass().add("hbox");
        this.bottomHBox.setId("hbox-custom");        
        this.startButton = new Button("Start");
        this.resetLocaleButton = new Button("reset locale");
        this.nextButton = new Button("next");
        this.bottomHBox.getChildren().add(this.startButton);        
        this.setStartEvent();
        this.setResetLocaleEvent();
        this.setNextEvent();
        this.root.setBottom(this.bottomHBox);
        Scene scene = new Scene(root, 700, 500);
        stage.setTitle("Localization Sample");
        scene.getStylesheets().addAll("/css/layout.css");
        stage.setScene(scene);
        stage.show();
    }

    private void setEntryStart(){
        URL url = getClass().getResource("EntryStart.fxml");
        FXMLLoader loader = new FXMLLoader(url);
        try {
            this.presentInfo.centerNode = loader.<Node>load();
        } catch (IOException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
        this.root.setCenter(this.presentInfo.centerNode);
        this.entryStartController = loader.getController();
    }

    private void setStartEvent() {
        this.startButton.setOnAction(event -> {
            this.presentInfo.localizationInfo = this.entryStartController.getLocalizationInfo();
            this.root.getChildren().remove(this.presentInfo.centerNode);
            this.presentInfo.topTitle = new LocalizationInfoTitle(this.presentInfo.localizationInfo);
            this.root.setTop(this.presentInfo.topTitle);
            this.bottomHBox.getChildren().remove(this.startButton);
            this.bottomHBox.getChildren().addAll(this.resetLocaleButton, this.nextButton);
            setEntry();
        });
    }
    
    private void setResetLocaleEvent() {
        this.resetLocaleButton.setOnAction(event -> {
            this.root.getChildren().remove(this.presentInfo.centerNode);
            this.root.getChildren().remove(this.presentInfo.topTitle);
            fxmlIx = 0;
            this.bottomHBox.getChildren().remove(this.resetLocaleButton);
            this.bottomHBox.getChildren().remove(this.nextButton);
            this.bottomHBox.getChildren().addAll(this.startButton);
            this.setEntryStart();
        });
    }

    private void setNextEvent() {
        this.nextButton.setOnAction(event -> {
            this.root.getChildren().remove(this.presentInfo.centerNode);
            fxmlIx++;
            setEntry();
        });
    }
    private void setEntry() {
        ENTRY entry = fxmls[fxmlIx];
        EntryBase entryBase = entry.getController();
        entryBase.loadFxml(this.presentInfo.localizationInfo, entry.getFxmlPath());
        this.root.setCenter(entryBase);
    }
    
private class PresentInfo{
    Node centerNode;
    LocalizationInfo localizationInfo;
    LocalizationInfoTitle topTitle;
}

}
enum ENTRY{
    Entry1("Entry1.fxml") {
        @Override
        EntryBase getController() {
            return new Entry1();
        }
    },
    Entry2("Entry2.fxml") {
        @Override
        EntryBase getController() {
            return new Entry2();
        }
    };
    private String fxmlPath;
    private ENTRY(String fxmlPath) {
        this.fxmlPath = fxmlPath;
    }
    abstract EntryBase getController();
    String getFxmlPath(){
        return this.fxmlPath;
    }
}
<AnchorPane id="AnchorPane" prefHeight="500.0" prefWidth="800.0" stylesheets="@../../css/layout.css" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.sample.EntryStartController">
   <children>
      <ComboBox fx:id="localeCombo" layoutX="172.0" layoutY="54.0" prefWidth="150.0" />
      <Label layoutX="45.0" layoutY="54.0" prefHeight="26.0" prefWidth="102.0" text="Select Locale" />
      <Label layoutX="45.0" layoutY="113.0" text="Select Calendar" />
      <VBox fx:id="calendarVBox" layoutX="172.0" layoutY="113.0" prefHeight="179.0" prefWidth="288.0" spacing="10.0" style="-fx-border-style: solid; -fx-border-color: #666666;">
         <padding>
            <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
         </padding></VBox>
   </children>
</AnchorPane>
public class EntryStartController implements Initializable{
    @FXML
    private ComboBox<Locale> localeCombo;
    @FXML
    private VBox calendarVBox;
    private ToggleGroup calendarGroup = new ToggleGroup();

    @Override
    public void initialize(URL location, ResourceBundle resources) {        
        Locale.setDefault(Locale.ENGLISH);
        setLocaleCombo();
        setCalendar();
    }
    private void setLocaleCombo() {
        ObservableList<Locale> list = FXCollections.observableArrayList(
                new Locale("ja", "JP"),  // Japan
                new Locale("en", "US"),  // United States
                new Locale("fr", "FR"),  // France
                new Locale("de", "DE"),  // Germany
                new Locale("th", "TH"),  // Thailand
                new Locale("ar", "SA"),  // Saudi Arabia
                new Locale("zh", "TW")   // Taiwan
        );
        StringConverter<Locale> converter = new StringConverter<Locale>(){
            @Override
            public String toString(Locale object) {
                return String.format("%s(%s)", object.getDisplayCountry(), object.getDisplayLanguage());
            }
            @Override
            public Locale fromString(String string) {
                return null;
            }
        };
        localeCombo.getItems().addAll(list);
        localeCombo.setCellFactory(ComboBoxListCell.<Locale>forListView(converter));
        localeCombo.getSelectionModel().select(0);
    }

    private void setCalendar() {
        List<RadioButton> chronolories = Chronology.getAvailableChronologies().stream()
                .map(chronology -> {
                    RadioButton radioButton = new RadioButton(chronology.getDisplayName(TextStyle.FULL, Locale.getDefault()));
                    radioButton.setToggleGroup(calendarGroup);
                    radioButton.setUserData(chronology);
                    if (chronology.getCalendarType().equals("iso8601")) {
                        radioButton.setSelected(true);
                    }
                    return radioButton;
                }).collect(Collectors.toList());
        calendarVBox.getChildren().addAll(chronolories);
    }
    public LocalizationInfo getLocalizationInfo() {
        Locale locale = localeCombo.getSelectionModel().getSelectedItem();
        Chronology chronology = (Chronology) calendarGroup.getSelectedToggle().getUserData();
        LocalizationInfo localizationInfo = new LocalizationInfo();
        localizationInfo.setLocale(locale);
        localizationInfo.setChronolory(chronology);
        return localizationInfo;
    }
}
<fx:root type="javafx.scene.layout.HBox" xmlns:fx="http://javafx.com/fxml" 
         stylesheets="@../../css/layout.css" styleClass="hbox"> 
      <Label text="%locale_label" styleClass="locale-label" />
      <Label fx:id="selectedLocale"  text="" styleClass="locale-label"/>
        <HBox.margin>
           <Insets right="50.0" />
        </HBox.margin>
      <Label text="%chronology_label" styleClass="locale-label" />
      <Label fx:id="selectedChronology" text="" styleClass="locale-label" />
</fx:root>
public class LocalizationInfoTitle extends HBox implements Initializable{
    private LocalizationInfo localizationInfo;
    @FXML
    private Label selectedLocale;
    @FXML
    private Label selectedChronology;
    
    public LocalizationInfoTitle(LocalizationInfo info) {
        this.localizationInfo = info;
        loadFxml();
    }
    private void loadFxml() {
        URL url = getClass().getResource("LocalizationInfoTitle.fxml");
        ResourceBundle bundle = ResourceBundle.getBundle("resources/Label"
                , localizationInfo.getLocale());
        FXMLLoader loader = new FXMLLoader(url, bundle);
        loader.setRoot(this);
        loader.setController(this);
        try {
            loader.<HBox>load();
        } catch (IOException ex) {
            Logger.getLogger(LocalizationInfoTitle.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    @Override
    public void initialize(URL location, ResourceBundle resources) {
        Locale locale = this.localizationInfo.getLocale();
        this.selectedLocale.setText(String.format("%s(%s)"
                , locale.getDisplayCountry(locale), locale.getDisplayLanguage(locale)));
        Chronology chronolory = this.localizationInfo.getChronolory();
        this.selectedChronology.setText(chronolory.getDisplayName(TextStyle.FULL, locale));
    }
}
public abstract class EntryBase extends GridPane implements Initializable {
    protected LocalizationInfo localizationInfo;

    protected void loadFxml(LocalizationInfo localizationInfo, String fxmlPath) {
        this.localizationInfo = localizationInfo;
        URL url = getClass().getResource(fxmlPath);
        ResourceBundle bundle = ResourceBundle.getBundle("resources/Label", localizationInfo.getLocale());
        FXMLLoader loader = new FXMLLoader(url, bundle);
        loader.setRoot(this);
        loader.setController(this);
        try {
            loader.<GridPane>load();
        } catch (IOException ex) {
            Logger.getLogger(LocalizationInfoTitle.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public abstract boolean goNext();
}
<fx:root xmlns:fx="http://javafx.com/fxml/1" type="javafx.scene.layout.GridPane" hgap="10" vgap="10" 
    stylesheets="@../../css/layout.css" styleClass="grid"> 
    <children>
      <Label text="%letter_field_label" GridPane.columnIndex="0" GridPane.rowIndex="0" />
      <TextField fx:id="letterText" GridPane.columnIndex="1" GridPane.rowIndex="0" />
      <Label text="%digit_field_label" GridPane.columnIndex="0" GridPane.rowIndex="1" />
      <TextField fx:id="digitText" GridPane.columnIndex="1" GridPane.rowIndex="1" />
      <Label text="%date_label" GridPane.columnIndex="0" GridPane.rowIndex="2" />
      <DatePicker fx:id="datePicker" GridPane.columnIndex="1" GridPane.rowIndex="2" />
      <Label text="%currency_field_label" GridPane.columnIndex="0" GridPane.rowIndex="3" />
      <TextField fx:id="currencyText" GridPane.columnIndex="1" GridPane.rowIndex="3" />
    </children>
</fx:root>
public class Entry1 extends EntryBase {
    @FXML
    private DatePicker datePicker;
    
    @Override
    public boolean goNext() {
        // TODO do something about locatizaltion
        return true;
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        this.datePicker.setChronology(this.localizationInfo.getChronolory());
    }    
}

The whole code is here(https://github.com/tomoTaka01/LocalizationSample)
I will continue working on this project to learn about localization.
I am really happy if you leave any comments.
keep coding... ;-)

2014-05-10 21:48

Simple WebView Sample

The following code is a very simple example how to start loading the url or cancel it.
You can get more details information here Adding HTML Content to JavaFX Applications | JavaFX 2 Tutorials and Documentation

f:id:tomoTaka:20140506171322p:image:w160

f:id:tomoTaka:20140506171355p:image:w360

f:id:tomoTaka:20140506172420p:image:w360

f:id:tomoTaka:20140506172441p:image:w360

The following code shows how to start or cancel loading a url.
This is very easy. First you get the WebEngine and use the load method to get the Web Page.
Since loading happens on a background thread, use the Worker to cancel it.

    public void initialize(URL url, ResourceBundle rb) {
...
        this.engine = webView.getEngine(); // *** 1.get the WebEngine from WebView
...
    }
    @FXML private void loadURL(Event event){
        startLoadState.apply();
        String url = urlText.getText();
        this.engine.load(url);   // *** 2.to start loading the url
    }
    @FXML private void cancelLoad(Event event) {
        startCancelState.apply();
        this.engine.getLoadWorker().cancel();  // *** 3.to cancel loading the url
    }

Thanks to bindings, it is very easy to show progress on indicator.(see figure1)

    public void initialize(URL url, ResourceBundle rb) {
...
        // binding the progressIndicator to the Web LoadWorker
        this.indicator.progressProperty().bind(this.engine.getLoadWorker().progressProperty());
...
    }

You need to add the ChangeListener for changing the state of the screen.
The following code implements SUCCEEDED, CANCELLED and FAILED states, but you can use more.
(FYR seehttp://docs.oracle.com/javafx/2/api/)

    public void initialize(URL url, ResourceBundle rb) {
…
        this.engine.getLoadWorker().stateProperty().addListener(
                (ov, oldState, newState) -> {
                    switch (newState){ 
                        case SUCCEEDED:
                            loadCompletedState.apply();
                            loadCompletedState.setScreenCommonState(this);
                            break;
                        case CANCELLED:
                            loadCanceledState.apply();
                            loadCanceledState.setScreenCommonState(this);
                            break;
                        case FAILED:
                            loadFailedState.apply();
                            loadFailedState.setScreenCommonState(this);
                            break;
                    };
                });
…

I just want to use FunctionalInterface to learn how to use it.
I am not sure if this is the right way.But it is fun to use JavaSE8.

@FunctionalInterface
interface LoadingState{
    void apply();
    default void setScreenCommonState(FXMLDocumentController controller) {
        controller.urlText.setDisable(false);
        controller.loadButton.setDisable(false);
        controller.cancelButton.setDisable(true);
        controller.indicator.setVisible(false);
    }

To change the state of controllers by implementing above FunctionalInterface.

    public void initialize(URL url, ResourceBundle rb) {
        setLoadingState();
…
    }

    private void setLoadingState() {
        initState = () -> {
            loadState.setText("");            
            webView.setVisible(false);
        };
        startLoadState = () -> {
            urlText.setDisable(true);
            loadButton.setDisable(true);
            cancelButton.setDisable(false);
            loadState.setTextFill(Color.BLACK);
            loadState.setText("loading...");            
            webView.setVisible(false);
            indicator.setVisible(true);
        };
        startCancelState = () -> {
            cancelButton.setDisable(true);
            loadState.setTextFill(Color.BLACK);
            loadState.setText("cancelling....");            
        };
        loadCompletedState = () -> {
            loadState.setTextFill(Color.BLACK);
            loadState.setText("completed!");            
            webView.setVisible(true);
        };
        loadFailedState = () -> {
            loadState.setTextFill(Color.RED);
            loadState.setText("failed!!!");            
            webView.setVisible(false);
        };
        loadCanceledState = () -> {
            loadState.setTextFill(Color.ORANGE);
            loadState.setText("canceled!");            
            webView.setVisible(false);
        };
    }

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.web.*?>

<AnchorPane id="AnchorPane" prefHeight="600.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafxsimplewebview.FXMLDocumentController">
    <children>
        <WebView fx:id="webView" layoutX="15.0" layoutY="86.0" prefHeight="497.0" prefWidth="773.0" />
        <Label layoutX="30.0" layoutY="33.0" text="URL:" />
        <TextField fx:id="urlText" layoutX="68.0" layoutY="28.0" prefHeight="26.0" prefWidth="592.0" />
        <Button fx:id="loadButton" layoutX="700.0" layoutY="28.0" mnemonicParsing="false" onMouseClicked="#loadURL" prefHeight="26.0" prefWidth="82.0" text="load" />
        <Label fx:id="loadState" layoutX="102.0" layoutY="65.0" prefHeight="16.0" prefWidth="500.0" />
        <Label layoutX="27.0" layoutY="65.0" prefHeight="16.0" prefWidth="75.0" text="load state:" />
        <ProgressIndicator fx:id="indicator" layoutX="163.0" layoutY="119.0" prefHeight="148.0" prefWidth="218.0" progress="0.0" />
        <Button fx:id="cancelButton" layoutX="673.0" layoutY="60.0" mnemonicParsing="false" onMouseClicked="#cancelLoad" prefHeight="26.0" prefWidth="111.0" text="cancel load" />
    </children>
</AnchorPane>

The above code2 is created by Scene Builder.
f:id:tomoTaka:20140510212904p:image:W380

The main entry point for JavaFX application is here.

public class JavaFXSimpleWebView extends Application {
    @Override
    public void start(Stage stage) throws Exception {
        // *** load the FXML(code2)
        Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
        Scene scene = new Scene(root);
        stage.setTitle("Simple WebView Sample");
        stage.setScene(scene);
        stage.show();
    }
    public static void main(String[] args) {
        launch(args);  // *** 
    }
}

Assigned the project using Flex, so I created the HTML with swf file before. 2014-05-06 - tomoTakaの日記
I was a little curious about if HTML with Flex works on JavaFX WebView.
It does not work, but it is very fun to try something new by myself.
f:id:tomoTaka:20140506173418p:image:w430
whole code is herehttps://github.com/tomoTaka01/JavaFXSimpleWebView
just keep coding... ;-)

2014-03-11 08:24

DragboardChecker

Thanks to JavaFX Drag & Drop function, you can drag something from a third-party(native) application such as Finder(Mac OS).
You just need to implement of the DragOver and DragDropped event hander on a Target(see code1).
This is exciting for me, so I just want to know what kind of content the dragboard has.
This application checks dragboard contents and shows them to the screen.

f:id:tomoTaka:20140310080809p:image:w360

When you drag files from Finder(Max OS 10.9) to this App, the dragboard has files and 1 Dataformat.
f:id:tomoTaka:20140310074624p:image:w480

When you drag URL from web browser to this, the dragboard has string, URL, files and 3 of Dataformat.
f:id:tomoTaka:20140310074652p:image:w480

f:id:tomoTaka:20140311075106p:image:w360f:id:tomoTaka:20140311075127p:image:w360

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        initContextCheckers();
        this.dataFormatListView.setCellFactory(p -> new DataFormatCell()); // <― see code 4
        this.dropHereImage.setOnDragOver(e -> {
            e.acceptTransferModes(TransferMode.ANY);
            e.consume();
        });
        this.dropHereImage.setOnDragDropped(e -> {
            Dragboard db = e.getDragboard();
            this.contextCheckers.forEach(checker -> checker.check(db)); // <― see code2,3
            setDataFormatListView(db);
            e.setDropCompleted(true);
        });
    }
    private void initContextCheckers() {
        this.contextCheckers = Arrays.asList(
            new StringContextChecker(this.stringCheck, this.stringText)
          , new UrlContextChecker(this.urlCheck, this.urlText)
          , new FileContextChecker(this.filesCheck, this.filesText)
          , new RtfContextChecker(this.rtfCheck, this.rtfText)
          , new ImageContextChecker(this.imageCheck, this.imageView)
          , new HtmlContextChecker(this.htmlCheck, this.htmlText)
        );
    }    
    private void setDataFormatListView(Dragboard db) {
        List<DataFormatInfo> list = db.getContentTypes().stream().map(df -> {
            return new DataFormatInfo(df, db.getContent(df).toString());
        }).collect(Collectors.toList());       // <― see code5
        this.dataFormatListView.setItems(FXCollections.observableArrayList(list));
    }

This is the base class for each checker class like StringChecker, UrlChecker so on.

public abstract class ContextChecker<T extends Node> {
    protected BooleanProperty checkboxProp;
    protected T node;
    public ContextChecker(CheckBox checkbox, T node) {
        this.checkboxProp = new SimpleBooleanProperty(false);
        checkbox.selectedProperty().bind(this.checkboxProp);
        this.node = node;
    }
    abstract public void check(Dragboard db);    
}

Since clipboard(dragboard) has 6 methods for contains data, I create 6 checker class.

typemethodmethodchecker class
StringhasStringgetString StringContextChecker
FileshasFilesgetFilesFileContextChecker
HTMLhasHtmlgetHtmlHtmlContextChecker
ImagehasImagegetImageImageContextChecker
RTFhasRtfgetRtfRtfContextChecker
URLhasUrlgetUrlUrlContextChecker
public class StringContextChecker extends ContextChecker<TextArea>{
    public StringContextChecker(CheckBox checkbox, TextArea node) {
        super(checkbox, node);
    }
    @Override
    public void check(Dragboard db) {
        if (db.hasString()) {
            super.checkboxProp.set(true);
            super.node.setText(db.getString());
        } else {
            super.checkboxProp.set(false);
            super.node.clear();
        }
    }   
}

The clipboard(dragboard) has some custom data which are defined by data format.
To show the custom data, you can implement custom list cell like below.

public class DataFormatCell extends ListCell<DataFormatInfo>{
    GridPane root;
    Label dataFormatLabel;
    Text dataFormatText;
    Label contentLabel;
    Text contentText;
    Label idsLabel;
    ListView idsListView;
    ObservableList<String> idsList;
    
    public DataFormatCell() {
        init();
    }
    @Override
    protected void updateItem(DataFormatInfo info, boolean empty) {
        super.updateItem(info, empty);
        if (empty) {
            setText(null);
            setGraphic(null);
        } else {
            this.dataFormatText.setText(info.getDataFormat());
            this.contentText.setText(info.getContent());
            this.idsList.setAll(info.getIdentifiersList());
            setGraphic(root);
        }
    }
    private void init() {
        this.root = new GridPane();
        this.root.setPadding(new Insets(2));
        this.root.setHgap(2);
        this.root.setVgap(2);
        this.dataFormatLabel = new Label("Data Format:");
        this.dataFormatLabel.setPrefWidth(100);
        this.dataFormatText = new Text();
        this.dataFormatText.prefWidth(400);
        this.contentLabel = new Label("Content:");
        this.contentText = new Text();
        this.idsLabel = new Label("Identifires");        
        this.idsList = FXCollections.observableArrayList();
        this.idsListView = new ListView(this.idsList);
        this.idsListView.setPrefHeight(70);
        this.idsListView.setPrefWidth(500);        
        this.root.add(this.dataFormatLabel, 0, 0);
        this.root.add(this.dataFormatText, 1, 0);
        this.root.add(this.contentLabel, 0, 1);
        this.root.add(this.contentText, 1, 1);
        this.root.add(this.idsLabel, 0, 2);
        this.root.add(this.idsListView, 0, 3, 2, 1);
    }
}

This code has custom data information for DataFormatCell(see code4).

public class DataFormatInfo {
    private StringProperty dataFormatProp;
    private StringProperty contentProp;
    private List<String> identifiersList;    

    public DataFormatInfo(DataFormat dataFormat, String content) {
        this.dataFormatProp = new SimpleStringProperty(dataFormat.toString());
        this.contentProp = new SimpleStringProperty(content);
        this.identifiersList = 
            dataFormat.getIdentifiers().stream().collect(Collectors.toList());
    }
    public String getDataFormat(){
        return this.dataFormatProp.getValue();
    }
    public String getContent() {
        return this.contentProp.getValue();
    }
    public List<String> getIdentifiersList() {
        return this.identifiersList;
    }
}

The whole code is heretomoTaka01/DragboardChecker ? GitHub.
keep coding... ;-)

tomoTaka
tomoTaka