

python初学者です。  
tkinterのButtonを使って、クリックするボタン(OK,
cancel)によって異なる変数(True,False)を格納した後ウインドウが消えるプログラムを作成しようとしています。動きとしてはmessageboxのaskokcancelのような動きです。  
普通であればmessageboxを使う所なのですが、ハイパーリンクをダイアログ中に入れたかったので、以下のようにButtonで作成しております。  
本題ですが、このソースだと戻り値のbuffがどちらのボタンを押してもTrueのまま返ってきてしまいます。destroyした時点でBooleanVarへの格納は出来なくなってしまうようです。  
destroyを消すと戻り値はボタンに応じて変わるようになるのですが、当然フレームが消えません。  
これらを共存させるよい方法がありましたらご教示願えませんでしょうか。

Python 3.5.2 :: Anaconda 4.0.0 (32-bit)  
Tcl/Tk 8.6  
です。

[code]

    import tkinter as tk
    import webbrowser
    
    def hyperlink(event):
        webbrowser.open_new(event.widget.cget('text'))
    
    def program_start():
        root.destroy()
        return lambda : buff.set(True)
    
    def program_quit():
        root.destroy()
        return lambda : buff.set(False)
    
    root = tk.Tk()
    buff = tk.BooleanVar()
    buff.set(True)
    
    lbl = tk.Label(root, text=r'https://google.co.jp',fg="blue", cursor="hand2")
    lbl.pack()
    lbl.bind("<Button-1>", hyperlink)
    tk.Button(root, text = 'OK', width=10 , command = program_start).pack()
    tk.Button(root, text = 'cancel', width=10 , command = program_quit).pack()
    
    root.mainloop()
    
    print (buff.get())
    
[/code]


CC BY-SA 3.0
2017-07-04T14:33:15.377
36096
2020-12-02T03:46:17.197
2017-07-04T14:40:57.880
19110
24221
question
python3 tkinter
tkinterのbuttonでmessageboxのような動作をさせたい


[リファレンス](http://effbot.org/tkinterbook/button.htm)を見る限り、そもそもコールバックはラムダ式を返すようなものではないようですが・・・。

解決策としては、`set`した後`destroy`するというのではダメでしょうか？

[code]

    def program_start():
        buff.set(True)
        root.destroy()
    
    def program_quit():
        buff.set(False)
        root.destroy()
    
[/code]

それから

> destroyを消すと戻り値はボタンに応じて変わるようになる

について、destroyを消すと言うのが`root.destroy()`をコメントアウトすることと等価であると仮定して、`set`しているコードは単にラムダ式の一部として返ってるだけなのであり得ないのでは？実際手元では再現しません。


CC BY-SA 3.0
2017-07-04T15:43:06.317
36097
2017-07-04T15:43:06.317
13199
36096
answer


クラス化しての再利用なら、こういった書き方もできるかなと思います。

[code]

    import tkinter as tk
    import webbrowser
    
    class MsgBox():
        def __init__(self):
            self.root = tk.Tk()
            self.ret = False
            lbl = tk.Label(self.root, text=r'https://google.co.jp',fg="blue", cursor="hand2")
            lbl.pack()
            lbl.bind("<Button-1>", self.hyperlink)
            tk.Button(self.root, text = 'OK', width=10 , command = lambda: self.root_exit(True)).pack()
            tk.Button(self.root, text = 'cancel', width=10 , command = lambda: self.root_exit(False)).pack()
    
        def hyperlink(self,event):
            webbrowser.open_new(event.widget.cget('text'))
    
        def start(self):
            self.root.mainloop()
    
        def root_exit(self,state):
            self.ret = state
            self.root.destroy()
    
        def get(self):
            return self.ret
    
    msg_box = MsgBox()
    msg_box.start()
    print(msg_box.ret)
    
    
[/code]


CC BY-SA 4.0
2020-12-02T03:46:17.197
72335
2020-12-02T03:46:17.197
32891
36096
answer