40

I'm trying to build a relatively simple JavaFX application using Gradle. However, I have no idea how to do it.

I'm relatively new to Gradle, and for simple (non-javafx) project I've successfully used the plugins java and application to build and package libraries and command-line applications.

However, I'm completely stuck when it comes to JavaFX. I've read this article, which suggests using the JavaFX plugin, however I could only find the source code for this plugin, but no documentation on how to actually obtain it an use it (in the article they simply apply it from a remote URL, but that fails on my machine, says I'm not authorized...)

Any clues on how to do this properly?

Master_T
  • 7,232
  • 11
  • 72
  • 144

5 Answers5

20

Here's an example Gradle JavaFX build on GitHub. Note that according to Bintray, the latest version of the plugin is 8.1.1, so replace the '0.3.0' in the plugin URL with '8.1.1' if you want the latest.

Just to be clear, this is a very unusual way to distribute a Gradle plugin. Most are much easier to incorporate in a build!

Edit: up-to-date fork that works using "apply plugin" https://github.com/FibreFoX/javafx-gradle-plugin

Fabian Zeindl
  • 5,860
  • 8
  • 54
  • 78
Peter Ledbrook
  • 4,302
  • 1
  • 21
  • 18
  • my problem is exactly that: apply from: "http://dl.bintray.com/content/shemnon/javafx-gradle/0.3.0/javafx.plugin" command doesn't work, bintray returns error 401 (unauthorized). Anyway, I solved by manually compiling the plugin from source and including it locally – Master_T Jul 15 '15 at 08:46
  • 1
    Are you sure? That link (minus the trailing double quote) doesn't require authentication for me. However, the one used in the original article _does_ require authentication. – Peter Ledbrook Jul 15 '15 at 08:51
  • You are indeed correct. I f**ed up and copied an extra trailing quote. It works, thanks. – Master_T Jul 15 '15 at 09:04
  • 1
    Using javafx-gradle-plugin still doesn't let me run JavaFX app from Idea. I guess suggestion to use this plugin is pointless without mentioning what else should be configured so that app can actually run. – AbstractVoid Jun 30 '18 at 14:08
  • Update to previous comment. For all the poor souls not knowing how to run JavaFX app with gradle javafx-gradle-plugin from idea, I figured out you can do that with: open Gradle side bar on the right pane > tasks > javafx > jfxRun. I also had to replicate the structure of this example project (yep, turns out directory structure really matters): https://github.com/gerardoprada/javafx-gradle-hello-world – AbstractVoid Jun 30 '18 at 14:59
  • FYI, the author of this plugin has said that as of April 2018, the current version is being retired (he is not working on it anymore), and that he is privately working on a new one, with no definite expected release date. See https://github.com/FibreFoX/javafx-gradle-plugin/issues/119 for details. – Some Guy Dec 02 '18 at 09:46
7

Here is my example project with OpenJDK 12, JavaFX 12 and Gradle 5.4. It uses the JavaFX Gradle plugin.

  • Opens a JavaFX window with the title "Hello World!"
  • Able to build a working runnable distribution zip file (Windows to be tested)
  • Able to open and run in IntelliJ without additional configuration
  • Able to run from the command line

I hope somebody finds the Github project useful. Feel free to clone it. It is licensed with the Unlicense.

Peter Lamberg
  • 8,151
  • 3
  • 55
  • 69
4

The official gradle plugin for javafx is at https://github.com/openjfx/javafx-gradle-plugin.

I have successfully used this plugin from INtelliJ IDEA CE with following to illustrate my build.gradle file:

plugins {
    id 'java'
    id 'application'
    id 'maven'
    id 'maven-publish'
    id 'org.openjfx.javafxplugin' version '0.0.8'
}

javafx {
    // Points to JDK and its JavaFX libraries, also declares target runtime JDK
//    javaRuntime = '/Library/Java/JavaVirtualMachines/jdk1.7.0_40.jdk'

    version = '13' // Specify javafx sdk version
    modules = [ 'javafx.controls', 'javafx.fxml', 'javafx.swing', 'javafx.media', 'javafx.graphics']
    sdk = System.getenv('JAVAFX_HOME')
    if (sdk == null || sdk.isBlank()) {
        throw new InvalidUserDataException("JAVAFX_HOME environment variable is not set. It must be set to root folder where JAVAFX SDK is located")
    }
    application {
        def javafxHome = System.getenv('JAVAFX_HOME')
        mainClassName = 'com.foo.FooApp'
        applicationName = 'foo-app'
        applicationDefaultJvmArgs = [
            "--module-path=${javafxHome}" + File.separator + 'lib',
            '--add-modules=javafx.controls,javafx.swing,javafx.media,javafx.graphics']
        println("applicationDefaultJvmArgs:" + applicationDefaultJvmArgs)
    }
}

dependencies {
  ... ommitted ...
}
Farrukh Najmi
  • 5,055
  • 3
  • 35
  • 54
  • `application` plugin has nothing to do with `javafxplugin` plugin, therefore the DSL invocation should be at project root (not inside `javafx`). – Hendra Anggrian Aug 23 '21 at 19:02
  • My `build.gradle` file doesn't like the syntax give here. It prefers, for instance, `id("org.openjfx.javafxplugin") version "0.0.8"`. Does that amount to the same thing? IF so, what else in this answer needs to change for it to work? – gotube Oct 16 '22 at 17:10
3

Peter Ledbrook's solution works, but just in case someone wants a solution that doesn't rely on external bintray links, I found one while waiting for an answer:

1) Built the JavaFX plugin from source
2) Put it in the project's libs directory
3) Applied it like this:

