まえがき
“変更あり”のテキスト表示を作る
close 時に確認ダイアログを
Quit 時にもダイアログ
まとめ
前回はリストボックスの内容を保存して、起動時の読み込む機能を持たせました。起動している最中にはリストボックスの内容が保存されているのか、わからない状態なので、それを表示する機能を持たせます。
ウィンドウに“変更あり”や“変更なし”の表示をするテキストボックスを加えて、リストボックスの項目に変更があったかどうかを表示するようにします。
前回までのspeak11.sit.bin(約 30k)に書き加えていきます。
speakwin.py 変更前:27 ---------------------------------------------- self.listbox = W.List((20,120,200,140), items = self.text, callback = self.settext) ---------------------------------------------- 変更後:27- ---------------------------------------------- self.listbox = W.List((20,120,200,140), items = self.text, callback = self.settext) self.modifiedtext = W.TextBox((5, 95, 85, 20), text = 'No Change', fontsettings = ('Osaka',0,12,(0,0,0))) #追記 ----------------------------------------------
self.modifiedtext = W.TextBox((10, 100, 60, 18), text = 'No Change', fontsettings = ('Osaka',0,10,(0,0,0)))
Add ボタンの左にテキストボックスを加えました。起動時に「No Change」という文字を表示します。
もちろん、このままではリストボックスの内容を変化させても、表示は何も変わらないので、リストボックスに「Add」されたら、「*Modified*」と変えるようにします。
speakwin.py 変更前:49、50 ---------------------------------------------- def addList(self): self.listbox.append(self.textaria.editor.get()) ---------------------------------------------- 変更前:49- ---------------------------------------------- def addList(self): self.listbox.append(self.textaria.editor.get()) self.modifiedtext.set('*Modified*') ----------------------------------------------
self.modifiedtext.set('*Modified*')
addList メソッドの中に入れました。リストボックスに何か文字を加えた時に self.modifiedtext のテキストを「*Modified*」に変えます。
以上のようにして MyApp.py を実行して「Add」ボタンを押すと、下のように「*Modified*」に表示が変わります。
忘れてました。「Delete」ボタンを押したときもリストボックスの内容が変わるので、self.delete メソッドにも、テキストボックスを変えるような処理を書かなければなりません。
speakwin.py 変更前:53-28 ---------------------------------------------- def delList(self): selecteditem = self.listbox.getselection() text = self.text[:] for i in selecteditem: self.text.remove(text[i]) self.listbox.set(self.text) ---------------------------------------------- 変更後: ---------------------------------------------- def delList(self): selecteditem = self.listbox.getselection() text = self.text[:] for i in selecteditem: self.text.remove(text[i]) self.listbox.set(self.text) self.modifiedtext.set('*Modified*') #追記 ----------------------------------------------
これで、リストボックスの追加、削除をすると、「*Modified*」になります。
もうひとつ、Save したら「*Modified*」を「No Change」にしなければなりません。
speakwin.py 変更後:61-69 ---------------------------------------------- def save(self): ・ ・ ・ self.modifiedtext.set('No Change') #追記 ----------------------------------------------
これで、Save してないなら「No Change」、リストボックスの項目が変更されたら「*Modified*」の表示になります。
せっかく「*Modified*」を表示して、リストボックスが変更されたという識別ができるようになったので、ウィンドウの close 時に保存しなくて良いか尋ねるダイアログを出しましょう。
speakwin.py 変更後:def load(self) の後、speakwin.py の末尾に追記 ---------------------------------------------- def close(self): if self.modifiedtext.get() == '*Modified*': import EasyDialogs ok = EasyDialogs.AskYesNoCancel("Text list is changed.\rClose, OK?", 0) if ok != 1: return W.Window.close(self) ----------------------------------------------
def close(self):
ウィンドウのクローズボックスをクリックしたり、File メニューの「閉じる」を選ぶと呼び出されるようにしたいのです。「W ウィジェットリファレンス」に、「... closeをオーバーライドしてドキュメントがセーブされているかどうか確かめたり、ユーザに尋ねたりしたいでしょう。」とあります。それで close メソッドをオーバーライド、つまり close メソッドを作って、加えたい処理を書きます。
if self.modifiedtext.get() == '*Modified*':
テキストボックス self.modifiedtext に get() メソッドを実行して、テキストの内容を得ます。それが「*Modified*」だったら...
import EasyDialogs
ok = EasyDialogs.AskYesNoCancel("Text list is changed.\rClose, OK?", 0)
EasyDialogs モジュールをインポートして、AskYesNoCancel(question, default) を使います。question は表示される文字列で、質問文のことです。default は Yes、No、Cancelのボタンのうちデフォルトにするものです。1ならYes、0なら No、-1ならCancelがデフォルトボタンになります。省略すると0、Noです。クリックした結果がそれぞれの値で返されます。つまり、Yes をクリックすると1が返されます。
ここでは、「リストが変わっています。閉じてもいいですか?」(英語は自信ありません)と尋ねて、No をデフォルトボタンにしています。クリックした結果を ok に代入しています。
if ok != 1:
return
もし、ok が 1 でない、つまり、No と Cancel がクリックされたら、何もせず、元のルーチンに戻ります。
W.Window.close(self)
Yes、つまり閉じてもいいと選択したら、close します。表示している Win クラスが継承している W.Window クラスの close メソッドを呼び出すことで、クローズしています。今作っている self.close を作る前は、この W.Window の close メソッドがそのまま使われていたわけです。
以上のように speakwin.py を訂正して、MyApp.py を実行し、リストボックスに追加したりした後、File メニューの「閉じる」を選んだり、ウィンドウのクローズボックスをクリックすると、以下のようなダイアログがでます。
ウィンドウの close 時にはダイアログが出ますが、Quit の時にはでません。Quit の時にも出すようにしてみます。MyApp.py のアプリケーションクラスで quit メソッドに書き加えることにします。
MyApp.py 変更前:196-198 ---------------------------------------------- def domenu_quit(self): # buh-bye self._quit() ---------------------------------------------- 変更後: ---------------------------------------------- def domenu_quit(self): # buh-bye if self.main.wid: if self.main.close() == 0: return self._quit() ----------------------------------------------
if self.main.wid:
これは、以前も使いました。ウィンドウが開いているかどうかを判定しています。
if self.main.close() == 0:
return
self._quit()
ウィンドウの close メソッドを呼び出します。しかし、
if self.main.wid:
self.main.close()
self._quit()
だと、speakwin.py の Win クラスの close メソッドが return すると、そのまま self._quit() を実行して、終了してしまいます。それで、後で close を書き換えて、No、Cancel が選ばれたら 0 を返すようにして、その場合には return で quit を中止することにします。
それで、speakwin.py も訂正します。
speakwin.py 変更前:82-88 ---------------------------------------------- def close(self): if self.modifiedtext.get() == '*Modified*': import EasyDialogs ok = EasyDialogs.AskYesNoCancel("Text list is changed.\rClose, OK?", 0) if ok != 1: return W.Window.close(self) ---------------------------------------------- 変更後: ---------------------------------------------- def close(self): if self.modifiedtext.get() == '*Modified*': import EasyDialogs ok = EasyDialogs.AskYesNoCancel("Text list is changed.\rClose, OK?", 0) if ok != 1: return 0 #変更 W.Window.close(self) ----------------------------------------------
ただの return でなく、0を返すようにしました。これで、「*Modified*」のときに Quit を選ぶと、ウィンドウを閉じる時と同じくダイアログが出て、Yes を選ぶと終了し、No か Cancel を選ぶと終了しません。
以上の結果をまとめた speak12.sit.bin(約 30k)を作りました。
何か誤りやご質問、お気付きの点、ご意見やご不満などございましたら、メールで、もしくはMacPython BBS(よ)へ書き込んでいただければ幸いです。