2018年1月7日日曜日

31: UNO拡張機能(LibreOffice拡張機能またはApache OpenOffice拡張機能)内でSwing GUIを使う方法

<このシリーズの、前の記事 | このシリーズの目次 |

本文 START

UNO拡張機能(LibreOffice拡張機能またはApache OpenOffice拡張機能)内でSwing GUIを使う方法を知る

話題: UNO (Universal Network Objects)

話題: LibreOffice

話題: Apache OpenOffice

話題: Javaプログラム言語

実のところ、UNO拡張機能では、GUIをただ使うというわけにはいかない

バイアス惑星の山あいの小川のほとりのある部屋で-Hypothesizerと-Rebutterがコンピュータースクリーンの前に座っている。

-Hypothesizer

UNO拡張機能の中でGUIを実装しようと思う。

-Rebutter

うーむ、 . . . それがどうした?JavaでUNO拡張機能を開発できるのだから、JavaFX、Swing、その他何でもただ使えばいいだけではないのか?

-Hypothesizer

実のところ、そういうわけではない。気をつけなければならないことがいくつかある。

-Rebutter

ほう?何だそれらは?

-Hypothesizer

最も重要なことは、Linux上では、UNO拡張機能で、JavaFXを使えないようだということだ。

-Rebutter

どうやら、Windows上では、UNO拡張機能で、JavaFXを使えると言っているようだな。

-Hypothesizer

Windows上でJavaFXの単純なダイアログを表示できることから、そのように私は推測している。我々のメインのマシンはLinuxなので、実際には、私はそれ以上調査していない。Windows上だけで使えるのでは我々の役には立たないから。

-Rebutter

Linux上ではなぜUNO拡張機能でJavaFXを使えないのか?

-Hypothesizer

以下が私の推測だ。JavaFXはGDKを使っている、LibreOfficeがそうであるように。JavaFXはGDKのメインループを作ろうとするのだが、このメインループは、LibreOfficeのGDKのメインループと同一プロセス内で共存できないようだ。

-Rebutter

ああ、JavaFXプログラムはFXプログラムインスタンスと指定して実行されるように想定されているので、LibreOfficeプログラムインスタンスの中で動くJVMでJavaFXを使えないのは自然かもしれない。

それで、Linux上、UNO拡張機能の中でJavaFXを使おうとすると、何がおきるのか?

-Hypothesizer

JavaFXの初期化が、受け取るべき一部のイベントを受け取ることができず、フリーズする。結果的に、LibreOfficeプログラムインスタンス全体がフリーズする。

-Rebutter

ふーむ、 . . . それでは、回避策は何もないのか?

-Hypothesizer

少なくとも、私は知らない。ただ、究極の解決策はある。

-Rebutter

それは何だ?

-Hypothesizer

GUIサーバーをUNOサーバーとして作ることができる。

-Rebutter

ああ、シリーズ、「外部JavaプログラムでUNOを使用する(LibreOfficeまたはApache OpenOfficeのドキュメントを操作する)方法」で話したように、UNOサーバーを作ることができる。UNOサーバーは独立したJavaプログラムなので、JavaFXだろうがJavaの他のどの機能だろうが、制限があるはずがない。

-Hypothesizer

Swingは問題なく使えるので(後で話すとおり、ある落とし穴はあるが)、その解決策を追求するのはまたの機会にしよう。

-Rebutter

いいだろう。

-Hypothesizer

言っておくが、UNO拡張機能の中で使うように推奨されているGUIライブラリがあるが、我々は従わない、なぜなら . . .

-Rebutter

. . . 我々の性格がゆがんでいるからか?

-Hypothesizer

それはここでの理由ではない、そのとおりではあるが、ある程度。理由は、そのライブラリがSwingやJavaFXほど便利だとも機能豊富だとも私は予想していないから。

-Rebutter

それは、何らかの事実に基づいているのか?

-Hypothesizer

当て推量と言うべきだろう。. . . 別の理由は、UNO拡張機能を開発するためだけのために、新たにGUIライブラリを学びたくないことだ。

-Rebutter

それは理解できる。

-Hypothesizer

必要であれば、GUIサーバーという解決策を選ぶだろう、そのGUIライブラリを使うというものではなく。

UNO拡張機能の中でSwingを使う前に、行なわければならない1つのことは何か?

前場と同じ。

-Hypothesizer

Swingは、UNO拡張機能の中で問題なく使えるが、Swingを使いはじめる前に行なわければならないことが1つある。

-Rebutter

それは何だ?

-Hypothesizerは、Javaのソースコードを開き、ある行を指差す。

-Hypothesizer

この行を呼ばなければならない。

@Java Source Code
  Thread.currentThread ().setContextClassLoader (ClassLoader.getSystemClassLoader ());

-Rebutter

