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

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

新規登録して質問してみよう
ただいま回答率
85.33%
Tkinter

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

Python

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

Q&A

解決済

2回答

131閲覧

tkinterのテキストボックスに入力された文字列を別画面で使用したい

two625

総合スコア2

Tkinter

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

Python

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

1グッド

0クリップ

投稿2025/02/12 03:10

実現したいこと

最初のウィンドウで文字入力を促し、そこで入力された文字列を次に表示する画面で使用したい

発生している問題・分からないこと

python入門者なので簡単なことも分かっていないと思うのですがよろしくお願いします。

最初のウィンドウで入力した文字列をそのウィンドウを閉じた後、
次に開くウィンドウに持っていきたいのですが方法が分かりません。

該当のソースコード

python

1import tkinter as tk 2 3class user_name_input(tk.Frame): 4 def __init__(self, master=None): 5 super().__init__(master) 6 self.pack 7 8 self.label1 = tk.Label(root, text="") 9 self.label1.pack() 10 self.label2 = tk.Label(root, text="あなたの名前を入力してください") 11 self.label2.pack() 12 self.entry = tk.Entry(root) 13 self.entry.pack() 14 self.kettei = tk.Button(root, text="決定", command=self.kettei_button_click) 15 self.kettei.place(x=82,y=75) 16 self.button = tk.Button(root, text="進む", command=self.on_button_click) 17 self.button.place(x=135,y=75) 18 19 def kettei_button_click(self): 20 self.entry["state"]=tk.DISABLED 21 22 def on_button_click(self): 23 root.destroy() 24 25class tkApp(tk.Frame): 26 def __init__(self, master=None): 27 super().__init__(master) 28 self.pack() 29 30 lbl=tk.Label(wnd,text="ここに取得した文字を出したい") 31 lbl.pack() 32 33root = tk.Tk() 34root.geometry("250x120") 35root.title("名前入力") 36user=user_name_input(root) 37root.mainloop() 38 39wnd=tk.Tk() 40wnd.geometry('300x300') 41wnd.title('test') 42app=tkApp(wnd) 43wnd.mainloop()

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

文字列を持っていくために変数に代入してみたりしたのですが、
最初の画面を閉じるためのquitやdestroyで文字列は消えるのでしょうか…うまく行きませんでした。

また、調べていると、mainloopは一度しか使ってはいけないようなことも見たのですが、このコードは大丈夫なのでしょうか。

補足

特になし

melian👍を押しています

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

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

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

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

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

guest

回答2

0

mainloopは一度しか使ってはいけないようなことも見たのですが、このコードは大丈夫なのでしょうか。

エラーなしに正常実行できる、という意味では大丈夫の範疇ですが、

コードの改変等、保守する際に なぜ mainloop が複数あるコードが問題になりやすいか
を把握してないと以降の保守が大変になる傾向があります。(実際に、QAサイトで質問が多い)

→ 事例: 余計な部分のデバッグに時間が掛かり、
本来追加したかった機能がなかなか実装出来ない、等。

質問のコードでは、

root1 = tk.Tk() root1.mainloop() # この時点で上の mainloop は終了している root2 = tk.Tk() root2.mainloop()

という構造になってそれぞれが独立しているため、root が複数ある状況にはなってません。
→ 複数のrootを同時に扱うと、別の問題があります。(tkinter ライブラリ利用の作法)

ただし、mainloopを抜けて再度 tk.Tk() を作るという事は、
ウィンドウ作成の度に tkinter ライブラリ全体が終了・初期化されるという事を留意しておいてください。
効率化の為には、初期化は一度のみにして、ウィンドウが複数必要であれば Toplevel を用いるように実装します。

追記: 問題の原因
恐らく2つめのウィンドウで user.entry.get() みたいな事をして、
以前入力された値を参照したい場合、
mainloop() が終了しているので、以前の UI 内の値を参照出来ないというのが、
mainloopが複数ある場合の気を付けなければならない点。

mainloop 終了前に値を別の場所の保存しておくのは解決策の一つですが、
ウィンドウ毎にmainloopを終了せずに、初期化・終了は1度で済ませる方法もあります。


お勧めできる解決策は、入力値を返すダイアログを使った実装方法です。

python

1from tkinter.simpledialog import askstring 2from tkinter.messagebox import showinfo 3 4if name := askstring("名前入力", "あなたの名前を入力してください"): 5 showinfo("test", f"Hello, {name}")

対話環境での入力みたいなコードは、
GUIで主に扱うイベント駆動プログラミングでは記述が難かったりします。
(出来ないわけではないけど、非同期処理や双方向ジェネレーター等を扱う話題)

対話環境のように 入力・出力を扱うには、ダイアログ・ベースにするのが簡単。
質問のコードをカスタムダイアログにした例

python

