質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

3142閲覧

tkinterを用いてStringVarで上手く値を参照できない2

sobagome

総合スコア9

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/01/26 00:45

編集2021/01/26 04:20

前提・実現したいこと

tkinterのStringVar()を用いたGUIの作成。
ChildWindowで各ボタンから1つ選択してからcloseを選択すると、
ChildWindowは消えてその選んだ文字がMainWindowに反映させるようにはできたが、
ChildWindowで設定した項目をMainWindowだけでなく、
ChildWinow2側にも表示したい。

該当のソースコード

python

1# -*- coding: utf-8 -*- 2 3import tkinter as tk 4import tkinter as ttk 5 6class MainWindow(tk.Frame): 7 def __init__(self,master): 8 super().__init__(master) 9 self.grid() 10 self.master.geometry("200x150+10+10") 11 self.master.title("MainWindow") 12 self.create_widgets() 13 14 def create_widgets(self): 15 self.param = tk.StringVar() 16 button = tk.Button(self, text="設定",command = self.set_vrt) 17 button.grid(row=0, column=0) 18 label = tk.Label(self,textvariable=self.param) 19 label.grid(row=1, column=2,columnspan=3,sticky=tk.W+tk.E) 20 button2 = tk.Button(self, text="反映",command = self.set_vrt2) 21 button2.grid(row=0, column=1) 22 23 def set_vrt(self): 24 self.newWindow = tk.Toplevel(self.master) 25 self.newWindow.grab_set() 26 self.app = ChildWindow(self.newWindow, self) 27 28 def set_vrt2(self): 29 self.newWindow = tk.Toplevel(self.master) 30 self.newWindow.grab_set() 31 self.app = ChildWindow2(self.newWindow) 32 33 34class ChildWindow(tk.Frame): 35 def __init__(self,master, main): 36 super().__init__(master) 37 self.grid() 38 self.master.geometry("200x150") 39 self.master.title("ChildWindow") 40 self.create_widgets() 41 self.main=main 42 43 def create_widgets(self): 44 label = tk.Label(self, text="""一つ選択していください。:""", justify = tk.LEFT, padx = 20) 45 label.grid(row=0,column=0,sticky=tk.W) 46 self.dialog = tk.StringVar() 47 languages = [("a","a"),("b","b"),("c","C")] 48 for language, val in languages: 49 tk.Radiobutton(self.master, 50 text=language, 51 indicatoron = 0, 52 width = 20, 53 padx = 20, 54 variable=self.dialog, 55 command=None, 56 value=val).grid(sticky=tk.W) 57 closeButton = tk.Button(self.master, text="close", command=self.close) 58 closeButton.grid(sticky=tk.W) 59 60 def close(self): 61 self.main.param.set(self.dialog.get()) 62 self.master.destroy() 63 64 65class ChildWindow2(tk.Frame): 66 def __init__(self,master): 67 super().__init__(master) 68 self.grid() 69 self.master.geometry("200x150") 70 self.master.title("ChildWindow2") 71 self.create_widgets() 72 73 def create_widgets(self): 74 self.param = tk.StringVar() 75 label = tk.Label(self,textvariable=self.param) 76 label.grid(row=0, column=0) 77 78 79def main(): 80 root = tk.Tk() 81 app = MainWindow(master=root) 82 app.mainloop() 83 84if __name__ == "__main__": 85 main()

試したこと

エラーは発生しませんが、ChildWindow2には何も表示されません。
このコードの記述方法だとMainWindowからしかStringVarの参照が出来ないのでしょうか?

補足情報(FW/ツールのバージョンなど)

Python 3.8.3

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

問題点: ChildWindow2 の StringVar は ChildWindow2 内で作られた値で
MainWindow のものと関連がありません。

対処方法はいくつか考えられますが(どれかひとつ)


解決策A:
MainWindowのself.param を ChildWindow2 に渡す。

率直な実装方法ですが、クラスの再利用性を考えると不便になる事はあります。


解決策B:
ChildWindow2 のインスタンスを作った後に、
config で ChildWindow2 の label に textvariable を設定する。


解決策C:
StringVar の値を共有する為に、共通のnameを設定する。
tkinter 依存の方法。

tk.StringVar(name="lang-var")


解決策D:
MainWindow, ChildWindow1, ChildWindow2 でそれぞれ StringVar を作っていますが
一つの StringVar を Label や Radiobutton 全てで共有すると、
get/set で明示的に値を設定してる部分も不要になります。

投稿2021/01/26 05:38

teamikl

総合スコア8664

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sobagome

2021/01/26 12:15

ご回答頂きありがとうございます。解決策を複数挙げて頂きましたが、勉強不足でどれも私には理解が出来ませんでした。記載頂いたキーワードを拾って検索して考えてみましたが難しいです。 1つの解決策でも構いませんので、後学の為にも、もう少しヒントを頂けないでしょうか。
teamikl

2021/01/26 13:16

とりあえず、目的の動作を達成するだけなら クラスの構成をそのままでできる、簡単な対処方法は tk.StringVar() の部分数か所を、 tk.StringVar(name="lang-var") として見て下さい。 "lang-var" の部分は何でも良いですが、 値を共有したいものの間で共通のnameを設定します。 ---- ChildWindow2 に MainWindowのself.param が渡されてない点なので、 MainWindow と ChildWindow2 の tk.StringVar だけでも良いです。 ChildWindow1 -> MainWindow はウィンドウを閉じた時に self.main.param.set(self.dialog.get()) と設定されていますが、 ChildWindow1 内の tk.StringVar でも共通の name を設定すれば ウィンドウを閉じた時の get/set での値の受け渡しは不要になります 問題点: name=を設定する場合の注意点 ただし、ChildWindow を複数同時に作る場合は、 全てのウィドウで変数の値が共有される点に注意してください。
sobagome

2021/01/26 14:00

MainWindow と ChildWindow2 を tk.StringVar(name="lang-var") として、 目的の動作が達成できました。 正直何故これで達成できたのか中身をちゃんと理解が出来ておりませんが、 その他の解決策も合わせて、理解出来るように引き続き勉強に励みます。 ご丁寧に解説頂き、ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問