LibreOffice5(20)Anaconda3のtkinterモジュールを使う

2016-01-08

旧ブログ

t f B! P L

前の関連記事:LibreOffice5(19)イベント駆動する拡張機能のJavaの例:AsyncJob.oxt その3


LibreOffice 4.5 SDK - Developer's Guide ExamplesのAsyncJobのJavaの例ではメッセージボックスとしてjava7のjavax.swing.JOptionPaneのshowMessageDialog()メソッドを使っています。それはピアオブジェクトがない状況ではそれを作成したツールキットを取得できないのでUNOのウィンドウオブジェクトも描けないからだと思います(未確認)。(LibreOffice(32)デベロッパーガイド4:コンポーネントフレームワーク参照。)
(2016.1.10追記。tkinterに代わってAnaconda3のデフォルトパッケージにあったPyQt4を使うことにしました。linuxBean14.04(96)Anaconda3のPyQtモジュールを使う参照。)

ノンモダルなダイアログ


どうしてバンドルPythonからanaconda3のtkinterモジュールを使いたいかというと単にLibreOffice 4.5 SDK - Developer's Guide ExamplesのAsyncJobのJavaの例をPythonに翻訳したいためだけです。

ノンモダルなメッセージボックスの作成が目的ではありません。

ノンモダルとモダルの解説についてはOOoBasic/Dialog/Example10 - ...?がわかりやすいです。

LibreOfficeでモダルなウィンドウを表示している間そのウィンドウを閉じない限りLibreOfficeの他のウィンドウが操作できません。

ノンモダルなウィンドウであればそのウィンドウの有無に関係なく他のLibreOfficeのウィンドウの操作ができます。

ノンモダルなダイアログ(モードレスダイアログともいうようです)のBasicでの作り方はOOoBasic/Dialog/Example10 - ...?に解説があります。

OOoBasic/Dialog/CreateDialog - ...?OOoBasic/Dialog/Example28 - ...?もノンモダルなダイアログ作成例があります。

これはBasicでの例です。

LibreOfficeのダイアログ自体はBasicでつくるしかないようですが、そのダイアログをPythonで呼び出す例はダイアログにあります。

ドキュメントに埋め込んだPythonからダイアログを呼び出すときの例はOOoPython/Dialogs - ...?にあります。

そのうちノンモダルなウィンドウが必要になったら試してみようと思います。

バンドルPythonでanaconda3のtkinterモジュールを使う


linuxBean14.04(86)AnacondaのパッケージをLibreOfficeマクロで使うのように
~/.local/lib/python3.3/site-packages/sites.pthをを作成しておく必要があります。

25.1.2.2. 簡単な Hello World プログラムの例を/opt/libreoffice5.0/program/pythonをインタープリタにして実行してみるとエラーが出て動きません。
/opt/libreoffice5.0/program/python /home/pq/.config/libreoffice/4/user/Scripts/python/LO5-18-1/tkinter_test.py
Traceback (most recent call last):
  File "/home/pq/.config/libreoffice/4/user/Scripts/python/LO5-18-1/tkinter_test.py", line 20, in <module>
    root = tk.Tk()
  File "/home/pq/anaconda3/envs/py335/lib/python3.3/tkinter/__init__.py", line 1807, in __init__
    self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
_tkinter.TclError: Can't find a usable init.tcl in the following directories: 
    /opt/anaconda1anaconda2anaconda3/lib/tcl8.5 /opt/libreoffice5.0/lib/tcl8.5 /opt/lib/tcl8.5 /opt/libreoffice5.0/library /opt/library /opt/tcl8.5.18/library /tcl8.5.18/library



This probably means that Tcl wasn't installed properly.


Process finished with exit code 1
ちゃんとanaconda3のtkinterモジュールを読み込んでいますが、そこからライブラリの取得に失敗しています。

Python - Tkinterを使うときの環境変数 - Qiita

これを参考に以下の行を最初に追加すると動きました。
# 環境変数の設定
import os
os.environ['TCL_LIBRARY'] = '/home/pq/anaconda3/envs/py335/lib/tcl8.5'
os.environ['TK_LIBRARY'] = '/home/pq/anaconda3/envs/py335/lib/tk8.5
/home/pqの部分はユーザーフォルダのパスです。
# 環境変数の設定
import os
os.environ['TCL_LIBRARY'] = os.environ['HOME'] + '/anaconda3/lib/tcl8.5'
os.environ['TK_LIBRARY'] = os.environ['HOME'] + '/anaconda3/lib/tk8.5'
もうちょっと汎用的に書き直してみました。

