Eclipse: PyDevメモ: LibreOfficeのPythonマクロのリスナーの問題点

2017-08-11

旧ブログ

t f B! P L
リスナーのメソッドでブレークしたときの問題点を見つけました。マウスが使えなくなる問題は、図らずもEclipse: PyDevメモ: LibreOfficeのPythonマクロのデバッグのenableRemoteDebuggingデコレーターを使えば発生しなくなりました。

前の関連記事:Eclipse: PyDevメモ: LibreOfficeのPythonマクロのデバッグ


リスナーのメソッドの問題点


linuxBean14.04(Ubuntu 14.04)、LibreOffice 5.2.6.2の組み合わせで気が付いた問題点です。

1 1回のイベントで複数回発火するリスナーがある

UnoControlCurrencyFieldをサブジェクトにしたXTextListenerのtextChanged()メソッドは、1回のイベント発生で4回も発火しました。

UnoControlEditをサブジェクトにしたXFocusListenerのfocusGained()メソッドは、1回のイベントで2回発火しました。

focusLost()メソッドも1回のイベントで同様に2回発火しました。

UnoControlScrollBarをサブジェクトにしたXAdjustmentListenerのadjustmentValueChanged()メソッドも1回のイベントで2回発火しました。

無駄な発火を防ぐにはLibreOfficeのソースをみて対策しないといけなさそうですが、それはC++が書けないとなかなか重荷です。

そこまでしなくても無駄な実行をしないために、サブジェクトのプロパティの変化をみて2回目以降の実行をスキップさせる処理を加えるようにしています。

それでもUnoControlScrollBarの場合はスクロールバーの位置が変化した値が返ってくるのでいまのところ実行を1回だけに限定させることには成功していません。

リスナーのメソッドで発生した例外がわからない

リスナーの__init__()メソッド以外のメソッドでは、例外が発生してもLibreOfficeのエラーメッセージウィンドウが表示されません(確認したのはランタイムダイアログのコントロールをサブジェクトにしたリスナーです)。

疑わしいリスナーのメソッドをリモートデバッグでブレークして調べるしかありません(Eclipse: PyDevメモ: LibreOfficeのPythonマクロのデバッグ参照)。

3 オートメーションではブレークポイントで止まらない

オートメーションではリスナーのメソッドにブレークポイントを張ってデバッガを起動してもそこでは止まりません。

なので、代替策としてリモートデバッグでブレークするしかありません。

4 オートメーションで発火しないリスナーがある

LibreOffice5(59)モードレスダイアログの例をPythonに翻訳する:その5でやったようにモードレスダイアログにするとXActionListenerのactionPerformed()メソッドが発火しませんでした。

モダルダイアログであっても、UnoControlDateFieldをサブジェクトにしたXSpinListenerのup()メソッドは発火しませんでした。

サブジェクトをUnoControlFormattedFieldにするとちゃんと発火しました。

マクロモードで発火しないリスナーにはいまのところ出会っていないので、リスナーの動作確認にはマクロモードかUNOコンポーネントモードを使わないといけません。

5 ブレークするとマウスが使えなくなるリスナーがある

XAdjustmentListenerのadjustmentValueChanged()メソッド内でブレークするとマウスボタンが無効になります。

LibreOfficeからEclipseに切り替えても、メソッドから抜けない限りマウスボタンが使えませんので、ショートカットキーでPyDevを操作しないといけません。

この問題はEclipse: PyDevメモ: LibreOfficeのPythonマクロのデバッグで作成したデコレーターenableRemoteDebuggingを使うことで回避できました。

偶然に解決したものですが、リスナーのメソッドが発火してからpydevd.settrace()をする前に、ステータスバーを使用するとマウスボタンが使えるようになりました。

ステータスバーを表示させる部分をコメントアウトするとやはりマウスボタンが使えなくなりました。

これらの問題点について検索しても何も参考ページが見つからなかったので私の環境特有の問題点かもしれません。
(2018.2.13追記。ドキュメントに追加したリスナーでもブレークするとマウスが使えなくなるときがありました。リスナーのメソッド内ではなく、そこから呼び出した関数内でブレークするとマウスは使えました。)

リスナーのメソッドにブレークポイントを張った結果


上に書いたリスナーのメソッドの問題点を書くために、リスナーのメソッドにリモートデバッグでブレークポイントを張ったときの挙動について調べた結果です。

GUI/unodialogsample_tmp.py at 7fa822613fa981a6f6bf5c84de540213c0756c30 · p--q/GUI

ランタイムダイアログを生成しているこのマクロを使って調べました。

サブジェクト(パブリシャ)によって異なる結果があったので、どのオブジェクトにつけたリスナー(つまりサブジェクト)なのかも記録しました。

XActionListenerのactionPerformed()メソッド

サブジェクト: UnoControlButton 問題なし。

オートメーションで起動したランタイムダイアログでも発火します。

リスナーの問題点ではありませんが、FilePickerサービスをオートメーションでインスタンス化するとLibreOfficeがクラッシュしました。

