Basic usage
Required Java version
To use Java-GI, download and install OpenJDK version 25 or newer. Java-GI uses many features of modern JDK versions, such as the Foreign Function & Memory API (JEP-454), Markdown Javadoc (JEP-467) and Flexible Constructor Bodies (JEP-513), so any JDK version below 25 will not work.
Java-GI does not work with Graal Native Image, for two reasons:
-
GraalVM requires registration of all foreign calls at compile time, but this has not (yet) been implemented in the bindings generator.
-
Java-GI uses runtime reflection for GType registration, GClosure marshaling, and other features. This would have to be completely replaced by a new solution based on annotation processors and a ServiceLoader.
Dependencies
Make sure that the native GLib, Gtk and/or GStreamer libraries are installed on your operating system.
-
If you use Linux, Gtk is often installed by default. On Windows or MacOS, follow the installation instructions.
-
GStreamer: Follow the installation instructions.
Next, add the dependencies. For example, to add Gtk as a dependency:
This will add the Gtk bindings to the application's compile and runtime classpath. Other libraries, like webkit, gstreamer, adw and gtksourceview can be included likewise. The complete list of available libraries is available here.
Application code
An example Gtk application with a "Hello world" button can be created as follows:
package my.example.helloapp;
import org.gnome.gtk.*;
import org.gnome.gio.ApplicationFlags;
public class HelloWorld {
public static void main(String[] args) {
new HelloWorld(args);
}
public HelloWorld(String[] args) {
var app = new Application("my.example.HelloApp");
app.onActivate(() -> activate(app));
app.run(args);
}
public void activate(Application app) {
var window = new ApplicationWindow(app);
window.setTitle("GTK from Java");
window.setDefaultSize(300, 200);
var box = Box.builder()
.setOrientation(Orientation.VERTICAL)
.setHalign(Align.CENTER)
.setValign(Align.CENTER)
.build();
var button = Button.withLabel("Hello world!");
button.onClicked(window::close);
box.append(button);
window.setChild(box);
window.present();
}
}
package my.example.helloapp
import org.gnome.gio.ApplicationFlags
import org.gnome.gtk.*
fun main(args: Array<String>) {
val app = Application("my.example.HelloApp")
app.onActivate { activate(app) }
app.run(args)
}
private fun activate(app: Application) {
val window = ApplicationWindow(app)
window.title = "GTK from Kotlin"
window.setDefaultSize(300, 200)
val box = Box.builder()
.setOrientation(Orientation.VERTICAL)
.setHalign(Align.CENTER)
.setValign(Align.CENTER)
.build()
val button = Button.withLabel("Hello world!")
button.onClicked(window::close)
box.append(button)
window.child = box
window.present()
}
package my.example.helloapp
import org.gnome.gtk.*
import org.gnome.gio.ApplicationFlags
class HelloWorld {
def activate(app: Application) = {
var window = new ApplicationWindow(app)
window.setTitle("GTK from Scala")
var box = new Box(Orientation.VERTICAL, 1) {
setHalign(Align.CENTER)
setValign(Align.CENTER)
}
var button = Button.withLabel("Hello world!")
button.onClicked{() => window.close}
box.append(button)
window.setChild(box)
window.present()
}
}
object HelloWorld {
def main(args: Array[String]) = {
val app = Application("my.example.HelloApp")
app.onActivate(() => HelloWorld().activate(app))
app.run(args);
()
}
}
(ns hello
(:import
(org.gnome.gio ApplicationFlags Application$ActivateCallback)
(org.gnome.gtk Align Application ApplicationWindow Box Button Button$ClickedCallback Orientation)))
(def app (doto (Application. "org.javagi.examples.HelloWorldClojure" (into-array ApplicationFlags [ApplicationFlags/DEFAULT_FLAGS]))
(.onActivate (reify Application$ActivateCallback
(run [this]
(let [app-window (ApplicationWindow. app)]
(doto app-window
(.setTitle "GTK from Clojure")
(.setDefaultSize 300 200)
(.setChild (doto (Box. Orientation/VERTICAL 0)
(.setHalign Align/CENTER)
(.setValign Align/CENTER)
(.append (doto (Button/withLabel "Hello world!")
(.onClicked (reify Button$ClickedCallback
(run [this] (.close app-window))))))))
(.present))))))))
(defn run [opts]
(.run app nil))
Compile and run
Build and run the application using your IDE or build tool of choice. The following command-line parameters are useful:
-
Add
--enable-native-access=ALL-UNNAMEDto suppress warnings about native access. (This warning will become an error in a future JDK release.) -
If you encounter an error about a missing library, override the java library path with
"-Djava.library.path=/usr/lib/...".
See this Gradle build file for a typical example.
Use an IDE
An Integrated Development Environment (IDE) with support for Java is the most efficient way to develop software in Java. IDEs will help setup a project and build configuration, navigate and refactor source code, detect problems and suggest improvements. The most commonly used Java IDEs are:
If you often work from the command line, SDKMAN! will prove useful to manage your installed JDKs and build tools.
Further reading
For more advanced instructions on using Java-GI consult this page, and read about subclassing GObject classes with Java-GI here. If you're new to Gtk development, read the Gtk "Getting started" guide that has been translated to use Java for all code examples.
Platform-specific notes
Linux
On most Linux distributions, Gtk will already be installed. Java-GI will load shared libraries using dlopen, and fallback to the java.library.path. So in most cases, you can simply run your application with --enable-native-access=ALL-UNNAMED:
MacOS
On MacOS, you can install Gtk using Homebrew. Gtk needs to run on the main thread, therefore you need to set the parameter -XstartOnFirstThread. A typical build configuration will look like this:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.6.3</version>
<configuration>
<mainClass>...</mainClass>
<jvmArguments>
<jvmArgument>--enable-native-access=ALL-UNNAMED</jvmArgument>
<jvmArgument>-Djava.library.path=/opt/homebrew/lib</jvmArgument>
<jvmArgument>-XstartOnFirstThread</jvmArgument>
</jvmArguments>
</configuration>
</plugin>
Windows
On Windows, Gtk can be installed with MSYS2. A typical build configuration will look like this:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.6.3</version>
<configuration>
<mainClass>...</mainClass>
<jvmArguments>
<jvmArgument>--enable-native-access=ALL-UNNAMED</jvmArgument>
<jvmArgument>-Djava.library.path=C:/msys64/mingw64/bin</jvmArgument>
</jvmArguments>
</configuration>
</plugin>