clearly_blurry
clearly_blurry

Reputation: 1

Running two python tkinter buttons at the same time

I have a program (The whole project is written in python and ran on a Raspberry Pi) that has a complete tkinter front end. I have some code to take measurements from a sensor and turn a motor in separate python files and that all works fine. The problem I have is that this backend is started by the user pressing a button, but they can't press another button while this is running. So this means they can't stop it either. My question is about how I can allow two buttons to run at once. I've tried doing a similar thing with a program that uses much less processing power, and it still didn't work so I know that's not the problem.

Here's how I've done the backend:

# Some import statements
def run():
  r = 0   # To ensure it will loop
  x_angle = sensor.get_x_rotation()
  print("The x angle is {}".format(x_angle))
  while r == 0:
    x_angle = sensor.get_x_rotation()
    if x_angle < 0:
        print("The x angle is now {}".format(x_angle))
        motor.run_motor(direction="clockwise")
        led.on()
        sleep(0.5)
        led.off()
    elif x_angle > 0:
        print("The x angle is currently {}".format(x_angle))
        motor.run_motor(direction="anti")
        led.on()
        sleep(0.5)
        led.off()
    else:
        print("The x angle is currently {}".format(x_angle))
        led.on()
        sleep(0.5)
        led.off()   ` 

A little clip of how I've written the GUI

# import statements, a couple of variables, Some colour definitions

# buttons
S = a(top, bg=(green), text= "Start Program", font=("Segoe UI Black", 40), height="2", width="15", command=lambda: main.run())
C = a(top, bg=(red), text="Stop Program", font=("Segoe UI Black", 40), height="2", width="15", command=lambda: main.quit())
R = a(top, text="View Reports", font=("Segoe UI",20), height="2", width="30")
P = a(top, text="View Current Process", font=("Segoe UI",20), height="2", width="30")
H = a(top, text="Help", font=("Segoe UI",20), height="2", width="30", command=lambda: help())
Q = a(top, bg=(blue), text="Quit", font=("Segoe UI Black", 35), height="2", width="17", command=lambda: ensure())

S.pack()
C.pack()
R.pack()
P.pack()
H.pack()
Q.pack()
tkinter.tk.mainloop()

Upvotes: 0

Views: 1613

Answers (2)

Mike - SMT
Mike - SMT

Reputation: 15226

sleep() and Tkinter do not work together. The only time you are able to use sleep() while also using Tkinter is if you do it in separate threads. This is where after() is useful and should work here for you.

The problem with sleep() is the fact it freezes the Tkinter instance until the time has elapsed. When we use after() we are adding an event to be triggered after a set amount of time so this does not freeze the mainloop().

I used root as your tkinter instance name so you will need to replace this with whatever your name is set to for your instance.

Try this and let me know if it helps.

def run():
  r = 0   # To ensure it will loop
  x_angle = sensor.get_x_rotation()
  print("The x angle is {}".format(x_angle))
  while r == 0:
    x_angle = sensor.get_x_rotation()
    if x_angle < 0:
        print("The x angle is now {}".format(x_angle))
        motor.run_motor(direction="clockwise")
        led.on()
        root.after(500, led.off)
    elif x_angle > 0:
        print("The x angle is currently {}".format(x_angle))
        motor.run_motor(direction="anti")
        led.on()
        root.after(500, led.off)
    else:
        print("The x angle is currently {}".format(x_angle))
        led.on()
        root.after(500, led.off)

Upvotes: 1

Novel
Novel

Reputation: 13729

You need threading to run 2 parts of your program "asynchronously". Untested guess:

from threading import Thread

def threaded_run(): 
    t = Thread(target=main.run)
    t.daemon = True
    t.start()

S = a(top, bg=(green), text= "Start Program", font=("Segoe UI Black", 40), height="2", width="15", command=threaded_run)

Integrating the main.quit may be a lot harder depending on what that function does. If all it does is set the global variable 'r' to stop the loop then you can leave it as is. Otherwise you may need to walk though a couple threading tutorials to learn to make your own Thread class.

Upvotes: 2

Related Questions