<このシリーズの、前の記事 | このシリーズの目次 |
UNO拡張機能(LibreOffice拡張機能またはApache OpenOffice拡張機能)内でSwing GUIを使う方法を知る
話題: UNO (Universal Network Objects)
話題: LibreOffice
話題: Apache OpenOffice
話題: Javaプログラム言語
バイアス惑星の山あいの小川のほとりのある部屋で-Hypothesizerと-Rebutterがコンピュータースクリーンの前に座っている。
UNO拡張機能の中でGUIを実装しようと思う。
うーむ、 . . . それがどうした?JavaでUNO拡張機能を開発できるのだから、JavaFX、Swing、その他何でもただ使えばいいだけではないのか?
実のところ、そういうわけではない。気をつけなければならないことがいくつかある。
ほう?何だそれらは?
最も重要なことは、Linux上では、UNO拡張機能で、JavaFXを使えないようだということだ。
どうやら、Windows上では、UNO拡張機能で、JavaFXを使えると言っているようだな。
Windows上でJavaFXの単純なダイアログを表示できることから、そのように私は推測している。我々のメインのマシンはLinuxなので、実際には、私はそれ以上調査していない。Windows上だけで使えるのでは我々の役には立たないから。
Linux上ではなぜUNO拡張機能でJavaFXを使えないのか?
以下が私の推測だ。JavaFXはGDKを使っている、LibreOfficeがそうであるように。JavaFXはGDKのメインループを作ろうとするのだが、このメインループは、LibreOfficeのGDKのメインループと同一プロセス内で共存できないようだ。
ああ、JavaFXプログラムはFXプログラムインスタンスと指定して実行されるように想定されているので、LibreOfficeプログラムインスタンスの中で動くJVMでJavaFXを使えないのは自然かもしれない。
それで、Linux上、UNO拡張機能の中でJavaFXを使おうとすると、何がおきるのか?
JavaFXの初期化が、受け取るべき一部のイベントを受け取ることができず、フリーズする。結果的に、LibreOfficeプログラムインスタンス全体がフリーズする。
ふーむ、 . . . それでは、回避策は何もないのか?
少なくとも、私は知らない。ただ、究極の解決策はある。
それは何だ?
GUIサーバーをUNOサーバーとして作ることができる。
ああ、シリーズ、「外部JavaプログラムでUNOを使用する(LibreOfficeまたはApache OpenOfficeのドキュメントを操作する)方法」で話したように、UNOサーバーを作ることができる。UNOサーバーは独立したJavaプログラムなので、JavaFXだろうがJavaの他のどの機能だろうが、制限があるはずがない。
Swingは問題なく使えるので(後で話すとおり、ある落とし穴はあるが)、その解決策を追求するのはまたの機会にしよう。
いいだろう。
言っておくが、UNO拡張機能の中で使うように推奨されているGUIライブラリがあるが、我々は従わない、なぜなら . . .
. . . 我々の性格がゆがんでいるからか?
それはここでの理由ではない、そのとおりではあるが、ある程度。理由は、そのライブラリがSwingやJavaFXほど便利だとも機能豊富だとも私は予想していないから。
それは、何らかの事実に基づいているのか?
当て推量と言うべきだろう。. . . 別の理由は、UNO拡張機能を開発するためだけのために、新たにGUIライブラリを学びたくないことだ。
それは理解できる。
必要であれば、GUIサーバーという解決策を選ぶだろう、そのGUIライブラリを使うというものではなく。
前場と同じ。
Swingは、UNO拡張機能の中で問題なく使えるが、Swingを使いはじめる前に行なわければならないことが1つある。
それは何だ?
-Hypothesizerは、Javaのソースコードを開き、ある行を指差す。
この行を呼ばなければならない。
Thread.currentThread ().setContextClassLoader (ClassLoader.getSystemClassLoader ());
うーむ、 . . . クラスローダーをカレントスレッドに登録しているのか?
そうだ。Swingはそれを使うが、それは、LibreOfficeが用意したJVMには登録されていない、なぜだか。
ふーむ。. . . それでは、それを行ないさえすれば、UNO拡張機能の中でSwingを何の問題なく使えるのか?
私が知る限り、そうだ。
前場と同じ。
サンプルを作ろう。
各ボタンが各機能を起動するボタン群を持つコントロールパネルはどうだろう?
コントロールパネルは結構だが、どんな機能だ、例えば?
うーむ、 . . . セルエディターはどうだろう?
「セルエディター」というのは何だ?
スプレッドシートはデータをグリッド状に整理するのに便利だが、セルに長いテキストを入れると、セルの中でテキストを見たり編集したりするのに難儀する。
実際、数字や短いテキストだけを扱う限りは良いが、長いテキストも扱わなければならない場合、スプレッドシートは事実上使い物にならなくなる。
もし、我々のセルエディターで長いテキストが扱えれば、そうした場合でもスプレッドシートを便利に使える。
ふーむ . . .
この記事では、コントロールパネルを作ることに集中しよう。この段階では、セルエディターはダミーだ。
まあ、我々は既に、スプレッドシートセルから読んだりスプレッドシートセルに書いたりする方法を知っているので、セルエディターを作るのは、UNO拡張機能内でGUIを使う方法を知ってさえいれば、単にJavaプログラミングの問題だ。
そのとおり。
コントロールパネルを表示するのは単にSwingプログラミングの問題だが、ここでは、コントロールパネルを、LibreOfficeのカレントフレームに対して相対的に適切な場所に表示しよう。
ああ、それでは、我々は、コントロールパネルに、スクリーンのランダムな位置や固定の位置に表示されてほしくないわけだ。
我々は、コントロールパネルを、LibreOfficeのカレントフレームの左境界の隣に表示しよう。
そこにスペースがなかったらどうするのか?
その場合は、LibreOfficeのカレントフレームの上に表示しなければならないだろう。
どこに表示したいにしろ、問題は、LibreOfficeのカレントフレームの境界の位置をどのように得られるかということだ。
以下のようにして得ることができる。
-Hypothesizerは、先程ののJavaソースファイルのあるセクションを選択する。
import com.sun.star.awt.XWindow;
import com.sun.star.frame.XDesktop;
import com.sun.star.frame.XFrame;
import thebiasplanet.unoutilities.constantsgroups.*;
import thebiasplanet.unoutilities.serviceshandling.UnoServiceHandler;
XDesktop l_unoDesktopInXDesktop = (XDesktop) UnoServiceHandler.getServiceInstance (i_componentContextInXComponentContext, UnoServiceNamesConstantsGroup.c_com_sun_star_frame_Desktop, XDesktop.class);
XFrame l_unoFrameInXFrame = l_unoDesktopInXDesktop.getCurrentFrame ();
XWindow l_desktopContainerWindowInXWindow = l_unoFrameInXFrame.getContainerWindow ();
com.sun.star.awt.Rectangle l_desktopContainerWindowBoundary = l_desktopContainerWindowInXWindow.getPosSize ();
Rectangle l_applicationContainerWindowBoundary = new Rectangle (l_desktopContainerWindowBoundary.X, l_desktopContainerWindowBoundary.Y, l_desktopContainerWindowBoundary.Width, l_desktopContainerWindowBoundary.Height);
ふむ、'thebiasplanet'パッケージ配下のクラス群は、我々のユーティリティクラスだ。
過去の記事で既に説明したコードについては、我々は、また明示的に示すことはせず、我々のユーティリティクラスを使うかもしれない。ユーティリティクラスは我々の各種zipファイルに含まれているので、必要であれば、それらの中を見ればよい。
いいだろう。
我々のサンプルプログラムは、ここにある。.
以前に引用したサンプルUNO拡張機能プロジェクトに実装したのか。
そうだ。zipファイルの使い方は、そこに書いてある。我々はいくつかの記事で引用されているプロジェクトにコードを追加するので、ある記事で引用されているプロジェクトがその記事とは関係ないコードを含んでいることがあり得る。そうしたコードは、他の記事から来ている。
-Hypothesizerはgradleコマンドを実行し、 コマンドは正常終了する。-Hypothesizerは、'TestSpreadSheetsDocumentForExecutingTests.ods'スプレッドシートドキュメントを開く。
シートに第2のボタンを追加したのか。
そうだ。ボタンを押す前に、LibreOffice Basicライブラリをインポートしなければならない、過去の記事に記載されているように。
-Hypothesizerは、'Show Test Control Panel'ボタンをクリックし、小さなダイアログボックスが、LibreOfficeのカレントフレームの左境界の隣に表示される。
. . . 「コントロールパネル」と呼ぶには印象の薄いしろものだな . . .
印象が薄かろうがなかろうが、コントロールパネルだ。'Edit Cell'ボタンをクリックすると、セルエディターが表示される。
-Hypothesizerは'Edit Cell'ボタンをクリックし、ダミーウィンドウが開く。
現時点では、このウィンドウはダミーであって、セルデータを表示はしない。
<このシリーズの、前の記事 | このシリーズの目次 |