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

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

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

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

Python

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

Q&A

解決済

1回答

1557閲覧

Pyhton(TkInter) ScrolledTextの高さを把握したいが ひょっとして得られないでしょうか??(Canvasのサイズをそちらから導き、Canvasの中央座標に画像採用したい)

saya24

総合スコア222

Tkinter

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

Python

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

1グッド

0クリップ

投稿2020/06/13 07:44

編集2020/06/13 07:46

以下のコードは Python3の開発環境があり、当該コードの上位にimagesフォルダ、その中には robot.pngという 画像ファイルを配置頂いた上で
実行いただければ 相応に動作するものと思われます。

実行後 SUBというコマンドボタンを押下頂くと一つのダイアログが現れます。
キャンバスのWidgetがスクロールドテキストを覆っている部分があり、キャンバス右下のチェックボックスを選択すると、パスワードを求められます。
こちらに当日日付半角8桁を応えると 下に隠れいてる スクロールドテキストが現れてくる仕組みになっています。
![イメージ説明

【質問】
キャンパスのサイズをスクロールドテキストのサイズから自動で導きたいです。
その上で、キャンバスの縦横中央の座標位置に画像を採用するようにしたいです。

現在キャンバスの大きさ(高さ)を固定値で指定しているのには ネット上で スクロールドテキストの高さを取得する方法が調べられなかったためです。
どたなか 上記2点の対策方法を ご教示頂けないでしょうか よろしくお願い致します。

Python

1from tkinter import * 2import tkinter.ttk as ttk 3import tkinter.scrolledtext as tksc 4import math 5import datetime 6 7class Apprication(ttk.Frame): 8 9 global dt_now 10 dt_now = datetime.datetime.now() 11 12 def __init__(self, app): 13 super().__init__(app) 14 self.pack() 15 16 btn1 = ttk.Button(self, text="Sub", command=self.openDialog) 17 btn1.bind('<Return>', self.openDialog) 18 btn1.pack(fill = 'x') 19 btn1.focus_set() 20 21 btn2 = ttk.Button(self, text="Quit", command=app.quit) 22 btn2.bind('<Return>', lambda _: app.quit()) 23 btn2.pack(fill = 'x') 24 25 self.menu() 26 27 28 29 def focus_next(self, event): 30 event.widget.tk_focusNext().focus() 31 return "break" 32 33 34 35 def menu(self): 36 menu_top = Menu(app) 37 menu_file = Menu(menu_top, tearoff=False) 38 menu_open = Menu(menu_top, tearoff=False) 39 40 app.configure(menu=menu_top, bg="#F0FFFF") 41 42 menu_top.add_cascade (label='File(F)', menu=menu_file, underline=0) 43 44 menu_file.add_cascade(label='Open(O)', underline=0, menu=menu_open) 45 menu_open.add_command(label='Sub(S)', underline=0, command=self.openDialog) 46 menu_file.add_command(label='Quit(Q)',underline=0, command=app.quit) 47 48 49 50 51 52 # 子画面開く 53 def openDialog(self, event=None): 54 55 self.dialog = Toplevel(self) 56 self.dialog.title("Sub Menu") 57 58 #フォームサイズを実行端末から導き、ド真中に配置表示 59 lw = math.ceil(ww * 0.408) 60 lh = math.ceil(wh * 0.477) 61 self.dialog.geometry(str(lw)+"x"+str(lh)+"+"+str(int(ww/2-lw/2))+"+"+str(int(wh/2-lh/2)) ) 62 63 self.dialog.configure(bg="#F0FFFF") 64 self.dialog.resizable(0,0) 65 self.dialog.protocol('WM_DELETE_WINDOW', (lambda: 'pass')()) 66 67 # 当該ダイアログのカーソルを変更し、関数側でもカーソルを変更できるように 68 self.dialog['cursor'] = 'hand2' 69 self.this = self.dialog 70 71 # modalに 72 self.dialog.grab_set() 73 74 # コンボボックス 75 db = {1:"AAA",2:"BBB",3:"CCC"} 76 self.v1 = StringVar() 77 cmbox1 = ttk.Combobox(self.dialog, takefocus=1, width=5, justify=CENTER, values=list(db.keys()), state='readonly', textvariable=self.v1) 78 cmbox1.bind('<<ComboboxSelected>>', self.cmbox1_selected) 79 cmbox1.grid(row=0, column=0, padx=(10, 0), pady=(10,0), sticky=W+E) 80 cmbox1.focus_set() 81 82 83 # テキストボックス 84 self.txt1 = Entry(self.dialog, state="readonly", takefocus=1) 85 self.txt1.grid(row=0, column=1, columnspan=7, sticky=W+E, pady=(10,0)) 86 87 88 # 入力枠 89 self.scrtxt1 = tksc.ScrolledText(self.dialog, bg="black", fg="orange", font=("Helvetica",11), insertbackground="orange", blockcursor=True, height=6, state="disable", takefocus=1) 90 self.scrtxt1.bind("<Leave>", self.scrtxt1_Chk) 91 self.scrtxt1.grid(row=2, column=0, columnspan=11, sticky=W+E, padx=10) 92 self.scrtxt1.bind("<Tab>", self.focus_next) 93 94 95 # ★覆うキャンバス★ 96 global pngfile 97 self.cvs = Canvas(self.dialog, height=102) #本当は高さを直接記載したくなく、上記scrtxt1の高さから取得したい 98 pngfile = PhotoImage(file='images\robot.png') 99 self.cvs.create_image(0,0, image =pngfile, anchor=CENTER) #本当は 画像の配置をキャンバスのど真ん中に配置したい 100 self.cvs.grid(row=2, column=0, columnspan=11, sticky=W+E, padx=10) 101 102 103 # 実行ボタン 104 self.btn1 = Button(self.dialog, text='Execute', width=10, state=DISABLED, takefocus=1) 105 self.btn1.grid(row=3, columnspan=11, pady=(0, 20), sticky=N) 106 107 108 # 入力枠を表示・非表示の切替えチェックボックス 109 self.chbox2_var = BooleanVar(self.dialog) 110 self.chbox2 = Checkbutton(self.dialog, variable=self.chbox2_var, bg="#F0FFFF", command=self.chbox2_OnOff, takefocus=1) 111 self.chbox2.grid(row=3, column=8, pady=(0, 20), sticky=N) 112 113 114 # 閉じるボタン 115 btn3 = Button(self.dialog, text='Quit', command=self.closeDialog, width=10, takefocus=1) 116 btn3.grid(row=5, column=10, pady=10, padx=(0,10)) 117 118 119 self.dialog.grid_rowconfigure(1, weight=1) 120 self.dialog.grid_rowconfigure(3, weight=1) 121 self.dialog.grid_columnconfigure(2, weight=1) 122 123 124 125 126 # 子画面閉じる 127 def closeDialog(self): 128 self.dialog.destroy() 129 130 131 # コンボボックス選択値をテキストボックス表示 132 def cmbox1_selected(self, event): 133 self.txt1['state'] = 'normal' 134 self.txt1.delete(0, END) 135 self.txt1.insert(END, self.v1.get()) 136 self.txt1['state'] = 'readonly' 137 138 self.scrtxt1['state'] = 'normal' 139 self.btn1_Enable() 140 141 142 # SQL文の表示を許すか許さないか 143 def chbox2_OnOff(self): 144 if self.chbox2_var.get(): 145 self.pw_Open() 146 else: 147 self.cvs.grid() 148 149 # パスワードのダイアログを表示 150 def pw_Open(self, event=None): 151 lw = math.ceil(ww * 0.1) 152 lh = math.ceil(wh * 0.1) 153 self.pwentry = Toplevel(self.dialog) 154 self.pwentry.geometry(str(lw)+"x"+str(lh)+"+"+str(int(ww/2-lw/2))+"+"+str(int(wh/2-lh/2))) 155 156 157 # gridのcolumnを伸縮可能にする 158 self.pwentry.grid_columnconfigure(0, weight=1) 159 self.pwentry.grid_columnconfigure(1, weight=1) 160 161 162 self.txt9 = Entry(self.pwentry, show='*') 163 self.btn8 = Button(self.pwentry, text="Enter!", command=self.pw_On) 164 self.btn8.bind('<Return>', self.pw_On) 165 self.btn9 = Button(self.pwentry, text="Cancel", command=self.pw_Off) 166 self.btn9.bind('<Return>', self.pw_Off) 167 self.pwentry.title("Enter the password to view SQL") 168 self.pwentry.resizable(0,0) 169 self.pwentry.protocol('WM_DELETE_WINDOW', (lambda: 'pass')()) 170 self.txt9.grid(row=0, column=0, columnspan=2, sticky=W+E, padx=10, pady=(10,0)) 171 self.txt9.focus_set() 172 self.btn8.grid(row=1, column=0, sticky=W+E, padx=(10,0), pady=(0,10)) 173 self.btn9.grid(row=1, column=1, sticky=W+E, padx=(0,10), pady=(0,10)) 174 self.pwentry.grab_set() 175 176 # パスワードのダイアログは本日日付8桁を 177 def pw_On(self, event=None): 178 if self.txt9.get() == dt_now.strftime('%Y%m%d'): 179 self.cvs.grid_remove() 180 self.pwentry.destroy() 181 else: 182 self.chbox2.deselect() 183 self.pwentry.destroy() 184 185 # パスワードのダイアログ、キャンセルの場合閉じる 186 def pw_Off(self): 187 self.chbox2.deselect() 188 self.pwentry.destroy() 189 self.dialog.grab_set() 190 191 192 193 # 入力枠チェック 194 def scrtxt1_Chk(self, event): 195 self.btn1_Enable() 196 197 198 # 実行ボタンの有効化 199 def btn1_Enable(self): 200 if (self.scrtxt1.get('1.0', 'end -1c') != ""): 201 self.btn1['state'] = 'normal' 202 else: 203 self.btn1['state'] = 'disable' 204 205 206if __name__ == '__main__': 207 208 #世間でいうrootをappとしています 209 app = Tk() 210 211 #実行端末の画面サイズを取得 212 ww = app.winfo_screenwidth() 213 wh = app.winfo_screenheight() 214 215 app.update_idletasks() 216 217 #フォームサイズを実行端末から導き、ド真中に配置表示 218 lw = math.ceil(ww * 0.208) 219 lh = math.ceil(wh * 0.277) 220 app.geometry(str(lw)+"x"+str(lh)+"+"+str(int(ww/2-lw/2))+"+"+str(int(wh/2-lh/2)) ) 221 222 #タイトルを指定 223 app.title("Main Menu") 224 225 #フォームの最大化、×ボタン操作を無効化 226 app.resizable(0,0) 227 #app.protocol('WM_DELETE_WINDOW', (lambda: 'pass')()) 228 229 # カーソル変更 230 app["cursor"] = "hand2" 231 232 233 234 235 menu_top = Menu(app) 236 menu_file = Menu(menu_top, tearoff=False) 237 menu_open = Menu(menu_top, tearoff=False) 238 239 app.configure(menu=menu_top, bg="#F0FFFF") 240 241 menu_top.add_cascade (label='File(F)', menu=menu_file, underline=0) 242 243 menu_file.add_cascade(label='Open(O)', underline=0, menu=menu_open) 244 menu_open.add_command(label='Sub(S)', underline=0, command="app.openDialog") 245 menu_file.add_command(label='Quit(Q)',underline=0, command=app.quit) 246 247 248 249 250 # フレームを作成する 251 frame = Apprication(app) 252 # 格納したTkインスタンスのmainloopで画面を起こす 253 app.mainloop()
teamikl👍を押しています

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

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

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

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

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

guest

回答1

0

ベストアンサー

winfo_height() で所得できますが、少し工夫が必要で、
サイズが決まるのはレイアウトにより配置された後
__init__ が終わり mainloop() に処理が戻った後なので、

__init__ 内でサイズを得たい場合は、update()を呼び出し
先に描画を更新してから問い合わせます。

python

1 # 入力枠 2 self.scrtxt1 = tksc.ScrolledText(self.dialog, bg="black", fg="orange", font=("Helvetica",11), insertbackground="orange", blockcursor=True, height=6, state="disable", takefocus=1) 3 self.scrtxt1.grid(row=2, column=0, columnspan=11, sticky=W+E, padx=10) 4 5 6 self.update() 7 scrtxt1_height = self.scrtxt1.winfo_height() 8

画像の中央配置は、create_canvas の座標を中心に置かれるので、
キャンバスの半分のサイズを指定すると中央配置になります。

投稿2020/06/13 15:41

teamikl

総合スコア8664

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

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

saya24

2020/06/14 02:18

teamiklさん いつもご支援を頂きまして 誠にありがとうございます。 スクロールドテキストの縦サイズ、無事に取得できました。 申し訳ありません、何から何まで聞いてしまって、 >キャンバスの半分のサイズを指定すると中央配置になります キャンバスのサイズもupdateしないと得られず、update後に.winfo_heightと.winfo_widthを2で割って座標位置を割り出す必要がある と申されていますか? 勘違いしていないかの確認でございます...
teamikl

2020/06/14 02:32

キャンバスのサイズは、 スクロールドテキストのサイズと同じになってるはずなので、 キャンバスのサイズを再確認しなくても、スクロールドテキストのサイズを使えますよ。 もし改めてキャンバスのサイズを得るならレイアウト(grid,pack)の後に、update() は必要です。 但し、注意点ですが、コンストラクタに渡す width引数 と winfo_width() で得られる値は一致するとは限りません。レイアウトの影響もありますが、 ウィジェットにより、ピクセル数だったり文字数だったりします。 Text, Entry 等のwidth は文字数・フォントサイズに影響されます。
saya24

2020/06/14 02:51

>キャンバスのサイズを再確認しなくても、スクロールドテキストのサイズを使えますよ。 そうでした、widthが登場していなかったので わざわざキャンバス側で取得しようとしてしまいました。 注意点までご教示頂き ありがとうございます。みた感じ大満足です、今回も助けられました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問