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

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

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

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

Q&A

解決済

1回答

1140閲覧

python,tkinter使用のソースコードのファイルの分割(分割するとエラーになる)

akiteru

総合スコア18

Python

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

0グッド

0クリップ

投稿2020/05/11 06:27

編集2020/05/11 07:19

前提・実現したいこと

すみません、インデントが全く出ていませんでした。修正しました、よろしくお願いします。
tkinterのENTRYウェジェットのvalidatecommand、invalidcommandで日付入力の検証をしました。これをウェジェットの表示部分と検証部分に分割するとエラーが発生します(ワンファイル時は正常に動作)。この対処法を指摘ください。
ついでで恐縮ですがtkinterのmessageboxのフォントサイズ指定法を教えて下さい。

ここに質問の内容を詳しく書いてください。
(例)PHP(CakePHP)で●●なシステムを作っています。
■■な機能を実装中に以下のエラーメッセージが発生しました。

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

Traceback (most recent call last): File "C:\Users\akiteru\AppData\Local\Programs\Python\Python38\lib\tkinter\__init__.py", line 1883, in __call__ return self.func(*args) TypeError: hizuke_onValidate() missing 1 required positional argument: 'W'エラーメッセージ

該当のソースコード

# ****** t1.py ***** import tkinter as tk import tkinter.ttk as ttk # 全半角判定用 import unicodedata # キーイベント入手 from msvcrt import getch # メッセージボックス from tkinter import messagebox import t2 class MainWindow(ttk.Frame): def __init__(self, parent): super(MainWindow, self).__init__(parent) self.parent = parent # 第1のエントリーオブジェクト self.frame2 = tk.Frame(pady=5) self.frame2.pack(fill="x") self.label2 = tk.Label(self.frame2,font=("",14),text="区 分 ") self.label2.pack(side="left") self.entry2 = tk.Entry(self.frame2,font=("",14),justify="left", width=12) self.entry2.pack(side="left") # **********日付入力領域 self.frame1 = tk.Frame(pady=5) self.frame1.pack(fill="x") self.label1 = tk.Label(self.frame1,font=("",14),text="日 付 ") self.label1.pack(side="left") self.entry1 = tk.Entry(self.frame1,font=("",14),justify="left", width=12) self.entry1.insert("end", "yy/mm/dd") # ***** エントリー1への入力を判定(validatecommandの設定) vcm_onValidate = (self.register(t2.hizuke_onValidate), '%d', '%i', '%p', '%s', '%S', '%v', '%V', '%W') vcm_inValidate = (self.register(t2.hizuke_inValidate), '%d', '%i', '%p', '%s', '%S', '%v', '%V', '%W') self.entry1["validate"] = "all" self.entry1["validatecommand"] = vcm_onValidate self.entry1["invalidcommand"] = vcm_inValidate self.entry1.pack(side="left") # 第3のエントリーオブジェクト self.frame3 = tk.Frame(pady=5) self.frame3.pack(fill="x") self.label3 = tk.Label(self.frame3,font=("",14),text="名 前 ") self.label3.pack(side="left") self.entry3 = tk.Entry(self.frame3,font=("",14),justify="left", width=12) self.entry3.pack(side="left") application = tk.Tk() application.geometry("800x500") application.title('PyPost') window = MainWindow(application) application.protocol('WM_DELETE_WINDOW', window.quit) application.mainloop() # ****** t2.py ****** import tkinter as tk import tkinter.ttk as ttk # 全半角判定用 import unicodedata # キーイベント入手 from msvcrt import getch # メッセージボックス from tkinter import messagebox # ***** 日付入力の検証関数(validatecommandとinvalidcommandを組み合わせて処理) def hizuke_onValidate(self, d, i, p, s, S, v, V, W): # validateで入力値、カーソル位置を変更することができない # この為、検証を含め全ての処理をhizuke_inValidate(invalidcommand)で処理 # ⇒戻り値Falseのみセットする return False def hizuke_inValidate(self, d, i, p, s, S, v, V, W): # (1)フォーカスイン/アウトの処理(アウトで入力値検証) if d == '-1': # フォーカスイン時の処理(初期設定値「yy/mm/dd」の時カーソルを先頭設定) if V == 'focusin': dummy = self.entry1.get() if dummy == 'yy/mm/dd': # 初期設定値の時 self.entry1.icursor('0') # フォーカスアウト時は日付入値の検証実行 if V == 'focusout': # 数字部分文字列抽出 dummy = self.entry1.get() # 年月日に分割 yy = dummy[0:2] mm = dummy[3:5] dd = dummy[6:8] ymd = yy + mm + dd # 日付入力のエラー有無Flg(エラー有=1 無=0) flg = 0 # エラー訂正意思有の場合のカーソルを戻す位置 pos = '0' # エラー時のメッセージ文 msg = '' # (1)年月日が数字で無い時はNG if ymd.isdecimal() == False: flg = 1 pos = '0' msg = '日付入力が不適です' else: # 年月日数値検証(年は00~99迄入力可の為、検証せず) # (2)月検証(01~12) if int(mm) > 12 or int(mm) < 1: flg = 1 pos = '3' msg = '月の入力が不適です' else: # (3)指定月の日検証(01~31) # 各月の最大数列 d = (31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30,31) m = int(mm) -1 if int(dd) > d[m]: flg = 1 pos= '6' msg = '日の入力が不適です' # エラーの時訂正意思確認 # 訂正意思の戻り値 if flg == 1: res = '' res = messagebox.askquestion("注 意", msg + '訂正しますか?') if res == 'yes': # 訂正する場合 self.entry1.icursor(pos) self.entry1.focus_set() else: # 訂正し無い時(初期設定の「yy/mm/dd」表示に戻す) self.entry1.delete(0, 'end') self.entry1.insert(0,'yy/mm/dd') # (2)削除処理の時。削除位置の表示を「/、y、m、d」に変更 if d == '0': # 表示文字列作成(消去文字位置により戻す文字を変える) ymd = ('y' ,'y', '/', 'm', 'm', '/', 'd', 'd', '') new_var = s[0:int(i)] + ymd[int(i)] + s[int(i)+1:] self.entry1.delete(0, 'end') self.entry1.insert(0, new_var) self.entry1.icursor(i) # (3)挿入処理の時 if d == '1': # 入力文字が半角数字以外NG。8文字目以上入力不可(⇒入力前の文字列に戻す) flg = 0 # 9文字目(i=8)からは入力禁止 if int(i) > 7: flg = 1 # 英数半角以外NG。数字以外NG if unicodedata.east_asian_width(S) != 'Na' or S.isdecimal() == False: flg = 1 # 入力位置及び入力文字種異常の時は表示を元に戻す if flg == 1: self.entry1.delete(0, 'end') self.entry1.insert(0, s) self.entry1.icursor(i) # 入力文字種が正常の時の処理(主に「/」を挟んでのカーソル移動制御) if flg == 0: # 今回の入力位置 ichi = int(i) # 年月日入力が入力された時の表示文字列(「/」位置で入力があった場合は例外処理) new_var = s[0:ichi] + S + s[ichi + 1:] # 入力後のカーソル設定位置(通常現在位置の次。「/」位置の場合「/」の後に移動の為+2⇒別処理) pos = int(i) + 1 # 年、月の第2文字目入力の時 if i == '1' or i == '4': # 次の「/」の後ろにカーソル移動pos = pos + 1 pos = pos + 1 # 年、月の後の「/」に入力された時 # 入力値を消去しカーソル位置を「/」の後に強制移動 if i == '2' or i == '5' : new_var = s # 判定後の文字列表示 self.entry1.delete(0, 'end') self.entry1.insert(0, new_var) self.entry1.icursor(str(pos)) # 以下を入れないとフォーカスイン時は%d=-1だが文字入力すると%d=0の削除となる vcm_onValidate = (self.register(t2.hizuke_onValidate), '%d', '%i', '%p', '%s', '%S', '%v', '%V', '%W') vcm_inValidate = (self.register(t2.hizuke_inValidate), '%d', '%i', '%p', '%s', '%S', '%v', '%V', '%W') self.entry1["validate"] = "all" self.entry1["validatecommand"] = vcm_onValidate self.entry1["invalidcommand"] = vcm_inValidate ソースコード

