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

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

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

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

Q&A

解決済

1回答

2402閲覧

python tkinter クリックする度に重くなるのを回避するには?

vibrato

総合スコア52

Python

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

0グッド

0クリップ

投稿2018/09/18 12:42

将棋盤を模したボードを再現し、クリックした部分の色が変わるという動作をさせています。

別の場所をクリックすると、以前にクリックした場所の色が元に戻るようにしているのですが、
「上書き描写」という方法でその動作を再現しているので、タイトルにもある通りクリックする度に重くなっているのだと思います。

重くなることを回避できる、良い記述方法はありますでしょうか?

python

1import tkinter as tk 2root = tk.Tk() 3root.geometry("960x480") 4root.title("ボード") 5 6BOADTYPE = 9 7 8size = 40 9base_x = 0 10base_y = 1 11BaseColor = "#e9967a" 12ClickedColore = "#a52a2a" 13 14def OneSquareDisplay(position, _bg): 15 label = tk.Label(root, bg=_bg) 16 label.userOwnValue = position 17 label.place(x=size*(BOADTYPE-position//BOADTYPE+base_x), y=size*(position%BOADTYPE+base_y), height=size-1, width=size-1) 18 label.bind("<1>",Callback) 19 20 21def BoadGeneration(): 22 for i in range(BOADTYPE**2): 23 OneSquareDisplay(i, BaseColor) 24 25 26def Callback(event): 27 click = event.widget.userOwnValue 28 click = int(str(click)) 29 print(click+1) 30 BoadGeneration() 31 OneSquareDisplay(click, ClickedColore) 32 33 34BoadGeneration() 35tk.mainloop() 36 37

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

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

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

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

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

guest

回答1

0

ベストアンサー

現状のコードではクリックする毎に BoadGeneration() が呼ばれるので、81個のLabelsが生成(&上書き)されております。

つまり1度クリックされると全部で162個のラベルが、2度クリックされると243個のラベルが、ボード上に配置されていることになりますのでクリック毎にどんどん『重く』なっていくのかと思います。

ということで、クリックする毎にLabelを新たに生成するのではなく、単にクリックされたLabelの背景色を変更するだけの処理を行う、具体的に書くと Callback()の処理を

Python

1def Callback(event): 2 click = event.widget.userOwnValue 3 click = int(str(click)) 4 print(click+1) 5 event.widget.config(bg=ClickedColore) 6 # BoadGeneration() 7 # OneSquareDisplay(click, ClickedColore)

のように修正すると良いのではないでしょうか


【追記】

背景色をトグル動作したい場合は、こんな感じで現在の背景色によって処理を変えればよいかと思います。

Python

1def Callback(event): 2 click = event.widget.userOwnValue 3 click = int(str(click)) 4 print(click+1) 5 if event.widget.cget('bg') == BaseColor: 6 event.widget.config(bg=ClickedColore) 7 else: 8 event.widget.config(bg=BaseColor)

【更に追記】

Python

1def Callback(event): 2 click = event.widget.userOwnValue 3 click = int(str(click)) 4 print(click+1) 5 6 # 全てのLabelの色を戻す 7 for child in root.winfo_children(): 8 if child.winfo_class() == 'Label': 9 child.config(bg=BaseColor) 10 # クリックされてLabelの色を変更 11 event.widget.config(bg=ClickedColore)

投稿2018/09/19 01:03

編集2018/09/19 12:27
magichan

総合スコア15898

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

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

vibrato

2018/09/19 11:31

回答ありがとうございます。 教えていただいた方法を試してみたところ、一度クリックした位置の背景色は変更されたままになるのですが、希望している処理は次回クリック時に、新たにクリックした場所以外の背景色は元に戻る動作を望んでおります。そのように動作させる方法はありますでしょうか?
magichan

2018/09/19 11:43

補足を追加しました
vibrato

2018/09/19 12:09

返信及び追記ありがとうございます。 追記していただいた動作ですと、クリックした場所の背景色のみが変わるという動作ですが、 例 マスAをクリック(マスAの色が変わる) ↓ マスBをクリック(マスBの色が変わる)(マスAの色が戻る) このようにBをクリックすることで、Bの色の変更及び、Aの色の戻しを行いたいと考えております。 可能でしょうか?
magichan

2018/09/19 12:26

やり方としては、 方法1:色が変わっている(前回クリックした)Labelを覚えておいて、Callback関数内にて戻す処理を入れる 方法2:Callback関数内で 全てのLabelの色を一旦戻した後に、クリックされたLabelの色を変更する あたりで出来るかと。
magichan

2018/09/19 12:34

方法2での実装例を追加しました
vibrato

2018/09/19 13:21

希望の動作をさせることができました。丁寧にわかりやすく教えていただきありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問