標題の件、ありがちな質問かもしれませんがよろしくお願いします。各Widgetには takefocus=1 のフォーカス遷移対象の設定を行っています。
つまりは ScrolledTextの中では タブが 別の機能(インデント飛ばし)として働いてしまうがゆえのことと思われます。
尚、下記コードでは
・コンボボックスからなんらかのアイテムが選択されている
・ScrolledTextに何らかの文字が入力されている
双方の条件が整わない限り 配置のボタンは 有効(status='normal')にならないようにしているつもりです。
(ScrolledTextからフォーカスが抜けたら、という手続きを 現在は イベントのバインドに<Leave>を設定して対応しています。
タブキーがうまく作用しない関係で、現在はマウスのカーソルが当該Widgetから外れた場合だけ ScrolledTextの入力枠チェックが働いている状態です)
よろしくお願いします。
Python
1from tkinter import * 2import tkinter.ttk as ttk 3import tkinter.scrolledtext as tksc 4import math 5 6 7 8class Apprication(ttk.Frame): 9 10 def __init__(self, app): 11 super().__init__(app) 12 self.pack() 13 14 btn = ttk.Button(self, text="Sub", command=self.openDialog) 15 btn.grid(row=1, column=0) 16 17 18 19 # 子画面開く 20 def openDialog(self): 21 22 self.dialog = Toplevel(self) 23 self.dialog.title("Sub Menu") 24 25 #フォームサイズを実行端末から導き、ド真中に配置表示 26 lw = math.ceil(ww * 0.408) 27 lh = math.ceil(wh * 0.477) 28 self.dialog.geometry(str(lw)+"x"+str(lh)+"+"+str(int(ww/2-lw/2))+"+"+str(int(wh/2-lh/2)) ) 29 30 self.dialog.configure(bg="#F0FFFF") 31 self.dialog.resizable(0,0) 32 self.dialog.protocol('WM_DELETE_WINDOW', (lambda: 'pass')()) 33 34 # 当該ダイアログのカーソルを変更し、関数側でもカーソルを変更できるように 35 self.dialog['cursor'] = 'hand2' 36 self.this = self.dialog 37 38 # modalに 39 self.dialog.grab_set() 40 41 42 43 # コンボボックス 44 db = {1:"AAA",2:"BBB",3:"CCC"} 45 self.v1 = StringVar() 46 cmbox1 = ttk.Combobox(self.dialog, takefocus=1, width=5, justify=CENTER, values=list(db.keys()), state='readonly', textvariable=self.v1) 47 cmbox1.bind('<<ComboboxSelected>>', self.cmbox1_selected) 48 cmbox1.grid(row=0, column=0, padx=(10, 0), pady=(10,0), sticky=W+E) 49 cmbox1.focus_set() 50 51 52 # テキストボックス 53 self.txt1 = Entry(self.dialog, state="readonly", takefocus=1) 54 self.txt1.grid(row=0, column=1, columnspan=7, sticky=W+E, pady=(10,0)) 55 56 57 # ★入力枠★ 58 self.scrtxt1 = tksc.ScrolledText(self.dialog, bg="black", fg="orange", font=("Helvetica",11), insertbackground="orange", blockcursor=True, height=6, state="disable", takefocus=1) 59 self.scrtxt1.bind("<Leave>", self.scrtxt1_Chk) 60 self.scrtxt1.grid(row=2, column=0, columnspan=11, sticky=W+E, padx=10) 61 62 63 # 実行ボタン 64 self.btn1 = Button(self.dialog, text='Execute', width=10, state=DISABLED, takefocus=1) 65 self.btn1.grid(row=3, columnspan=11, pady=(0, 20), sticky=N) 66 67 68 # 閉じるボタン 69 btn3 = Button(self.dialog, text='Quit', command=self.closeDialog, width=10, takefocus=1) 70 btn3.grid(row=5, column=10, pady=10, padx=(0,10)) 71 72 73 self.dialog.grid_rowconfigure(1, weight=1) 74 self.dialog.grid_rowconfigure(3, weight=1) 75 self.dialog.grid_columnconfigure(2, weight=1) 76 77 78 79 80 # 子画面閉じる 81 def closeDialog(self): 82 self.dialog.destroy() 83 84 85 # コンボボックス選択値をテキストボックス表示 86 def cmbox1_selected(self, event): 87 self.txt1['state'] = 'normal' 88 self.txt1.delete(0, END) 89 self.txt1.insert(END, self.v1.get()) 90 self.txt1['state'] = 'readonly' 91 92 self.scrtxt1['state'] = 'normal' 93 self.btn1_Enable() 94 95 96 # ★★★入力枠チェック★★★ 97 def scrtxt1_Chk(self, event): 98 self.btn1_Enable() 99 100 101 # 実行ボタンの有効化 102 def btn1_Enable(self): 103 if (self.scrtxt1.get('1.0', 'end -1c') != ""): 104 self.btn1['state'] = 'normal' 105 else: 106 self.btn1['state'] = 'disable' 107 108 109if __name__ == '__main__': 110 111 #世間でいうrootをappとしています 112 app = Tk() 113 114 #実行端末の画面サイズを取得 115 ww = app.winfo_screenwidth() 116 wh = app.winfo_screenheight() 117 118 app.update_idletasks() 119 120 #フォームサイズを実行端末から導き、ド真中に配置表示 121 lw = math.ceil(ww * 0.208) 122 lh = math.ceil(wh * 0.277) 123 app.geometry(str(lw)+"x"+str(lh)+"+"+str(int(ww/2-lw/2))+"+"+str(int(wh/2-lh/2)) ) 124 125 #タイトルを指定 126 app.title("Main Menu") 127 128 #フォームの最大化、×ボタン操作を無効化 129 app.resizable(0,0) 130 #app.protocol('WM_DELETE_WINDOW', (lambda: 'pass')()) 131 132 # カーソル変更 133 app["cursor"] = "hand2" 134 135 app.configure(bg="#F0FFFF") 136 137 # フレームを作成する 138 frame = Apprication(app) 139 # 格納したTkインスタンスのmainloopで画面を起こす 140 app.mainloop()
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/05/18 06:08
2020/05/18 06:39 編集
2020/05/18 06:52