1import tkinter as tk 2from tkinter.simpledialog import _QueryDialog, Dialog, askinteger 3from dataclasses import dataclass 4 5import re 6 7def is_valid_email(email): 8 return bool(re.fullmatch(r"[^@]+@[^@]+\.[^@]+", email)) 9 10@dataclass 11class UserInput: # 入力された値を纏める入れ物。辞書でもいい 12 name: str = "" 13 age: int = -1 14 email: str = "" 15 16# 質問のコードをカスタムダイアログに 17class _QueryMyStringDialog(_QueryDialog): 18 def body(self, master): 19 label1 = tk.Label(master, text=self.prompt) 20 label1.pack() 21 label2 = tk.Label(master, text="") 22 label2.pack() 23 entry = self.entry = tk.Entry(master) 24 entry.pack() 25 self.geometry("300x150") 26 27 def getresult(self): 28 return self.entry.get() 29 30 31# 入力検査のカスタマイズ例 32class _QueryEmailDialog(_QueryMyStringDialog): 33 errormessage = "無効なメールアドレス" 34 35 def getresult(self): 36 email = super().getresult() 37 38 if not is_valid_email(email): 39 raise ValueError() 40 41 return email 42 43 44def ask_string(title="", prompt=""): 45 d = _QueryMyStringDialog(title, prompt) 46 return d.result 47 48def ask_email(title="", prompt=""): 49 d = _QueryEmailDialog(title, prompt) 50 return d.result 51 52 53class OutputDialog(Dialog): 54 def __init__(self, parent, user): 55 self.user = user ## NOTE: body が __init__内で呼び出される為、事前に設定 56 super().__init__(parent) 57 58 def body(self, master): 59 user = self.user 60 lbl=tk.Label(master ,text=f"Hello, {user.name} <{user.email}>") 61 lbl.pack() 62 63 def buttonbox(self): # ボタン部分のカスタマイズ例 64 box = tk.Frame(self) 65 button = tk.Button(box, text="OK", command=self.ok) 66 button.pack() 67 box.pack() 68 69 70def main(): 71 user = UserInput() 72 73 user.name = ask_string("名前入力", "あなたの名前を入力してください") 74 user.age = askinteger("年齢", "年齢を入力してください") 75 user.email = ask_email("Email", "メールアドレスを入力してください") 76 77 OutputDialog(None, user) 78 79 80if __name__ == '__main__': 81 main()

参考までに、GUI でこういったステップ入力
名前入力、次の画面で EMailアドレス入力~~と、
ユーザの入力・選択によって進む UI は 「 Wizard 」と呼ばれていて
残念ながら tkinter には用意されてませんが、探せばサンプルコードはいくつか見つかるかも。

簡易的には ユーザ入力を求めるダイアログ関数で似たような実装が出来ます。

投稿2025/02/12 14:37

編集2025/02/12 14:51
teamikl

総合スコア8805

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

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

two625

2025/02/13 01:42

すごく分かりやすいご説明、ありがとうございます! 今作成しているもの(二つ目の画面にてRPGのようなものを動かそうとしています)に取り入れれるか分かりませんが、理解を深めるためにもよりスマートなコードを書きたいとは思っているので、いろいろ使用してみたり試行錯誤を繰り返してみようと思います。
guest

0

ベストアンサー

user_name_input クラスに入力テキストを保存する属性(input_text)を用意して、それを利用して次のウィンドウ(tkAppクラスのウィジェットインスタンス)に渡します。

python

1import tkinter as tk 2 3class user_name_input(tk.Frame): 4 def __init__(self, master=None): 5 super().__init__(master) 6 self.pack 7 8 self.label1 = tk.Label(root, text="") 9 self.label1.pack() 10 self.label2 = tk.Label(root, text="あなたの名前を入力してください") 11 self.label2.pack() 12 self.entry = tk.Entry(root) 13 self.entry.pack() 14 self.kettei = tk.Button(root, text="決定", command=self.kettei_button_click) 15 self.kettei.place(x=82,y=75) 16 self.button = tk.Button(root, text="進む", command=self.on_button_click) 17 self.button.place(x=135,y=75) 18 self.button.place(x=135,y=75) 19 # 入力テキスト 20 self.input_text = "" 21 22 def kettei_button_click(self): 23 # 入力テキストを保存 24 self.input_text = self.entry.get() 25 self.entry["state"]=tk.DISABLED 26 27 def on_button_click(self): 28 root.destroy() 29 30class tkApp(tk.Frame): 31 def __init__(self, master=None, user_name=None): 32 super().__init__(master) 33 self.pack() 34 # 入力テキストを表示 35 input_text = "" if user_name is None else user_name.input_text 36 lbl=tk.Label(wnd,text=input_text) 37 # lbl=tk.Label(wnd,text="ここに取得した文字を出したい") 38 lbl.pack() 39 40root = tk.Tk() 41root.geometry("250x120") 42root.title("名前入力") 43user=user_name_input(root) 44root.mainloop() 45 46wnd=tk.Tk() 47wnd.geometry('300x300') 48wnd.title('test') 49# user_name_input クラスのインスタンス(user)をイニシャライザ(__init__())に渡す 50app=tkApp(wnd, user) 51wnd.mainloop()

投稿2025/02/12 03:35

編集2025/02/12 04:10
melian

総合スコア20905

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

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

two625

2025/02/12 04:45

早々のご回答ありがとうございます。 やりたかったことができました! まだまだ知らないことが多くて難しく感じますががんばります。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.33%

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

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

質問する

関連した質問