GUIパネルを作成
eSEATでは、PythonのTkinterモジュールを使ったGUIパネルの作成機能を実装しています。eSEATの内部では、以下に記載されたGUI要素をSEATLML内で定義した場合のみ、Tkinterの初期化とメインループをTkinterの方へ切り替えを行っています。
このメインループ部分の実装は、rtm.eSEATManagerの中では下記のようになっています。
このメインループ部分の実装は、rtm.eSEATManagerの中では下記のようになっています。
if self.comp.hasGUI() :
self.manager.runManager(True)
# GUI part
self.comp.root = Tk()
for st in self.comp.states:
self.comp.newFrame(st)
self.comp.create_gui(st)
self.comp.show_frame(self.comp.init_state)
self.comp.frames[self.comp.init_state].pack()
self.comp.setTitle(self.comp.getInstanceName())
self.comp.root.mainloop()
self.comp.disconnectAll()
# Shutdown Component
try:
self.manager.shutdown()
except:
pass
sys.exit(1)
else:
self.manager.runManager()
OpenRTM-aistがインストールされていないか、eSEAT_Nodeコマンドで起動した場合にもcore.Managerでほぼ同等の実装がされています。
レイアウトについて
eSEATのGUIパネル作成機能は、最低限のGUIを実現することを念頭において実装していますので、あまりいろいろなことはできません。また、GUIアイテムのレイアウトもGRID形式のみをサポートしており、複雑なレイアウトや各アイテムの大きさの調整等は実装していません。すなわち、基本的には、HTMLの表のようなパネルをイメージし、各アイテムがSEATMLスクリプト内での出現順に左から右へ各アイテムが配置されていきます。
このGUIパネル生成機能の例として、インストール時の動作確認時に示したexamples/TestaGuu.seatmlのようなレイアウトが作成できます。この例では、3x6(横x縦)のレイアウト例になります。
GUIを構成する要素
eSEATでは、Tkinterを使っていますが、すべてのGUIパーツを使えるわけではありません。しかし、最低限のGUIパネルが作成できるように、以下の要素が定義されています。
フレームとして、frame要素、labelframe要素を使うことができ、GUIのアテムとして、label, button, entry, text, combobox, listbox, checkbutton, radiobutton, scaleを使うことができます。また、レイアウト用としてbrk要素とspace要素を定義しています。
フレームとして、frame要素、labelframe要素を使うことができ、GUIのアテムとして、label, button, entry, text, combobox, listbox, checkbutton, radiobutton, scaleを使うことができます。また、レイアウト用としてbrk要素とspace要素を定義しています。
frame要素
frame要素は、TkinterにおけるFrameになります。複数のGUIアイテムをまとめる時に使用します。frame要素は、下記の属性を使うことができます。
タグ名 | |
<frame> | |
属性 | |
name | 識別子 |
height | フレームの高さ |
width | フレームの幅 |
relief | フレームの形状 (flat, raised, sunken, groove, ridge) を指定できる |
color | テキストの色 |
bg_color | フレームの背景色 |
colspan | レイアウト時の横方向の結合幅(デフォルトは1) |
rowspan | レイアウト時の縦方向の結合幅(デフォルトは1) |
frame | 親フレーム。省略時はGUIのrootパネル |
子要素 | |
なし |
labelframe要素
labelframe要素は、frameとほぼ同じなのですが、デフォルトで枠とタイトルをつけることができます。
タグ名 | |
<labelframe> | |
属性 | |
label | 表示する文字列(タイトル)。eSEAT内部では識別子として使用 |
height | フレームの高さ |
width | フレームの幅 |
labelanchor | 見出しラベルの位置 (nw, n, ne, e, se, s, sw, w) を指定できる |
relief | フレームの形状 (flat, raised, sunken, groove, ridge) を指定できる |
color | テキストの色 |
bg_color | フレームの背景色 |
colspan | レイアウト時の横方向の結合幅(デフォルトは1) |
rowspan | レイアウト時の縦方向の結合幅(デフォルトは1) |
frame | 親フレーム。省略時はGUIのrootパネル |
子要素 | |
なし |
TestGui.seatmlファイルにおけるlabelframe要素は、下の図の赤枠の部分になります。
また、この部分のSEATMLは、下のように記述できます。
<labelframe label="RadioButtons" colspan="2" />
label要素
label要素は、単純な文字列表示のラベルアイテムを生成します。この要素は、''text''属性を必須属性としており、必ず設定しなければいけません。このtext属性値がLabelアイテムに表示されます。また、オプション属性として''color'', ''bg_color'', ''colspan''の属性を設定することができます。
''color''属性と''bg_color''属性は、それぞれLabelアイテムの文字列の色、背景の色に対応しており、text属性値、color属性値、bg_color属性値が name, fg, bg だった場合に、eSEAT内部では、
Label(frame, text=name, bg=bg, fg=fg )
のようにLabelアイテムを生成します。
また、colspan属性は、Labelアイテムをパネルに配置する場合に指定可能な属性です。
eSEATでは、GRID形式のアイテム配置packのみを利用するようにしています。そのため、横方向に何カラム分の大きさで配置するかをこの属性値で設定することができます。
タグ名 | |
<label> | |
属性 | |
text | 表示するテキスト[必須] |
color | テキストの色 |
colspan | レイアウト時の横方向の結合幅(デフォルトは1) |
rowspan | レイアウト時の縦方向の結合幅(デフォルトは1) |
frame | 親フレーム。省略時はGUIのrootパネル |
args | その他のオプション |
子要素 | |
なし |
TestGui.seatml内でのlabel要素は、下図の赤枠の部分になります。
これらのアイテムのSEATML内での記述は、下記の通りです。
<label text="TestGui" colspan="3" bg_color="blue" />
<label text="Input:" />
<label text="Coming Text:" />
また新たにLabelには、args属性を定義しています。これは、Labelを生成時にその他のオプションを設定するためのテスト実装です。上記の最初のラベルのフォントを変更する場合には、下記のように書くことができます。
<label text="TestGui" colspan="3" bg_color="blue" args="font=('helvetica', 20), height=3"/>
button要素
button要素は、単純な文字列をラベルとして持つのボタンアイテムを生成します。この要素は、label属性を必須属性として必ず設定しなければならず、この文字列を持ったボタンアイテムを生成し、配置します。
また、オプション属性として、''color'',''bg_color'', ''colspan''を設定することができます。このオプション属性を設定することでGUIパネル上のボタンアイテムの見た目を変更することができます。各属性の機能としては、label要素と同じです。
また、この要素は子要素としてコマンド要素を持つことができます。対応するボタンアイテムが押下された場合に、子要素であるコマンド要素が動作します。
この要素は、rule要素と非常によく似た動作をしますが、rule要素が外部からのデータによって駆動しますが、button要素は、GUIのボタンを押下することで動作することが大きな違いです。
この要素は、rule要素と非常によく似た動作をしますが、rule要素が外部からのデータによって駆動しますが、button要素は、GUIのボタンを押下することで動作することが大きな違いです。
タグ名 | |
<button> | |
属性 | |
label | 表示するテキスト[必須] |
color | テキストの色 |
bg_color | 背景の色 |
width | Buttonの幅 |
colspan | レイアウト時の横方向の結合幅(デフォルトは1) |
rowspan | レイアウト時の縦方向の結合幅(デフォルトは1) |
frame | 親フレーム。省略時はGUIのrootパネル |
子要素 | |
message | ボタンアイテム押下時に、sendto属性に指定されたポートに対して、子要素に記載された文字列を送信する |
shell | ボタンアイテム押下時に、子要素に記載された文字列を、system関数で評価し、Shellコマンドを実行する。 |
script | ボタンアイテム押下時に、execfile属性で指定されたPythonスクリプトファイルをexecfile関数で評価し、子要素に記載された文字列があれば、exec関数で評価しPythonスクリプトを実行する。 |
statetransition | ボタンアイテム押下時に、この要素は、eSEATの内部状態を別の状態に遷移させます。 |
log | ボタンアイテム押下時に、TEXT要素の内容をloggerに出力する。 |
TestGui.seatml内でのbutton要素は、下図の赤枠の部分になります。
これらのアイテムのSEATML内での記述は、下記の通りです。
<button label="Send">
<message sendto="str_out" input="main_mode:textIn" />
<message sendto="web" input="main_mode:textIn" />
</button>
<button label="Clear">
<script>
seat.clearText("main_mode:textOut")
</script>
</button>
input要素
input要素は、一行の文字列入力を行うためのGUIアイテムを生成します。eSEATの内部では、TkinterのEntryを用いて実現しています。
この要素は、id属性を必須属性として必ず設定しなければならず、この属性値を識別子として使用します。前述していますが、script要素のPythonスクリプトでこのアイテムの入力フィールドの中の文字列を得るには、
seat.getEntry('id属性値')
とします。また、このアイテムの入力フィールドに文字列を入れたい場合には、
seat.setEntry('id属性値', '入力したい文字列')
のようなスクリプトを設定してください。
例えば、下記のように''input1''というIDを持つinput要素と''exec''というラベルのbutton要素作成し、''input1''に入力したPythonのコマンドを実行させたい場合には、
<input id="input1" width="50" colspan="3"></input>
<button label="exec">
<script>
exec(seat.getEntry("input1"), globals())
</script>
</button>
と記述できます。
また、オプション属性として、''width''、''colspan''を指定することができます。''width''属性は、入力アイテムの幅を設定するための属性であり、単位は文字数です。上記の例では、50文字分の入力アイテムを生成します。
''colsoan''属性は、label要素やbutton要素の同名属性と同じ機能です。
''colsoan''属性は、label要素やbutton要素の同名属性と同じ機能です。
この要素でも、子要素としてコマンド要素を持つことができます。子要素が設定された場合にが、<ENTER>キー入力時に動作するようになっています。現在のところ入力アイテムにおける他のキーバインドについてカスタマイズは不可にしています。
タグ名 | |
<input> | |
属性 | |
id | 入力アイテムの識別子[必須] |
width | 入力アイテムの幅(文字数。省略時は20) |
colspan | レイアウト時の横方向の結合幅(デフォルトは1) |
rowspan | レイアウト時の縦方向の結合幅(デフォルトは1) |
frame | 親フレーム。省略時はGUIのrootパネル |
子要素 | |
message | <ENTER>キー入力時に、sendto属性に指定されたポートに対して、子要素に記載された文字列を送信する |
shell | <ENTER>キー入力時に、子要素に記載された文字列を、system関数で評価し、Shellコマンドを実行する。 |
script | <ENTER>キー入力時に、execfile属性で指定されたPythonスクリプトファイルをexecfile関数で評価し、子要素に記載された文字列があれば、exec関数で評価しPythonスクリプトを実行する。 |
statetransition | <ENTER>キー入力時に、この要素は、eSEATの内部状態を別の状態に遷移させます。 |
log | <ENTER>キー入力時に、TEXT要素の内容をloggerに出力する。 |
TestGui.seatml内でのinput要素は、下図の赤枠の部分になります。
これらのアイテムのSEATML内での記述は、下記の通りです。
<input id="textIn" width="50" >
<message sendto="str_out" input="main_mode:textIn" />
</input>
text要素
text要素は、複数行の文字列入力を行うためのGUIアイテムを生成します。eSEATの内部では、TkinterTextを用いて実現しています。
この要素は、id属性を必須属性として必ず設定しなければならず、この属性値を識別子として使用します。前述していますが、script要素のPythonスクリプトでこのアイテムの入力フィールドの中の文字列を得るには、
seat.getText('id属性値')
とします。また、このアイテムの入力フィールドに文字列を入れたい場合には、
seat.appendText('id属性値', '追加入力したい文字列')
とします。このメソッドは、現在のTextアイテム内に文字列を追加する機能であり、input要素のように文字列を置き換えるわけではありません。そのため、現在のアイテム内の文字列を消去するために clearTextというメソッドも定義しています。すなわち、
seat.clearText('id属性値')
とすれは、アイテム内の文字列をすべて消去します。
また、オプション属性として、''width''、''height''、'colspan''、''rowspan''を指定することができます。''width''属性は、入力アイテムの幅を設定するための属性であり、単位は文字数です。''height''属性は、入力アイテムの高さを設定するための属性であり、単位は行数です。''colsoan''属性は、label要素やbutton要素の同名属性と同じ機能です。''rowsoan''属性は、colspan属性の縦方向版です。
この要素でも、子要素としてコマンド要素を持つことができようになっています。しかしながら、現在のところ子要素としてコマンド要素を設定しても動作しないと思います。
タグ名 | |
<text> | |
属性 | |
id | 入力アイテムの識別子[必須] |
width | 入力アイテムの幅(文字数、省略時は20) |
height | 入力アイテムの行数(省略時は3) |
colspan | GIRD形式のpack時にTextを配置する横方向の幅(デフォルトは1) |
rowspan | GIRD形式のpack時にTextを配置する縦方向の幅(デフォルトは1) |
frame | 親フレーム。省略時はGUIのrootパネル |
子要素 | |
message | 〔動作条件が未実装〕 |
shell | 〔動作条件が未実装〕 |
script | 〔動作条件が未実装〕 |
log | 〔動作条件が未実装〕 |
TestGui.seatml内でのtext要素は、下図の赤枠の部分になります。
これらのアイテムのSEATML内での記述は、下記の通りです。
<text id="textOut" width="50" height="5" colspan="2" >
</text>
combobox要素
comboboxは、ドロップダウンリストと1行のテキストボックス(Entry)を合わせた入力用アイテムです。ドロップダウンリストに表示するアイテム(テキスト)は、values属性に','で区切られたテキストです。eSEATの内部では、values属性の値を','で分割しています。
Comboboxは、Pythonでは、Tkinter.ttkモジュール内に定義されています。
タグ名 | |
<combobox> | |
属性 | |
id | comboboxアイテムの識別子[必須] |
values | comboboxアイテムの列(','で区切られたテキスト) |
default | comboboxの初期値(デフォルトは '') |
colspan | GIRD形式のpack時にcomboboxを配置する横方向の幅(デフォルトは1) |
rowspan | GIRD形式のpack時にcomboboxを配置する縦方向の幅(デフォルトは1) |
frame | 親フレーム。省略時はGUIのrootパネル |
子要素 | |
message | 選択変更時に、sendto属性に指定されたポートに対して、子要素に記載された文字列を送信する |
shell | 選択変更時に、子要素に記載された文字列を、system関数で評価し、Shellコマンドを実行する。 |
script | 選択変更時に、execfile属性で指定されたPythonスクリプトファイルをexecfile関数で評価し、子要素に記載された文字列があれば、exec関数で評価しPythonスクリプトを実行する。 |
statetransition | 選択変更時に、この要素は、eSEATの内部状態を別の状態に遷移させます。 |
log | 選択変更時に、TEXT要素の内容をloggerに出力する。 |
TestGui.seatml内でのcombobox要素は、下図の赤枠の部分になります。
これらのアイテムのSEATML内での記述は下記の通りです。この例では、選択変更時にコンソールに選択されたアイテム(文字列)が出力されます。
<combobox id="combo1" values="Foo,Bar,Baz" default="Bar">
<script>
val=seat.getComboboxValue("main_mode:combo1")
seat.appendText("main_mode:textOut", val+"\n")
</script>
</combobox>
checkbutton要素
checkbutton要素は、TkinterのCheckboxを生成することができます。name属性は、eSEAT内での識別子でもあり、GUIパネル上に表示される文字列になります。
タグ名 | |
<checkbutton> | |
属性 | |
name | checkbuttonの表示文字列。アイテムの識別子[必須] |
colspan | GIRD形式のpack時にcheckbuttonを配置する横方向の幅(デフォルトは1) |
rowspan | GIRD形式のpack時にcheckbuttonを配置する縦方向の幅(デフォルトは1) |
frame | 親フレーム。省略時はGUIのrootパネル |
子要素 | |
message | 選択変更時に、sendto属性に指定されたポートに対して、子要素に記載された文字列を送信する |
shell | 選択変更時に、子要素に記載された文字列を、system関数で評価し、Shellコマンドを実行する。 |
script | 選択変更時に、execfile属性で指定されたPythonスクリプトファイルをexecfile関数で評価し、子要素に記載された文字列があれば、exec関数で評価しPythonスクリプトを実行する。 |
statetransition | 選択変更時に、この要素は、eSEATの内部状態を別の状態に遷移させます。 |
TestGui.seatml内でのcheckbutton要素は、下図の赤枠の部分になります。
これらのアイテムのSEATML内での記述は下記の通りです。この例では、選択変更時にコンソールに真偽(Ture or False)が出力されます。
<checkbutton name="Check1">
<script>
val=seat.getCheckValue("main_mode:Check1")
seat.appendText("main_mode:textOut", str(val)+"\n")
</script>
</checkbutton>
listbox要素
listbox要素は、複数の行のリストを表すGUIアイテムです。リストの要素は、valuesに','区切りのテキストを与えます。eSEAT内部では、このテストを分割して、Listboxに渡しています。通常は、listboxの高さは、リスト要素の数できますのですが、height属性を指定すれば、表示する高さを制限することができます。その場合には、右端にスクロースバーが現れます。
タグ名 | |
<listbox> | |
属性 | |
name | listboxアイテムの識別子[必須] |
values | listboxアイテムの列(','で区切られたテキスト) |
height | listboxの表示される行数(デフォルトは アイテムの数) |
colspan | GIRD形式のpack時にlistboxを配置する横方向の幅(デフォルトは1) |
rowspan | GIRD形式のpack時にlistboxを配置する縦方向の幅(デフォルトは1) |
frame | 親フレーム。省略時はGUIのrootパネル |
子要素 | |
message | 選択変更時に、sendto属性に指定されたポートに対して、子要素に記載された文字列を送信する |
shell | 選択変更時に、子要素に記載された文字列を、system関数で評価し、Shellコマンドを実行する。 |
script | 選択変更時に、execfile属性で指定されたPythonスクリプトファイルをexecfile関数で評価し、子要素に記載された文字列があれば、exec関数で評価しPythonスクリプトを実行する。 |
statetransition | 選択変更時に、この要素は、eSEATの内部状態を別の状態に遷移させます。 |
TestGui.seatml内でのlistbox要素は、下図の赤枠の部分になります。
これらのアイテムのSEATML内での記述は下記の通りです。heught属性を競ってしていますので、表示の高さは4行分になります。
<listbox name="lb1" values="Red,Green,Blue" height="4" > </listbox>
radiobutton要素
radiobutton要素は、通常、複数の要素を並べる形で表示される選択アイテムです。表示はChecklistに似ていますが、複数のradiobuttonをグループ化して、いずれか1つを選択するための入力アイテムです。label属性は、チェックボックスのみ右に表示されるテキストです。このradiobuttonには、variable属性をvalue属性を設定する必要があります。variable属性(変数名)が同じものがグループ化され、選択した場合に、variable属性の変数にvalue属性の値が代入されます。
タグ名 | |
<radiobutton> | |
属性 | |
label | radiobuttonアイテムの識別子[必須] |
variable | radiobuttonの状態変数 |
value | radiobuttonの値(このradiobuttonが選択状態の時に、状態変数に代入される) |
colspan | GIRD形式のpack時にradiobuttonを配置する横方向の幅(デフォルトは1) |
rowspan | GIRD形式のpack時にradiobuttonを配置する縦方向の幅(デフォルトは1) |
frame | 親フレーム。省略時はGUIのrootパネル |
子要素 | |
message | 選択変更時に、sendto属性に指定されたポートに対して、子要素に記載された文字列を送信する |
shell | 選択変更時に、子要素に記載された文字列を、system関数で評価し、Shellコマンドを実行する。 |
script | 選択変更時に、execfile属性で指定されたPythonスクリプトファイルをexecfile関数で評価し、子要素に記載された文字列があれば、exec関数で評価しPythonスクリプトを実行する。 |
statetransition | 選択変更時に、この要素は、eSEATの内部状態を別の状態に遷移させます。 |
TestGui.seatml内でのradiobutton要素は、下図の赤枠の部分になります。
これらのアイテムのSEATML内での記述は下記のようになっています。この例では、rootフレームではなく labelframeの上にradiobuttonを配置しています。
<radiobutton label="Radio1" variable="r1" value="aaa" frame="RadioButtons" />
<brk frame="RadioButtons" />
<radiobutton label="Radio2" variable="r1" value="bbb" frame="RadioButtons" />
<brk frame="RadioButtons" />
<radiobutton label="Radio3" variable="r1" value="ccc" frame="RadioButtons" />
scale要素
scale要素は、スクロールバーのようなスケール値を操作するためのGUIアイテムです。このアイテムは、通常、ヨコ型なのですが、orientation属性を設定すことで、タテ型に変更することができます。基本的に属性値は、TkinterのScaleアイテムに与えるキーワードと同じになっています。
タグ名 | |
<scale> | |
属性 | |
label | scaleアイテムの識別子およびタイトル[必須] |
from | scaleの最小値 |
to | scaleの最大値 |
resolution | scaleの刻み幅 |
orientation | scaleの配置方向(デフォルトはhorizontal) |
colspan | GIRD形式のpack時にscaleを配置する横方向の幅(デフォルトは1) |
rowspan | GIRD形式のpack時にscaleを配置する縦方向の幅(デフォルトは1) |
frame | 親フレーム。省略時はGUIのrootパネル |
子要素 | |
message | スライド変更時に、sendto属性に指定されたポートに対して、子要素に記載された文字列を送信する |
shell | スライド変更時に、子要素に記載された文字列を、system関数で評価し、Shellコマンドを実行する。 |
script | スライド変更時に、execfile属性で指定されたPythonスクリプトファイルをexecfile関数で評価し、子要素に記載された文字列があれば、exec関数で評価しPythonスクリプトを実行する。 |
statetransition | スライド変更時に、この要素は、eSEATの内部状態を別の状態に遷移させます。 |
TestGui.seatml内でのscale要素は、下図の赤枠の部分になります。
これらのアイテムのSEATML内での記述は下記のようになっています。
<scale name="scale1" from="0" to="10" resolution="1" orientation="h" colspan="3">
brk要素
brk要素は、上述のlabel要素等とはことなり、GUIのパネルアイテムを生成しません。この要素は、GUIのパネルアイテムを配置するための要素であり、HTML等での<br>のような機能を果たします。すなわち、eSEATでは、GUIアイテムの配置を横方向のみの配置したサポートしていないためそのままでは複数行になるテーブルのようなGUIパネルの生成ができません。そのため、この要素が出現したところで強制的に改行させるようにしています。
brk要素は、他のGUIアイテム要素と同じように frame属性を設定することができます。frame属性が設定されれば、その識別子のフレーム上で有効になっています。(radiobutton要素の例を参照してください)
タグ名 | |
<brk> | |
属性 | |
comment | コメントの入力。eSEATでは不使用。 |
frame | 親フレーム。省略時はGUIのrootパネル |
子要素 | |
なし |
space要素
space要素は、前述のbrk要素と同じようにGUIアイテムの配置を制御するための要素です。brk要素が改行のような機能を実現していますが、このspace要素を、GRID形式は左詰めで配置されるGUIアイテムの途中で挿入することで、GUIアイテムをスキップさせて配置させることができます。また、この要素は ''length''属性を持つことができ、''length="2"''のように記載することで2枡スキップして次のGUIアイテムを配置させることができます。
space要素もbrk要素とおなじようにframe属性を設定することができます。
タグ名 | |
<space> | |
属性 | |
length | スキップする枡数 |
frame | 親フレーム。省略時はGUIのrootパネル |
子要素 | |
なし |