復活していたQtJambi

QtJambiの開発は引き継がれていた

OracleからJavaのクライアントテクノロジーに関するロードマップが発表され、それについて色々思うことを垂れ流した次のブログを投稿したのですが、あれからもう5年になるのですね。

aoe-tk.hatenablog.com aoe-tk.hatenablog.com

このエントリにて、次のようなことを書いていました。

汎用的なクロスプラットフォーム GUI で一番成功しているのはやはり Qt でしょうか。モバイルへの進出にも成功していますし。開発言語は C++ ですが、他のプログラミング言語へのバインディング も多いです。ですが、Java バインディングである Jambi が死んでしまったんですよね...。

QtのJavaバインディングであるJambiについて、このエントリを書いたときは死んだような状態になっていたのですね。ところが最近QtJambiという名称として (以前は "Qt Jambi" とQtとJambiの間にスペースが入っていました) 復活していたことに気付きました。

github.com

これは元々NokiaがQt JambiのOSS化にあたって作った 旧Qt Jambiのリポジトリ とは別のリポジトリです。 どうもOmix Visualizationという会社が最新のQtに対応したフォークを作成して開発を引き継いだようです。旧リポジトリでは対応していなかったQt5系はもちろん、6系も最新の6.5にまで対応したリリースがあります。

コミット履歴を調べてみると *1 一番最初のコミットは2015年9月で、旧リポジトリの最後のコミットが2015年9月であるのを見るに、旧プロジェクトの開発終了後すぐに新しいリポジトリを作ったようです。旧プロジェクトにてコミッタ間で話し合いがあってフォークが決まったとかですかねえ。

リポジトリ作成は2015年9月ですがリリースタグの付いた最初のリリースは2020年8月で、ここからプロダクトとしてリリースしていくステップに入ったようです。 Qt本家Wikiの言語バインディングのページ に追加されたのもその時からでした。旧プロジェクトの終了後、5年のブランクを経て復活した形ですね。

触ってみる

見つけたからには触ってみることにしましょう。なお自分はQtによる開発の経験は過去に一切ありません🙂

QtJambiはJPMSに従ったモジュール化がされています。次のAPIドキュメントのトップメージにモジュール一覧が列挙されています。Qtが提供する膨大なライブラリを概ねカバーしているようです。3DやWebViewなどはもちろん、BluetoothNFC、センサーなど実に膨大な範囲をカバーしていることが分かりますね。

https://doc.qtjambi.io/latest/

基本的なものは全て qtjambi モジュールに入っています。モジュール別にMaven Centralに登録されているので、Mavenを使っている場合は pom.xml に次のように依存設定を追加します。実行にあたってはプラットフォームに応じたネイティブライブラリも必要なので qtjambi-native-<os>-<architecture> も追加する必要があります。

    <dependencies>
        <dependency>
            <groupId>io.qtjambi</groupId>
            <artifactId>qtjambi</artifactId>
            <version>6.5.0</version>
        </dependency>
        <dependency>
            <groupId>io.qtjambi</groupId>
            <artifactId>qtjambi-native-windows-x64</artifactId>
            <version>6.5.0</version>
        </dependency>
    </dependencies>

これでプログラムを作成できます。ごく簡単なウィンドウとメニューを持つアプリケーションを作ってみます。

package aoetk.qtsamle;

import io.qt.gui.QAction;
import io.qt.widgets.QApplication;
import io.qt.widgets.QLabel;
import io.qt.widgets.QMainWindow;
import io.qt.widgets.QMenu;

import static io.qt.core.QObject.tr;
import static java.util.Objects.requireNonNull;

public class WindowSample {

    public static void main(String[] args) {
        QApplication.initialize(args);
        QMainWindow mainWindow = new QMainWindow();
        QMenu menu = requireNonNull(mainWindow.menuBar()).addMenu(tr("&File"));
        QAction quitAction = requireNonNull(menu).addAction(tr("&Quit"));
        requireNonNull(quitAction).triggered.connect(QApplication::quit);
        mainWindow.setCentralWidget(new QLabel(tr("Hello Qt!"), mainWindow));
        mainWindow.show();
        QApplication.exec();
        QApplication.shutdown();
    }

}

実行するにあたっては予めQtがインストールされている必要があります。 インストーラのダウンロードページ からQtのインストールを行います。予めユーザー登録を行う必要がある点に注意してください。非常に巨大なライブラリなのでインストールには結構時間が掛かります。

作ったJavaアプリケーションを実行する際、JVMシステムプロパティ java.library.path にQtのライブラリパスを指定します。OS別に次のようなパスになります。

  • Windows
    • <path to>\Qt\<version>\msvc2019_64\bin
  • Linux
    • <path to>/Qt/<version>/gcc_64/lib
  • macOS
    • <path to>/Qt/<version>/macos/lib
    • macOSの場合はさらに起動引数として -XstartOnFirstThread を指定する必要あり

Windows環境のIntelliJでの実行設定の例を示しておきます。

プログラムを実行すると次のようにメニューとラベルを持つウィンドウが起動しました。

使い方を学ぶには?

汎用クロスプラットフォームGUIツールキットとしては最強と思われるQtへのバインディングが提供されたことで、再びJavaにもスタンドアロンGUIアプリケーションを作るための強力な手段が加わりました。

現時点での問題点は余りにも情報が少ないという点ですね。GoogleTwitter、Stack Overflowなどを検索してもこの新しいQtJambiへの言及がほとんど見られていません。本当に一握りの人間しかこれの存在に気付いていないような気がしますw

基本的にドキュメントは GitHubプロジェクト上のWiki からたどれる範囲のみで、Qtについての基本概念は知っていることを前提とした記述になっています。APIドキュメントについても本家C++版のページへのリンクを示すだけのクラスが多いです。

自分はC++の開発経験がゼロに等しいので、C++版のドキュメントを読むのはちょっと辛いんですよねえ。幸いQtは有名どころのプログラミング言語に対してはほぼバインディングを提供しており、例えばPythonバインディングであるQt for Python (PySide) については公式からも豊富なドキュメントが提供されているので、これでQtを勉強しますかねえ。

www.qt.io

というわけでいつの間にか復活していたQtJambiについての紹介でした。

*1:コミット数はほぼリリース単位になっていて少なく、クローズドのリポジトリで開発してリリースのタイミングで一気にパブリックリポジトリにpushしているスタイルのようです。