buildscript {
    repositories {
        flatDir dirs: "../libs"
    }
    dependencies {
        classpath "org.bitbucket.shemnon.javafxplugin:gradle-javafx-plugin:0.5.0-SNAPSHOT"
        classpath files("${System.properties['java.home']}/../lib/ant-javafx.jar")
    }
}

if (!project.plugins.findPlugin(org.bitbucket.shemnon.javafxplugin.JavaFXPlugin)) {
    project.apply(plugin: org.bitbucket.shemnon.javafxplugin.JavaFXPlugin)
}

Note that including ant-javafx in the classpath is needed due to a bug in the plugin itself (if I understand correctly)

Master_T
  • 7,232
  • 11
  • 72
  • 144
1

I would use the gradle init command as:

thufir@dur:~/NetBeansProjects$ 
thufir@dur:~/NetBeansProjects$ git clone git@github.com:THUFIR/javaFX.git
Cloning into 'javaFX'...
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 4 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (4/4), 12.48 KiB | 2.08 MiB/s, done.
thufir@dur:~/NetBeansProjects$ 
thufir@dur:~/NetBeansProjects$ cd javaFX/
thufir@dur:~/NetBeansProjects/javaFX$ 
thufir@dur:~/NetBeansProjects/javaFX$ tree
.
├── LICENSE
└── README.md

0 directories, 2 files
thufir@dur:~/NetBeansProjects/javaFX$ 
thufir@dur:~/NetBeansProjects/javaFX$ gradle init --type java-application --test-framework testng --dsl kotlin

Project name (default: javaFX): 

Source package (default: javaFX): net.bounceme.dur.javafx

BUILD SUCCESSFUL in 17s
2 actionable tasks: 2 executed
thufir@dur:~/NetBeansProjects/javaFX$ 
thufir@dur:~/NetBeansProjects/javaFX$ tree
.
├── build.gradle.kts
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── LICENSE
├── README.md
├── settings.gradle.kts
└── src
    ├── main
    │   ├── java
    │   │   └── net
    │   │       └── bounceme
    │   │           └── dur
    │   │               └── javafx
    │   │                   └── App.java
    │   └── resources
    └── test
        ├── java
        │   └── net
        │       └── bounceme
        │           └── dur
        │               └── javafx
        │                   └── AppTest.java
        └── resources

17 directories, 10 files
thufir@dur:~/NetBeansProjects/javaFX$ 

here I've first cloned an empty repository (except for the license and readme) from github first, then initialized with gradle. Note that it's of type java-application and is using kotlin for the dsl; those can be omittied or changed to, for example, --type java-library.

Thufir
  • 8,216
  • 28
  • 125
  • 273