うーむ、 . . . クラスローダーをカレントスレッドに登録しているのか?

-Hypothesizer

そうだ。Swingはそれを使うが、それは、LibreOfficeが用意したJVMには登録されていない、なぜだか。

-Rebutter

ふーむ。. . . それでは、それを行ないさえすれば、UNO拡張機能の中でSwingを何の問題なく使えるのか?

-Hypothesizer

私が知る限り、そうだ。

サンプルを作ろう

前場と同じ。

-Hypothesizer

サンプルを作ろう。

各ボタンが各機能を起動するボタン群を持つコントロールパネルはどうだろう?

-Rebutter

コントロールパネルは結構だが、どんな機能だ、例えば?

-Hypothesizer

うーむ、 . . . セルエディターはどうだろう?

-Rebutter

「セルエディター」というのは何だ?

-Hypothesizer

スプレッドシートはデータをグリッド状に整理するのに便利だが、セルに長いテキストを入れると、セルの中でテキストを見たり編集したりするのに難儀する。

-Rebutter

実際、数字や短いテキストだけを扱う限りは良いが、長いテキストも扱わなければならない場合、スプレッドシートは事実上使い物にならなくなる。

-Hypothesizer

もし、我々のセルエディターで長いテキストが扱えれば、そうした場合でもスプレッドシートを便利に使える。

-Rebutter

ふーむ . . .

-Hypothesizer

この記事では、コントロールパネルを作ることに集中しよう。この段階では、セルエディターはダミーだ。

-Rebutter

まあ、我々は既に、スプレッドシートセルから読んだりスプレッドシートセルに書いたりする方法を知っているので、セルエディターを作るのは、UNO拡張機能内でGUIを使う方法を知ってさえいれば、単にJavaプログラミングの問題だ。

-Hypothesizer

そのとおり。

コントロールパネルを表示するのは単にSwingプログラミングの問題だが、ここでは、コントロールパネルを、LibreOfficeのカレントフレームに対して相対的に適切な場所に表示しよう。

-Rebutter

ああ、それでは、我々は、コントロールパネルに、スクリーンのランダムな位置や固定の位置に表示されてほしくないわけだ。

-Hypothesizer

我々は、コントロールパネルを、LibreOfficeのカレントフレームの左境界の隣に表示しよう。

-Rebutter

そこにスペースがなかったらどうするのか?

-Hypothesizer

その場合は、LibreOfficeのカレントフレームの上に表示しなければならないだろう。

-Rebutter

どこに表示したいにしろ、問題は、LibreOfficeのカレントフレームの境界の位置をどのように得られるかということだ。

-Hypothesizer

以下のようにして得ることができる。

-Hypothesizerは、先程ののJavaソースファイルのあるセクションを選択する。

@Java Source Code
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);

-Rebutter

ふむ、'thebiasplanet'パッケージ配下のクラス群は、我々のユーティリティクラスだ。

-Hypothesizer

過去の記事で既に説明したコードについては、我々は、また明示的に示すことはせず、我々のユーティリティクラスを使うかもしれない。ユーティリティクラスは我々の各種zipファイルに含まれているので、必要であれば、それらの中を見ればよい。

-Rebutter

いいだろう。

-Hypothesizer

我々のサンプルプログラムは、ここにある。.

-Rebutter

以前に引用したサンプルUNO拡張機能プロジェクトに実装したのか。

-Hypothesizer

そうだ。zipファイルの使い方は、そこに書いてある。我々はいくつかの記事で引用されているプロジェクトにコードを追加するので、ある記事で引用されているプロジェクトがその記事とは関係ないコードを含んでいることがあり得る。そうしたコードは、他の記事から来ている。

-Hypothesizerはgradleコマンドを実行し、 コマンドは正常終了する。-Hypothesizerは、'TestSpreadSheetsDocumentForExecutingTests.ods'スプレッドシートドキュメントを開く。

-Rebutter

シートに第2のボタンを追加したのか。

-Hypothesizer

そうだ。ボタンを押す前に、LibreOffice Basicライブラリをインポートしなければならない、過去の記事に記載されているように。

-Hypothesizerは、'Show Test Control Panel'ボタンをクリックし、小さなダイアログボックスが、LibreOfficeのカレントフレームの左境界の隣に表示される。

-Rebutter

. . . 「コントロールパネル」と呼ぶには印象の薄いしろものだな . . .

-Hypothesizer

印象が薄かろうがなかろうが、コントロールパネルだ。'Edit Cell'ボタンをクリックすると、セルエディターが表示される。

-Hypothesizerは'Edit Cell'ボタンをクリックし、ダミーウィンドウが開く。

-Rebutter

現時点では、このウィンドウはダミーであって、セルデータを表示はしない。

本文 END

<このシリーズの、前の記事 | このシリーズの目次 |