Yes, you can use tkinter.after() to create sequential operations.
How tkinter.after() works:
Non-blocking: this function schedules callbacks to run later without blocking the mainloop.
sequential timing: each after() call's delay is relative to when it was scheduled, not when the previous one completed.
chaining: You can chain operations by scheduling the next step in the current step's callback.
what you can do:
chain after() calls:
def start_cycle():
plc.write((onTag, 1))
cycleStartWidget.grid()
print("Cycle started\nCycle running...")
# Schedule cycle finish after runtime
widget.after(cycle_runtime * 1000, finish_cycle)
def start_logger():
logger.start()
# Schedule PLC write after 3 seconds
widget.after(3000, start_cycle)
def start_sequence():
print("Log script starting")
logStartWidget.grid()
# Start logger immediately
widget.after(0, start_logger)
def finish_cycle():
print("Cycle finished")
plc.write((onTag, 0))
logger.stop()
cycleRunningWidget.grid_remove() # or whatever cleanup needed
or, use a single timeline:
def handle_cycle_start():
plc.write((onTag, 1))
cycleStartWidget.grid()
print("Cycle started\nCycle running...")
def handle_cycle_end():
print("Cycle finished")
plc.write((onTag, 0))
logger.stop()
def start_sequence():
print("Log script starting")
logStartWidget.grid()
logger.start()
# Schedule all events relative to start time
widget.after(3000, handle_cycle_start)
widget.after(3000 + cycle_runtime*1000, handle_cycle_end)
differences:
In your question's example, cycleStartWidget.grid() would execute immediately after logStartWidget.grid(), not waiting for the 3-second delay
Each after() call's time is relative to when it was scheduled from the main thread
For truly sequential operations, you should chain them (Option 1) rather than scheduling all at once
the chained approach is generally clearer and the recommended best practice for sequential operations because:
It makes the sequence of events more obvious
Each step clearly follows the previous one
It's easier to add error handling between steps
also, remember that all GUI updates (like grid()) must happen in the main thread, which after() handles properly.
Edit: As @TheLizzard pointed out:
Using multiple statements inside a lambda is discouraged in python since it's much harder to read. For clarity, I suggest defining a separate helper function.
so I edited my code to fix that. 😀
afterto run itself - and this way you will have loop which updates data periodically. There are examples which uses it to display current time.