linuxBean14.04(86)AnacondaのパッケージをLibreOfficeマクロで使うでパスを設定して利用しているanaconda3のライブラリはpy335という環境のものですがこれは自分で作ったものなので同じバージョンのanaconda3のデフォルトの環境のtclライブラリを指定しています。


こんな小さなウィンドウが出現しました。

click meとあるボタンをクリックするとコンソールにhi there, everyone!が出力されました。

QUITボタンをクリックするとウィンドウを閉じます。

これでオートメーションではtkinterが使えることはわかりました。

マクロモードでanaconda3のtkinterモジュールを使う


今度はマクロモードでtkinterが使えるかやってみました。

マクロで呼び出せるようにモジュールのグローバルスコープのコードをtkinter_test()という関数に入れます。

tclライブラリの環境変数の設定はグローバルスコープで設定するとマクロセレクターでtkinter_test()が見えなくなったのでtkinter_test()のスコープの入れました。

これでマクロから呼び出してみましたが動きません。


argvがどうこうというエラーがでてきます。

29.1. sys — システムパラメータと関数 — Python 3.5.1 ドキュメントをみるとこれは引数のリストとわかります。

tkinterはsys.argv[0]、つまり実行している引数名を必要としているようです。

マクロモードでは何を入れたらよいのかわかりませんでしたが適当な文字列を入れてみたら解決しました。
import tkinter as tk
class Application(tk.Frame):
    def __init__(self, master=None):
        tk.Frame.__init__(self, master)
        self.pack()
        self.createWidgets()
        self.master = master
    def createWidgets(self):
        self.hi_there = tk.Button(self)
        self.hi_there["text"] = "Hello World\n(click me)"
        self.hi_there["command"] = self.say_hi
        self.hi_there.pack(side="top")
        self.QUIT = tk.Button(self, text="QUIT", fg="red", command=self.master.destroy)
        self.QUIT.pack(side="bottom")
    def say_hi(self):
        print("hi there, everyone!")
def tkinter_test():
    # tclライブラリの環境変数の設定
    import os
    os.environ['TCL_LIBRARY'] = os.environ['HOME'] + '/anaconda3/lib/tcl8.5'
    os.environ['TK_LIBRARY'] = os.environ['HOME'] + '/anaconda3/lib/tk8.5'
    import sys
    sys.argv = ['macro']  # マクロモードでのみ必要。sys.argvがないのでtkinterでエラーがでる。
    root = tk.Tk()
    app = Application(master=root)
    app.mainloop()
if __name__ == "__main__":
    import unopy
    XSCRIPTCONTEXT = unopy.connect()
    if not XSCRIPTCONTEXT:
        print("Failed to connect.")
        import sys
        sys.exit(0)
    tkinter_test()
これをマクロモードで呼び出すとtkinterのダイアログが表示されました。


モダルダイアログになっています。

ドラッグすると残像が残ります。

どうも動作がおかしいです。

参考にしたサイト


LibreOffice 4.5 SDK - Developer's Guide Examples
AsyncJobの例ではノンモダルメッセージボックスとしてjava7のshowMessageDialog()メソッドを使っています。

JOptionPane (Java Platform SE 7 )
showMessageDialog()メソッドをもつJava7のクラス。

OOoBasic/Dialog/Example10 - ...?
モダルとノンモダルダイアログの違いとノンモダルダイアログの例。

OOoBasic/Dialog/CreateDialog - ...?
ノンモダルダイアログの例。

OOoBasic/Dialog/Example28 - ...?
ノンモダルダイアログの例。

OOoPython/OverView - ...?
ダイアログエディタで作成したダイアログをPythonから利用する例。

OOoPython/Dialogs - ...?
ドキュメントに埋め込んだダイアログを呼び出すPythonの例。

25.1. tkinter — Tcl/Tk の Python インタフェース — Python 3.3.6 ドキュメント
Pythonの標準モジュールのtkinterを使う例。

Python - Tkinterを使うときの環境変数 - Qiita
tkinterをインストールしたインタープリタ以外のインタープリタから使うときは環境変数の設定が必要です。

お気楽 Python/Tkinter 入門
tkinterの解説。

次の関連記事:LibreOffice5(21)ダイアログエディタでGUIを作成しPythonで利用する:その1

ブログ検索 by Blogger

Translate

最近のコメント

Created by Calendar Gadget

QooQ