PyMOLでダイアログを表示しよう
PyMOLはPythonスクリプトを使用して作成されており、そのAPIを使用することでユーザーが機能を自由に追加できるようになっています。ここでは、GUIを作成し、そこから機能を追加する方法の基礎を解説します。
Python経験者向き。複雑なGUIを作成するならTkinterまたはPython MegaWidgetsの使用経験がある方がいいでしょう(私は今回初めて使いましたが・・・)。動作確認はPyMOL 1.2r2 + Vine 5.1 + Python 2.5.4で行いました。
開発時の注意
GUIを表示する場合は作成したプラグイン起動時にPyMOLアプリケーションオブジェクトPMGAppを渡す必要がありますが、開発時にPyMOLコマンドラインからプラグインをコールするときにはアプリケーションオブジェクトが取得できません(私が調べた限り)。そのため、アプリケーションオブジェクトが簡単に取得できるようにpmg_tk/startup/develop.py中で以下を定義しておきました。
def __init__(self): self.pymol.cmd.app = self
これでPyMOLコマンドラインからcmd.appを通してPMGAppオブジェクトにアクセスすることができるようになります。通常、ダイアログはPyMOL External Menuから起動し、引数としてコンストラクタに渡すことができるのであくまで開発用のセッティングと考えてください。
シンプルな自作ダイアログボックス
ここではファイル選択ボタンとテキスト入力をもつシンプルなダイアログボックスのサンプルを示します。
コードと解説
- simpledlg.py
import Pmw, Tkinter, tkFileDialog # TkinterおよびPython MegaWidgets from pymol import cmd # PyMOL APIオブジェクト class FileAndTextDialog(Pmw.Dialog): __slots__ = ("txtFile", "txtText", "app") def __init__(self, app): """ オーナーをapp.rootとしてダイアログを作成 """ Pmw.Dialog.__init__(self, app.root, title="Input Dialog", buttons=("OK", "Cancel"), command=self.execute) self.withdraw() self.app = app self.txtFile = Tkinter.StringVar() self.txtText = Tkinter.StringVar() root = self.interior() Tkinter.Label(root, text="Select file").grid(row=0, column=0) Tkinter.Entry(root, textvariable=self.txtFile).grid(row=0, column=1) Tkinter.Button(root, text="...", command=self.select_file).grid(row=0, column=2) Tkinter.Label(root, text="Input text").grid(row=1, column=0) Tkinter.Entry(root, textvariable=self.txtText).grid(row=1, column=1) def execute(self, result): """ resultにクリックされたボタンの値が代入される """ if result == "OK": pass # TODO: ここにOKをクリックしたときの動作を記述 self.destroy() # このダイアログを閉じる def select_file(self): """ ファイル選択ダイアログを開く """ self.txtFile.set(tkFileDialog.askopenfilename(filetypes=[("Log file","*.log")]))
PyMOLからの呼び出し
External GUIからの呼び出し
External GUIから呼び出すために__init__でPluginメニューに項目を追加します。なお、PyMOL起動時にpmg_tk/startup/*.pyが読み込まれるので標準のインストールでは/usr/lib/python2.5/site-packages/pmg_tk/startup/以下に作成したプラグインのスタートアップスクリプトを登録しておきます。内容は以下のような感じ。
from simpledlg import FileAndTextDialog def __init__(self): # Simply add the menu entry and callback self.menuBar.addmenuitem('Plugin', 'command', 'Sample Tool', label='Sample Tool', command=lambda s=self: SampleToolCaller(s)) class SampleToolCaller(object): def __init__(self, app): dlg = FileAndTextDialog(app) dlg.show()
このスクリプトは、PyMOL起動時に__init__がコールされPluginメニューにSample Toolという項目が追加されます。Plugin->Sample ToolがクリックされるとSampleToolCallerクラスがコールされ、コンストラクタSampleToolCaller#__init__()が実行されるとFileAndTextDialogダイアログが表示されます。