🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Tkinter

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

button

HTMLで用いる<button>タグです。

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

Python

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

Q&A

解決済

2回答

4973閲覧

tkinterGUI上でボタンを押して実行した無限ループから同様にボタンを押して中断したい

sobagome

総合スコア9

Tkinter

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

button

HTMLで用いる<button>タグです。

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

Python

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

0グッド

0クリップ

投稿2021/03/16 09:39

前提・実現したいこと

tkinterにより作成したGUI上で「開始」ボタンを押して実行した無限ループから、
「停止」ボタンを押して処理を中断したい。
強制的に中断する方法としては、except KeyboardInterruptによってキー入力する等の方法が
あることは分かりましたが、そうではなく、GUI上のボタンを用いて中断させたいと思っています。
また、メインウインドウ自体を強制的に閉じる訳では無く、あくまで「開始」した処理を「停止」させたいです。

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

destroy()を使用する方法で何か出来ないかと考えていますが、エラーが発生します。 AttributeError: 'function' object has no attribute 'destroy'

該当のソースコード

python

1# -*- coding: utf-8 -*- 2 3import tkinter as tk 4 5class MainWin(tk.Frame): 6 def __init__(self,master): 7 super().__init__(master) 8 self.grid() 9 self.master.geometry("100x50") 10 self.master.title("MainWindow") 11 self.create_widgets() 12 13 def create_widgets(self): 14 # 実行ボタンの作成 15 button_run = tk.Button(self, text="実行", command=self.start) 16 button_run.grid(row=0, column=0) 17 # 停止ボタンの作成 18 button_stop = tk.Button(self, text="停止", command=self.stop) 19 button_stop.grid(row=0, column=1) 20 21 def start(self): 22 while True: 23 print("a") 24 25 def stop(self): 26 self.start.destroy() 27 28def main(): 29 root = tk.Tk() 30 app = MainWin(master=root) 31 app.mainloop() 32 33if __name__ == "__main__": 34 main() 35

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

Python 3.8.3

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

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

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

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

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

guest

回答2

0

ベストアンサー

特に何もしなければ、python(tkinterも含めて)のプロセス(=処理の流れ)は1つしかありません。
なので、どこかで無限ループしていると、ボタンの処理とか画面の更新とかができなくなります。

GUIを動かしながら、他に何かさせたければ、別のプロセスを作ってそこで実行する必要があります。 「マルチプロセッシング」で検索すると方法はみつかるでしょう。
また、別で動いているプロセスを止めたりするためには、「プロセス間通信」の仕組みを使う必要があります。これもいろいろ方法があるので、調べて実装しましょう。

投稿2021/03/16 12:02

TakaiY

総合スコア13758

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

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

sobagome

2021/03/17 06:00

別のプロセスを使用するという発想はありませんでした。 各々の用語も初耳ですので、調べて内容の理解に努めたいと思います。 ありがとうございました。
TakaiY

2021/03/17 06:42

そこそこ難しいと思いますが、Tkinter と からめて検索すると似たような処理の例がみつかります。
teamikl

2021/03/18 06:45

マルチスレッドだと思って読んで高評価しましたが 「マルチプロセス」を検討する前に、 「マルチスレッド」GUIを使わない時間のかかる処理 「タイマーを使う」GUIを伴うアニメーション用途 の検討をお勧めします。 ループの処理内容・用途次第では、 適切でなかったり冗長だったりする場合があります。
guest

0

あらかじめ変数を用意しといて、停止ボタンを押したら、Trueにするようにしておきます
その無限?ループの中でその変数をチェックして、Trueだったらループを終了するようにしておきます

投稿2021/03/16 11:12

y_waiwai

総合スコア88038

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

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

sobagome

2021/03/17 06:03

whileやforループではなく、after等で入力待ちが発生するループでは使えるということですかね。 今回のコードではwhileループなので、停止を押しても入力を受け付けないようです。 ありがとうございました。
teamikl

2021/03/18 06:46

おすすめの方法ではないけれど、time.sleep 等を使わないコードであれば while ループ内で root.update() を呼び出せば、入力受付可能です。 また、GUIのアニメーション等の用途であれば while や for のループをジェネレータで実装することで after を用いてループ処理を実行する方法もあります。(少し工夫は必要)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問