試したこと

ワンファイルの時は下記にあるt1.py、t2.pyにある[t2.]は[self.]としてありました。

***** エントリー1への入力を判定(validatecommandの設定)

vcm_onValidate = (self.register(t2.hizuke_onValidate), '%d', '%i', '%p', '%s', '%S', '%v', '%V', '%W') vcm_inValidate = (self.register(t2.hizuke_inValidate), '%d', '%i', '%p', '%s', '%S', '%v', '%V', '%W')

ここに問題に対して試したことを記載してください。

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

ここにより詳細な情報を記載してください。

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

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

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

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

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

y_waiwai

2020/05/11 06:38

このままではコードが読めないので、質問を編集し、<code>ボタンを押し、出てくる’’’の枠の中にコードを貼り付けてください
guest

回答1

0

ベストアンサー

関数にすると、引数のself を自分で渡す必要がるので、
呼び出し時の引数の不一致でエラーになってます。
引数呼び出しがひとつづつずれて末尾の%W がない状態。

解決策:
A: class 内で import することで、メソッドとしてアクセス可能にする。
B: 明示的に呼び出し時に self を渡す。

python

1# (B) ここで import すると、hizuke_onValidateは通常の関数です。 2# import t2 3 4class MainWindow(ttk.Frame): 5 # (A) ここで import する事で、これらの関数はメソッドとしてアクセス可能になります。 6 from t2 import hizuke_onValidate, hizuke_inValidate 7 8 9# (A) ファイルを分割しても呼び出し時の変更の必要なく 10# self. 経由でアクセスできます。 11vcm_onValidate = (self.register(self.hizuke_onValidate), 12 '%d', '%i', '%p', '%s', '%S', '%v', '%V', '%W') 13vcm_inValidate = (self.register(self.hizuke_inValidate), 14 '%d', '%i', '%p', '%s', '%S', '%v', '%V', '%W') 15 16 17# (B) 従来の方法で self を明示的に渡す場合は、少し複雑になります。 18# functools を使った方法と、lambda を用いた場合の例 19from functools import partial 20vcm_onValidate = (self.register(partial(t2.hizuke_onValidate, self)), 21 '%d', '%i', '%p', '%s', '%S', '%v', '%V', '%W') 22vcm_inValidate = (self.register(lambda *args: t2.hizuke_onValidate(self, *args)), 23 '%d', '%i', '%p', '%s', '%S', '%v', '%V', '%W')

他の問題
処理内容については把握してませんが、関数呼び出し方法についてのみ。

t2.pyファイル 内では t2 は参照できないので、NameError となります。
上記の方法と同様の変更が必要ですが、
(B)の方法の場合、t2. ではないことに注意。

投稿2020/05/11 08:51

teamikl

総合スコア8664

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

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

akiteru

2020/05/11 09:24

何時も有難う御座います。いつもの様に安易な選択で(B)を採用させていただきます。NameError のご指摘は「t2.」を削除するとうまくいきました。「lambda *args: 」と「hizuke_onValidate(self, *args)」の意味は現状では理解していませんが。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問