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

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

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

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

Tkinter

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

Python

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

Q&A

解決済

1回答

19679閲覧

python tkinter Entryに数字以外を入れない方法

suger365

総合スコア7

Python 3.x

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

Tkinter

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

Python

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

0グッド

0クリップ

投稿2019/12/02 13:50

前提・実現したいこと

python初心者です。
不足点などあればお教えください。

これに近いかと思いましたが、解決方法が違ったようで…
https://teratail.com/questions/60174

出勤管理アプリを作っています。
4桁の社員番号をentryに入力させるのですが、数字以外も入ってしまうことに気づきました。
entryに数字以外を入れさせない方法はどのようになるでしょうか?

発生している問題・エラーメッセージ

数字しか入力させたくないentryに数字以外が入ってしまう

該当のソースコード

import tkinter as tk root = tk.Tk() #entryを設定 Number = tk.Entry(font=("15","25"),textvariable=sv) Number.place(x=175,y=100) InEnter = tk.Label(root,text = "出勤",font=("25","40"),bg="blue") InEnter.place(x=200,y=175) InEnter.bind("<Button-1>", InWork) def InWork(event): Status = "出勤" EmpNum = Number.get()#EmpNumは社員番号 EmpNum_Count = len(EmpNum) if EmpNum_Count == 4 : d_now = str(format(datetime.now().strftime("%Y/%m/%d"))) t_now = str(format(datetime.now().strftime("%H:%M:%S"))) print(EmpNum,d_now,t_now,Status) root.mainloop()

結果
4桁の数字以外も入ってしまう

試したこと

コードを次のように変更
変更1

def OutWork(event): Status = "退勤" EmpNum = Number.get() EmpNum_Count = len(EmpNum) if EmpNum_Count == 4 and type(EmpNum) is int:#数字=intだからand条件にすればいい? d_now = str(format(datetime.now().strftime("%Y/%m/%d"))) t_now = str(format(datetime.now().strftime("%H:%M:%S"))) print(EmpNum,d_now,t_now,Status)

結果
数字4桁も入らなくなった

変更2

def InWork(event): Status = "出勤" EmpNum = Number.get()#EmpNumは社員番号 EmpNum_Count = len(EmpNum) if EmpNum = int(EmpNum):#ここで社員番号をintにする if EmpNum_Count == 4 and type(EmpNum) is int:#if文で4桁かつintだけ通す? d_now = str(format(datetime.now().strftime("%Y/%m/%d"))) t_now = str(format(datetime.now().strftime("%H:%M:%S"))) print(EmpNum,d_now,t_now,Status)

結果
数字4桁の場合入る
アルファベットを入れると以下のエラー

Exception in Tkinter callback Traceback (most recent call last): File "C:\Users\User\AppData\Local\Programs\Python\Python38-32\lib\tkinter\__init__.py", line 1883, in __call__ return self.func(*args) File "C:\python\tkinter\tkinter_PG.py", line 24, in InWork EmpNum = int(EmpNum) ValueError: invalid literal for int() with base 10: 'aaaa'

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

python Ver3.8.0です

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

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

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

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

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

guest

回答1

0

ベストアンサー

tkinterのEntryには入力された文字列の検証を行う validatecommand (vcmd) という仕組みがありますので、これを使うことを推奨いたします。

https://anzeljg.github.io/rin2/book2/2405/docs/tkinter/entry-validation.html

Python

1import tkinter as tk 2root = tk.Tk() 3 4# 文字列検証関数 5def validation(before_word, after_word): 6 return ((after_word.isdecimal()) and (len(after_word)<=4)) or (len(after_word) == 0) 7 8def InWork(event): 9 Status = "出勤" 10 EmpNum = Number.get()#EmpNumは社員番号 11 EmpNum_Count = len(EmpNum) 12 if EmpNum_Count == 4 : 13 d_now = str(format(datetime.now().strftime("%Y/%m/%d"))) 14 t_now = str(format(datetime.now().strftime("%H:%M:%S"))) 15 print(EmpNum,d_now,t_now,Status) 16 17#entryを設定 18sv = tk.StringVar() 19Number = tk.Entry(font=("15","25"),textvariable=sv) 20# %s は変更前文字列, %P は変更後文字列を引数で渡す 21vcmd = (Number.register(validation), '%s', '%P') 22# Validationコマンドを設定('key'は文字が入力される毎にイベント発火) 23Number.configure(validate='key', vcmd=vcmd) 24Number.place(x=175,y=100) 25 26InEnter = tk.Label(root,text = "出勤",font=("25","40"),bg="blue") 27InEnter.place(x=200,y=175) 28InEnter.bind("<Button-1>", InWork) 29 30root.mainloop()

