HZK
@HZK (Ritoku Sakamae)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

tkinter: canvasのcreate_textでtextvariableは可能!?

解決したいこと

tkinterのキャンバスクラスでテキストを描画しています。
テキストを任意に変更することを考えていますが、
create_text のオプションにはtextvariableがないので困っていました。

ネット上で、唯一解決策らしきものがありました。
https://stackoverflow.com/questions/28518976/how-to-add-a-tkinter-text-variable-in-canvas-text

発生している問題・エラー

これを参考にして、コードを組み上げたらうまくいきました。特に、固定表現とコメントした部分が重要ポイントと見当をつけましたが、そもそもこれでうまくいく理由が分かりません。そのため、発展性もなく、自身の実力にはつながっておりません。

これがうまくいく理由。または他にcreate_textでtextvariableを実現する方法、その他コード上の問題等、なんでも良いので是非教えてください。よろしくお願いします。

該当するソースコード

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import tkinter as tk
import random

CANVAS_WIDTH = 540
CANVAS_HEIGHT = 320
onigi_lst = ["さけ", "いくら", "うめ", "こんぶ", "ツナマヨ", "なっとう"]

def rotate_switch():
    onigi = random.choice(onigi_lst)
    svr1.set(onigi)   
#固定表現
def on_change(varname, index, mode):
    canvas.itemconfigure(cv_txt, text=root.getvar(varname))
#main関数
def main():
    global canvas
    root = tk.Tk()
    canvas = tk.Canvas(
        root,
        width=CANVAS_WIDTH,
        height=CANVAS_HEIGHT,
        bg="white",
        highlightthickness=0)
    canvas.pack()
    # ボタン作成
    button = tk.Button(
        root,
        text="ボタン",
        command=rotate_switch)
    button.pack()

    #座標の指定
    lstB = [[420, 70], [120, 130], [300, 190], [350, 280]]
    canvas.create_polygon(lstB, 
        tag= "polygonA", fill="", outline="blue", width=10, 
        smooth=1,)

    svr1 = tk.StringVar(root) 
    svr1.set('おにぎりの具は?')
    svr1.trace_variable('w', on_change)
    cv_txt = canvas.create_text(270,160, font=("", 40), text=svr1.get())
    root.mainloop()

if __name__ == '__main__':
    main()
0

4Answer

main関数のglobal宣言を以下に変更しないと、ボタンを押したときにエラーになりました。

global root, canvas, svr1, cv_txt

ボタンを押したときの処理の流れ:

  1. ボタンを押すとrotate_switch関数が呼び出される
  2. rotate_switch関数のsvr1.set(onigi)でsvr1に具の名前がセットされる
  3. svr1.trace_variable('w', on_change) により、svr1への書き込み('w')が行われるとon_change関数が呼び出される
  4. on_change関数のroot.getvar(varname)で書き込まれた具の名前を取り出し
  5. canvas.itemconfigure(cv_txt, text=具の名前) でcv_txt に具の名前が表示される
1Like

いつもお世話になっており、恐縮しています。グローバル変数については失礼しました。
Jupyter Notebook で作業をしているのですが、グローバル変数汚染?というのでしょうか、他のセルで定義済みだと、エラーが出ないことがあるので困惑します。
あらためて教えて頂き、大分理解が深まりました、ありがとうございます。

特に、canvas.create_textにおいて、textvariable の代わりにtext=svr1.get()とし(set()でないことに注意か)、そこに、canvas.itemconfigureで、text=root.getvar(varname)とし、その間を、svr1.trace_variable('w', on_change)で処理するというように理解しました。

なお、この手法を流用すれば、textvariableが用意されていないオプションでも同様なことが可能となるのか、また、一方でtextvaribleが用意されていても、別途この処理も併用可能になるという理解で正しいでしょうか?

0Like

textvairableが用意されていなくても、StringVarへの書き込みイベントを拾って値を反映することが可能になりますね。
textvariableが用意されている場合には、それと同じことを内部で行っているので、併用する必要はないと思います。

0Like

内部的には同じ処理なのですね。Widget変数の奥深さが垣間見えた気がします。
今回もご教授ありがとうございました。

0Like

Your answer might help someone💌