简体   繁体   中英

Making a switch button using "threading" module for executing while loop

I want to make program which a has button, when we click on button, it will run some functions infinitely and the button turn into another button such that when we click it second time, it will stop the infinite process. In my codes you can see my aim.

When i do not click on button, there is a text on button such as "start", and when i click first time, it starts an infinite process such as printing two functions. After that, the button turn into a red color button which has text "stop" and when you click it second time, it stops this infinite while loop.

What I want: I want to convert my button into a switch such that when i click it second time, it stop the process, but be ready for running it again. What i meant is that when i click it second time, it stop the process and its color be green and text = "start", again.I want this clicking process foreover such as a switch of a lamb.When you click it, it will be ready for the other process.

My problem: When i click the button second time, my code gives error. It did not turn into "start" button again". Can you help me to fix it.

Note: I am beginner in "threading" module,so please be clear in your answers.

MY CODE:

from tkinter import *
from tkinter import ttk
import threading
class Uygulama(object):
    def __init__(self):
        self.araclar()
    def araclar(self):
        self.etiket1 = Label(text="WELCOME TO HERE", fg="blue", font="Times 15 bold", 
                      bg="grey")
        self.etiket1.pack()
        
        self.stop_event = threading.Event()
        self.thread = threading.Thread(target=self.start, args=(self.stop_event,))
        self.dugme1 = Button( text="Start Greeting", command=self.start_cmd, 
                             fg="black", bg="green", font="bold")
        self.dugme1.place(relx=0.05, rely=0.65)

        self.etiket3 = Label(font="Times 14 bold", bg="grey")
        self.etiket3.place(rely=0.30, relx=0.08)

    def say_hello(self):
        print("Hello there")

    def say_hi(self):
        print("hi there")

    def start_cmd(self):
        self.dugme1.config(text="Stop greeting", command=self.stop_cmd,fg="black", bg="red", 
                             font="bold")
        self.thread.start()

    def stop_cmd(self):
        self.stop_event.set()
        self.destroy()

    def start(self, stop_event):
        self.etiket3.config(text="You are greeting them !",  font="Times 17 bold")                              
        while not stop_event.is_set():
            self.say_hello()
            self.say_hi()

pencere = Tk()
pencere.geometry("500x500+400+30")
pencere.resizable(width=False, height=False)
pencere.configure(bg="grey")
uyg = Uygulama()
mainloop()

The error:

Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python3.10/tkinter/__init__.py", line 1921, in __call__
  return self.func(*args)
File "/home/sunw/Desktop/uygulama.py", line 34, in stop_cmd
  self.destroy()
AttributeError: 'Uygulama' object has no attribute 'destroy'

** ADDING DESTROY:**

def destroy(self):
    self.dugme1.config(text="Start Greeting", command=self.start_cmd,
                       fg="black", bg="green", font="bold")

New error:

Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python3.10/tkinter/__init__.py", line 1921, in __call__
 return self.func(*args)
File "/home/sunw/Desktop/uygulama.py", line 35, in start_cmd
  self.thread.start()
File "/usr/lib/python3.10/threading.py", line 930, in start
 raise RuntimeError("threads can only be started once")
RuntimeError: threads can only be started once

As explained, not sure what was the purpose for self.destroy(), just remove that.

Also threads once defined can be started only once, see https://bugs.python.org/issue751260

Remove self.thread declaration from araclar, and have start and stop functions as below:

def start_cmd(self):
    self.dugme1.config(text="Stop greeting", command=self.stop_cmd, fg="black", bg="red",
                       font="bold")
    self.stop_event.clear()
    threading.Thread(target=self.start, args=(self.stop_event,)).start()

def stop_cmd(self):
    self.stop_event.set()
    self.dugme1.config(text="Start Greeting", command=self.start_cmd,
                         fg="black", bg="green", font="bold")

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2025 STACKOOM.COM