投稿2019/12/02 23:59

編集2019/12/03 00:11
magichan

総合スコア15898

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

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

suger365

2019/12/03 01:56

まさにやりたいことができました! ありがとうございます。 何点かわからない点を質問させていただきます。 理解があってるかを含めて長文ですがお付き合いいただければありがたいです。 ```python def validation(before_word,after_word): return((after_word.isdecimal())) and (len(after_word) <= 4) or (len(after_word) ==0 ) ``` ここで ・after_wordがisdecimal(すべて数字)かつ4桁いかまたは0桁の場合returnで戻す だと思うのですが、すべてが数字でない かつ ~ にならないのはなぜでしょうか? ```python #entryを設定 sv = StringVar() Number = tk.Entry(font=("15","25"),textvariable=sv) # %sは変更前文字列、%Pは変更後文字列を引数で渡す vcmd = (Number.register(validation), "%s" , "%P") #validationコマンドを設定 Number.configure(validate = "key",vcmd = vcmd) Number.place(x=175,y=100) ``` ・サンプル見ながら書いたので自分で書いておいてわからないのですが sv=StringVar() はstring型を保持させているという認識でよいですか? ・vcmd = (Number.register(validation), "%s" , "%P") registerは登録、vcmdは文字列の検証というのは分かったのですが %s %P としているのはどういった意味があるでしょうか? ここ以外に出てきているところが見当たらないように見えるのですが… ・Number.configure(validate='key', vcmd=vcmd) vcmd = vcmdとしているのはkeyで発火した際に何か行わせているというのは なんとなくわかるのですが、どんな意味があるのですか? (validate='key', vcmd)では動きませんでした。
magichan

2019/12/03 06:47

・すべてが数字でない かつ ~ にならないのはなぜでしょうか? validation用の関数は、検証結果として問題ない場合をTrue、問題画ある場合(入力を拒否する場合)Falseを返します。 ですので今回の場合は、「すべて数字かつ4文字以下」という条件となっております。ただこの条件の場合は入力がない場合(文字を全て削除する処理)も拒否されてしまいますので、「または入力が無い(文字長が0)」を追加しております。 ・sv=StringVar() はstring型を保持させているという認識でよいですか? その通りです。Entry Widgetは文字列の入力を扱いますので、StringVarを使うのが適切です。 ・%s %P としているのはどういった意味があるでしょうか? これらはValidation関数の引数として何を渡したいかを記述します。 今回の場合は '%s' : 変更前の文字列 '%P' : 変更後の文字列 となっております。 そのほかに選択できるパラメータに関してはリンク先のTable 18を見てください。 ・Number.configure(validate='key', vcmd=vcmd) はどんな意味があるのですか? 'validate' は発火条件です。'key'のほかにも'focus','all','none' などが選べます。 'vcmb' は'validatecommand'の略称('validatecommand=vcmd'でも動作します)です。ここではvalidatecommandとして1行前で定義している vcmd = (Number.register(validation), '%s', '%P') を設定しております。 configure() コマンドはWidgetの様々な内部設定を設定変更するためのAPIのため、内部パラメータ名=パラメータ のように引数に渡す必要があるため、(validate='key', vcmd)では動作しないと思います。
suger365

2019/12/03 08:27

magichan 様 非常に丁寧なご回答をいただきありがとうございます。 参照先まで教えていただき助かりました。 %sなどは関数で既定で決まっているものでしたか… vcmdで実行する分としてvcmdを設定しているので二回出てくるのですね おかげさまで何とか完成させられそうです。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問