XMouseListenerのmouseEntered()メソッド

サブジェクト: UnoControlFixedText 問題なし。

オートメーションで起動したランタイムダイアログでも発火します。

XTextListenerのtextChanged()メソッド

サブジェクト: UnoControlCurrencyField なぜか1回のイベントで4回も発火します。

オートメーションで起動したランタイムダイアログでも発火します。

XFocusListenerのfocusGained()メソッド

サブジェクト: UnoControlEdit なぜか1回のイベントで2回発火します。

オートメーションで起動したランタイムダイアログでも発火します。

このfocusGained()メソッドはサブジェクトが画面に出てくるたびに呼び出されるので、デバッガのウィンドウに切り替えるときにサブジェクトが隠れるようにウィンドウを配置してしまうと、永遠とfocusGained()メソッドが呼び出され続けることになるので注意が必要です。

XFocusListenerのfocusLost()メソッド

サブジェクト: UnoControlEdit なぜか1回のイベントで2回発火します。

オートメーションで起動したランタイムダイアログでも発火します。

XKeyListenerのkeyPressed()メソッド

サブジェクト: UnoControlEdit 問題なし。

オートメーションで起動したランタイムダイアログでも発火します。

XSpinListenerのup()メソッド

サブジェクト: UnoControlDateField 問題なし。

オートメーションで起動したランタイムダイアログでは発火しませんでした。

サブジェクト: UnoControlFormattedField 問題なし。

オートメーションで起動したランタイムダイアログでも発火します。

XItemListenerのitemStateChanged()メソッド

サブジェクト: UnoControlCheckBox 問題なし。

オートメーションで起動したランタイムダイアログでも発火します。

XAdjustmentListenerのadjustmentValueChanged()メソッド

サブジェクト: UnoControlScrollBar 

オートメーションで起動したランタイムダイアログでも発火します。

ブレークしたところでマウスが使えなくなります。

1回のイベントで2回発火します。

XCloseListenerのnotifyClosing()メソッド

サブジェクト: Frame 問題なし。 

オートメーションで起動したランタイムダイアログでも発火します。

(2017.11.17追記

XEnhancedMouseClickHandlerのmousePressed()メソッド

サブジェクト: Calcのコントローラ。

やはりマウスがらみのリスナーはデバッグしにくいです。

enableRemoteDebuggingはクリックするたびに起動してフリーズするので、クリック数で場合分けした後にimport pydevd; pydevd.settrace(stdoutToServer=True, stderrToServer=True)でブレークする方法でうまくいきました。
(Calc(27)ドキュメント内のすべてのシートでクリックを補足する参照)

XSelectionChangeListenerのselectionChanged()メソッド

サブジェクト: Calcのコントローラ。

これはenableRemoteDebuggingでは全く何もできなくなって、OSの再起動が必要になりました。

import pydevd; pydevd.settrace(stdoutToServer=True, stderrToServer=True)でブレークすることはできますが、マウスは使えずすべてショートカットキーで操作しないといけません。)

ショートカットキーでPyDevのデバッガーを操作する方法


Eclipse: PyDevメモ: LibreOfficeのPythonマクロのデバッグのデコレーターenableRemoteDebuggingを導入するまではPyDevをマウスを使わずに操作しないといけないときがありました。

もう回避策をみつけたのでショートカットキーで操作する必要はなくなりましたが、学習結果を残しておきます。

ブレークポイントを設定したマクロをLibreOfficeで起動して、Eclipseのデバッグサーバーに接続して、Debugパースペクティブのエディタビューでブレークされている状態からの一連の操作手順を示します。


Alt+tab アプリケーションを切り替える

Altキーを押しながらtabキーを押してEclipseが選択されるようにしてキーを離すとEclipseに切り替わります。


Ctrl+F8 パースペクティブを切り替える

Ctrlキーを押しながらF8キーを押してDebugパースペクティブに切り替えます。


Ctrl+F7 ビューを切り替える

Ctrlキーを押しながらF7キーを押してビューを切り替えます。

ステップオーバーなどはビューに関係なくできるので、切り替えるビューはVariablesかConsoleになるでしょう。


Variablesビューでは上下の矢印キーで変数を移動できます。

変数の折り畳みを展開するにはEnterキーを使います。

展開した変数でEnterキーを押すと今度は折り畳められます。

F5 ステップイン
F6 ステップオーバー
F7 ステップリターン
F8 リズーム

これらはビューに関係なく操作できます。

Ctrl+F2 Terminate

だいたいこれぐらいの操作ができれば、マウスが使えない状態を脱出できると思います。

参考にしたサイト


【eclipse】ショートカットキー一覧(よく使うもの抜粋) at softelメモ
Eclipseの主なショートカットキーの解説。

PyDev Shortcut Cheat Sheet Cheat Sheet by WaltheRed - Download free from Cheatography - Cheatography.com: Cheat Sheets For Every Occasion
PyDevのショートカットキー一覧。

ブログ検索 by Blogger

Translate

最近のコメント

Created by Calendar Gadget

QooQ