adding button status updates to countdown counter - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: GUI (https://python-forum.io/forum-10.html) +--- Thread: adding button status updates to countdown counter (/thread-33322.html) |
adding button status updates to countdown counter - knoxvilles_joker - Apr-15-2021 I have gotten my script farther and farther along thanks to some help here. I am now trying to get things to where the temperature bar has an automatic cool down to a set level if the keyboard is not pressed, a temperature warning and stop on further key presses until a quarter second cool down occurs and then a critical alert at 100 rounds and 0 round alert. The alerts would come from one button/label. Programatically is there a good example I can reference so I can figure this out a little more easily myself? This is the code: import tkinter.ttk as ttk import tkinter as tk # sets ammo count to initial value of 500 INITIAL_COUNTER_VALUE = 500 # sets initial time at 100% INITIAL_TIMER_VALUE = 33000 # sets initial gun terminal ID #sets gun rate RMMAX = 0 # sets initial temparature TEMP_INITIAL = 30 # sets text string for ammo/temp/low ammo status button STATUS = "OK" # initial class declaration for main body of program class TkApp(tk.Tk): # these arguments initialize the class and how to form arguments within def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # set screen options self.geometry("640x400") self.configure(bg='black') self.title("Sentry Terminal") # locally initialize ammo count down self.counter = tk.IntVar() self.counter.set(INITIAL_COUNTER_VALUE) # locally sets the timer count down at 100% self.timer = tk.IntVar() self.timer.set(INITIAL_TIMER_VALUE) # locally sets rmbar to 0% self.rmcount = tk.IntVar() self.rmcount.set(RMMAX) # locally sets tempbar self.temperature = tk.IntVar() self.temperature.set(TEMP_INITIAL) # locally sets text string for ammo status button self.stat = tk.StringVar() self.stat.set(STATUS) # this arranges the grid row and column groupings. tk.Grid.rowconfigure(self, 0, weight=1, uniform='c') tk.Grid.rowconfigure(self, 1, weight=1, uniform='b') tk.Grid.rowconfigure(self, 2, weight=1, uniform='b') tk.Grid.rowconfigure(self, 3, weight=1, uniform='b') tk.Grid.rowconfigure(self, 4, weight=1, uniform='b') tk.Grid.rowconfigure(self, 5, weight=1, uniform='b') tk.Grid.rowconfigure(self, 6, weight=1, uniform='b') tk.Grid.rowconfigure(self, 7, weight=1, uniform='b') tk.Grid.rowconfigure(self, 8, weight=1, uniform='b') tk.Grid.columnconfigure(self, 0, weight=1, uniform='a') tk.Grid.columnconfigure(self, 1, weight=1, uniform='a') tk.Grid.columnconfigure(self, 2, weight=1, uniform='a') tk.Grid.columnconfigure(self, 3, weight=1, uniform='a') tk.Grid.columnconfigure(self, 4, weight=1, uniform='a') tk.Grid.columnconfigure(self, 5, weight=1, uniform='a') # these are the button and label declarations rounds = tk.Label(self, justify=tk.CENTER, textvariable=self.counter) rounds.grid(row=3, column=2, columnspan=1, sticky="EW") label1 = tk.Label(self, textvariable=self.timer) label1.grid(row=7, column=2, sticky="EW") temp = tk.Button(self,justify=tk.CENTER,text="Temp",bg='black', fg='yellow', highlightbackground='yellow', highlightcolor='black',activebackground='yellow') temp.grid(row=2,column=4,sticky="NSEW") rm = tk.Button(self,justify=tk.CENTER,text="R(M)",bg='black', fg='yellow', highlightbackground='yellow', highlightcolor='black',activebackground='yellow') rm.grid(row=2,column=5,sticky="NSEW") # rounds rate bar rmbar = ttk.Progressbar(self, orient="vertical", variable=self.rmcount) rmbar.grid(row=3,column=5,rowspan=6, sticky="NS") # temperature bar tempbar = ttk.Progressbar(self, orient="vertical", variable=self.temperature) tempbar.grid(row=3,column=4,rowspan=6,sticky="NS") # declarative buttons timestat = tk.Button(self,bg='black',state=tk.DISABLED, fg='yellow',disabledforeground='yellow',highlightbackground='yellow',borderwidth=2,justify=tk.CENTER,text="TIME AT 100% \n (msecs)") timestat.grid(row=7,column=0,columnspan=2,sticky="NSEW") roundsr = tk.Button(self,bg='black',state=tk.DISABLED, fg='yellow',disabledforeground='yellow',highlightbackground='yellow',borderwidth=2,justify=tk.CENTER,text="Rounds \n Remaining") roundsr.grid(row=3,column=0,columnspan=2,sticky="NS") # crit menu bar crit = tk.Button(self,justify=tk.CENTER,textvariable=self.stat, bg='black', fg='yellow', highlightbackground='yellow', highlightcolor='black',activebackground='yellow') crit.grid(row=5,column=0,columnspan=2,sticky="NSEW") # static center header headernew = tk.Button(self, bg='black',state=tk.DISABLED,justify=tk.CENTER, text="UA 571-C \n REMOTE SENTRY WEAPON SYSTEM") headernew.grid(row=0,column=1,columnspan=4,rowspan=2,sticky="NSEW") # displays gun id on top left and right of screen gun_1 = tk.Label(self, borderwidth=7,bg='black',fg='yellow',disabledforeground='yellow',state=tk.DISABLED,text="kp") gun_1.grid(row=0,column=0,rowspan=2,sticky="NS") gun_2 = tk.Button(self, borderwidth=7,bg='black',fg='yellow',disabledforeground='yellow',state=tk.DISABLED,text="kp") gun_2.grid(row=0,column=5,rowspan=2,sticky="NS") # this quits by clicking a button labeled q quit = tk.Button(self, bg='black', fg='yellow', text='q', command=self.quit) quit.grid(row=8,column=0,sticky="SW") # these are the attachments for input from keyboard into the application # These are the button inputs from the original flash app that were used # I added a q as well to quit and close window in case there was a need to close self.bind("<KeyPress-f>", self.on_keypress_f) self.bind("<KeyRelease-f>", self.on_keyrelease_f) self.bind("<KeyPress-a>", self.on_keypress_a) self.bind("<KeyPress-b>", self.on_keypress_b) self.bind("<KeyPress-c>", self.on_keypress_c) self.bind("<KeyPress-d>", self.on_keypress_d) self.bind("<KeyPress-r>", self.on_keypress_r) self.bind("<KeyPress-q>", self.on_keypress_q) self.bind("<KeyPress-space>", self.on_keypress_space) # this defines the fire ammo count down sequence and resets def on_keypress_f(self, evet): counter_value = self.counter.get() counter_value = counter_value-1 or INITIAL_COUNTER_VALUE self.counter.set(counter_value) # this is logic to try and get ammo warnings if counter_value == 490: stat_value = "OUT" else: stat_value = "OK" self.stat.set(stat_value) # this sets the time at 100% timer_value = self.timer.get() timer_value = timer_value-66 or INITIAL_TIMER_VALUE self.timer.set(timer_value) # this sets the rmbar to 40% rmcount_count = self.rmcount.get() rmcount_count = 40 self.rmcount.set(rmcount_count) # this sets the temperature temperature_count = self.temperature.get() temperature_count = temperature_count+1 self.temperature.set(temperature_count) def on_keyrelease_f(self, evet): #this adds logic to say rate is zero if not firing rmcount_count = self.rmcount.get() rmcount_count = 0 self.rmcount.set(rmcount_count) # this adds logic to say if not firing cool down temperature_count = self.temperature.get() temperature_count = temperature_count-10 self.temperature.set(temperature_count) # this sets the gun terminal identification # this can also be expanded to do other things if you want to alter the script def on_keypress_a(self, evet): counter_value = self.counter.get() counter_value = counter_value-1 or INITIAL_COUNTER_VALUE self.counter.set(counter_value) def on_keypress_b(self, evet): counter_value = self.counter.get() counter_value = counter_value-1 or INITIAL_COUNTER_VALUE self.counter.set(counter_value) def on_keypress_c(self, evet): counter_value = self.counter.get() counter_value = counter_value-1 or INITIAL_COUNTER_VALUE self.counter.set(counter_value) def on_keypress_d(self, evet): counter_value = self.counter.get() counter_value = counter_value-1 or INITIAL_COUNTER_VALUE self.counter.set(counter_value) def on_keypress_space(self, evet): counter_value = self.counter.get() counter_value = counter_value-1 or INITIAL_COUNTER_VALUE self.counter.set(counter_value) # this reloads the window, you have to click it to make it the active window again def on_keypress_r(self, evet): self.destroy() self.__init__() # this quits and closes the window by hitting a single key def on_keypress_q(self, evet): self.quit() # this executes the main loop and tkinter self delcared class. It declares the function then runs it in the main loop. tk_app = TkApp() tk_app.mainloop() RE: adding button status updates to countdown counter - knoxvilles_joker - Apr-15-2021 If I need to make a separate thread on each Issue, just say the word and I will do so. RE: adding button status updates to countdown counter - Yoriz - Apr-15-2021 You could do this by using a timer similar to this post You can then check on the state of things at a certain interval of time passed and adjust things as needed. RE: adding button status updates to countdown counter - knoxvilles_joker - Apr-16-2021 (Apr-15-2021, 06:26 PM)Yoriz Wrote: You could do this by using a timer similar to this post Well I added these functions to the class: def coolbar(self): temperature_count = self.temperature.get() self.temperature.set(temperature_count) while temperature_count >= 20: self.temperature.set(temperature_count) temperature_count = temperature_count-1 self.temperature.set(temperature_count) print("key not pressed") # time.sleep(0.1) def overheat(self): temperature_count = self.temperature.get() temperature_count = temperature_count-1 self.temperature.set(temperature_count) print("overheat") time.sleep(0.1)The coolbar or cooldown function auto resets to the starting value on the bar. It behaves kind of like I want. The coolbar only seems to work when I use a while loop. Unfortunately I can not use a time.sleep function on it as that seems to break things. I think the issue is that it is not updating the screen draw as it is cooling down in the while loop. RE: adding button status updates to countdown counter - Yoriz - Apr-17-2021 A while loop with a time.sleep will block the GUI's loop which I why I suggested using a timer and altering the state at an interval of time passed. RE: adding button status updates to countdown counter - knoxvilles_joker - Apr-17-2021 (Apr-17-2021, 04:40 PM)Yoriz Wrote: A while loop with a time.sleep will block the GUI's loop which I why I suggested using a timer and altering the state at an interval of time passed. I have slept some. I will try that approach again. Learning is learning. Failing to make something work teaches one that a way of doing something does not work. Thanks for the pointers and help! RE: adding button status updates to countdown counter - knoxvilles_joker - Apr-17-2021 With the example you provided using the: self.after(msec, self.function) helped a lot. I just have to figure out logic to make the cycling work properly, but that is progressing slowly, I think. logic in programs is not failable, only the creator is. RE: adding button status updates to countdown counter - knoxvilles_joker - Apr-18-2021 The bars are working the way I want now. the self.after(msec, functionname) command did the trick. This function: def coolbar(self): temperature_count = self.temperature.get() if temperature_count >= 21: temperature_count = self.temperature.get() temperature_count = temperature_count-1 or TEMP_INITIAL self.temperature.set(temperature_count) print("key not pressed", temperature_count) self.after(300, self.coolbar)with this one on key release f: def on_keyrelease_f(self, evet): #this adds logic to say rate is zero if not firing #this automatically turns off rate bar moment key is released fixing a logic issue rmcount_count = self.rmcount.get() rmcount_count = 0 self.rmcount.set(rmcount_count) temperature_count = self.temperature.get() if temperature_count >= 20: self.coolbar()but I had to add this on keypress f: def on_keypress_f(self, evet): counter_value = self.counter.get() counter_value = counter_value-1 or INITIAL_COUNTER_VALUE self.counter.set(counter_value) counter_value = self.counter.get() # this is logic to try and get ammo warnings counter_value = self.counter.get() self.reload() self.critical() self.out() # this sets the time at 100% timer_value = self.timer.get() timer_value = timer_value-66 or INITIAL_TIMER_VALUE self.timer.set(timer_value) # this sets the rmbar to 40% rmcount_count = self.rmcount.get() rmcount_count = 40 self.rmcount.set(rmcount_count) # this sets the temperature temperature_count = self.temperature.get() temperature_count = temperature_count+1 self.temperature.set(temperature_count) if temperature_count == 90: self.coolbar() self.overheat() else: state_stat = self.stat.get() state_stat = "" self.stat.set(state_stat)Now on to updating a label depending upon temp reading or ammo levels. I am thinking it is a logic issue with the way the readings are taken and then updated. import tkinter.ttk as ttk import tkinter as tk import datetime as dt import time #import os #from tkinter import messagebox from threading import Thread # sets ammo count to initial value of 500 INITIAL_COUNTER_VALUE = 500 # sets initial time at 100% INITIAL_TIMER_VALUE = 33000 # sets initial gun terminal ID #sets gun rate RMMAX = 0 # sets initial temparature TEMP_INITIAL = 20 # sets text string for ammo/temp/low ammo status button STATUS = "" COOLED = 20 GUN = "" # initial class declaration for main body of program class TkApp(tk.Tk): # these arguments initialize the class and how to form arguments within def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # set screen options self.geometry("640x400") self.configure(bg='black') self.title("Sentry Terminal") # locally initialize ammo count down self.counter = tk.IntVar() self.counter.set(INITIAL_COUNTER_VALUE) # locally sets the timer count down at 100% self.timer = tk.IntVar() self.timer.set(INITIAL_TIMER_VALUE) # locally sets rmbar to 0% self.rmcount = tk.IntVar() self.rmcount.set(RMMAX) # locally sets tempbar self.temperature = tk.IntVar() self.temperature.set(TEMP_INITIAL) # locally sets text string for ammo status button self.stat = tk.StringVar() self.stat.set(STATUS) # self.cooldown = tk.IntVar() self.stat.set(COOLED) self.gun = tk.StringVar() self.gun.set(GUN) # this arranges the grid row and column groupings. tk.Grid.rowconfigure(self, 0, weight=1, uniform='c') tk.Grid.rowconfigure(self, 1, weight=1, uniform='b') tk.Grid.rowconfigure(self, 2, weight=1, uniform='b') tk.Grid.rowconfigure(self, 3, weight=1, uniform='b') tk.Grid.rowconfigure(self, 4, weight=1, uniform='b') tk.Grid.rowconfigure(self, 5, weight=1, uniform='b') tk.Grid.rowconfigure(self, 6, weight=1, uniform='b') tk.Grid.rowconfigure(self, 7, weight=1, uniform='b') tk.Grid.rowconfigure(self, 8, weight=1, uniform='b') tk.Grid.columnconfigure(self, 0, weight=1, uniform='a') tk.Grid.columnconfigure(self, 1, weight=1, uniform='a') tk.Grid.columnconfigure(self, 2, weight=1, uniform='a') tk.Grid.columnconfigure(self, 3, weight=1, uniform='a') tk.Grid.columnconfigure(self, 4, weight=1, uniform='a') tk.Grid.columnconfigure(self, 5, weight=1, uniform='a') # these are the button and label declarations rounds = tk.Label(self, justify=tk.CENTER, textvariable=self.counter) rounds.grid(row=3, column=2, columnspan=1, sticky="EW") label1 = tk.Label(self, textvariable=self.timer) label1.grid(row=7, column=2, sticky="EW") temp = tk.Button(self,justify=tk.CENTER,text="Temp",bg='black', fg='yellow', highlightbackground='yellow', highlightcolor='black',activebackground='yellow') temp.grid(row=2,column=4,sticky="NSEW") rm = tk.Button(self,justify=tk.CENTER,text="R(M)",bg='black', fg='yellow', highlightbackground='yellow', highlightcolor='black',activebackground='yellow') rm.grid(row=2,column=5,sticky="NSEW") # rounds rate bar rmbar = ttk.Progressbar(self, orient="vertical", variable=self.rmcount) rmbar.grid(row=3,column=5,rowspan=6, sticky="NS") # temperature bar tempbar = ttk.Progressbar(self, orient="vertical", variable=self.temperature) tempbar.grid(row=3,column=4,rowspan=6,sticky="NS") # declarative buttons timestat = tk.Button(self,bg='black',state=tk.DISABLED, fg='yellow',disabledforeground='yellow',highlightbackground='yellow',borderwidth=2,justify=tk.CENTER,text="TIME AT 100% \n (msecs)") timestat.grid(row=7,column=0,columnspan=2,sticky="NSEW") roundsr = tk.Button(self,bg='black',state=tk.DISABLED, fg='yellow',disabledforeground='yellow',highlightbackground='yellow',borderwidth=2,justify=tk.CENTER,text="Rounds \n Remaining") roundsr.grid(row=3,column=0,columnspan=2,sticky="NS") # crit menu bar crit = tk.Button(self,justify=tk.CENTER,textvariable=self.stat, bg='black', fg='yellow', highlightbackground='yellow', highlightcolor='black',activebackground='yellow') crit.grid(row=5,column=0,columnspan=2,sticky="NSEW") # static center header headernew = tk.Button(self, bg='black',state=tk.DISABLED,justify=tk.CENTER, text="UA 571-C \n REMOTE SENTRY WEAPON SYSTEM") headernew.grid(row=0,column=1,columnspan=4,rowspan=2,sticky="NSEW") # displays gun id on top left and right of screen gun_1 = tk.Label(self, borderwidth=7,bg='black',fg='yellow',disabledforeground='yellow',state=tk.DISABLED,textvariable=self.gun) gun_1.grid(row=0,column=0,rowspan=2,sticky="NS") gun_2 = tk.Button(self, borderwidth=7,bg='black',fg='yellow',disabledforeground='yellow',state=tk.DISABLED,textvariable=self.gun) gun_2.grid(row=0,column=5,rowspan=2,sticky="NS") # this quits by clicking a button labeled q quit = tk.Button(self, bg='black', fg='yellow', text='q', command=self.quit) quit.grid(row=8,column=0,sticky="SW") # these are the attachments for input from keyboard into the application # These are the button inputs from the original flash app that were used # I added a q as well to quit and close window in case there was a need to close self.bind("<KeyPress-f>", self.on_keypress_f) self.bind("<KeyRelease-f>", self.on_keyrelease_f) self.bind("<KeyPress-a>", self.on_keypress_a) self.bind("<KeyPress-b>", self.on_keypress_b) self.bind("<KeyPress-c>", self.on_keypress_c) self.bind("<KeyPress-d>", self.on_keypress_d) self.bind("<KeyPress-r>", self.on_keypress_r) self.bind("<KeyPress-q>", self.on_keypress_q) self.bind("<KeyPress-space>", self.on_keypress_space) # self.coolbar(temperature_count) def coolbar(self): temperature_count = self.temperature.get() if temperature_count >= 21: temperature_count = self.temperature.get() temperature_count = temperature_count-1 or TEMP_INITIAL self.temperature.set(temperature_count) print("key not pressed", temperature_count) self.after(300, self.coolbar) def overheat(self): rmcount_count = self.rmcount.get() rmcount_count = 0 self.rmcount.set(rmcount_count) state_stat = self.stat.get() state_stat = "OVERHEAT" self.stat.set(state_stat) time.sleep(0.7) def critical(self): counter_value = self.counter.get() if counter_value <= 50: counter_value = self.counter.get() state_stat = self.stat.get() state_stat = "CRITICAL" self.stat.set(state_stat) counter_value = self.counter.get() print("ammo CRIT", counter_value) def out(self): counter_value = self.counter.get() if counter_value == 1: state_stat = self.stat.get() state_stat = "OUT" self.stat.set(state_stat) counter_value = self.counter.get() print("ammo CRIT", counter_value) def reload(self): counter_value = self.counter.get() if counter_value >= 1: state_stat = self.stat.get() state_stat = "" self.stat.set(state_stat) counter_value = self.counter.get() print("ammo CRIT", counter_value) # this defines the fire ammo count down sequence and resets def on_keypress_f(self, evet): counter_value = self.counter.get() counter_value = counter_value-1 or INITIAL_COUNTER_VALUE self.counter.set(counter_value) counter_value = self.counter.get() # this is logic to try and get ammo warnings counter_value = self.counter.get() self.reload() self.critical() self.out() # this sets the time at 100% timer_value = self.timer.get() timer_value = timer_value-66 or INITIAL_TIMER_VALUE self.timer.set(timer_value) # this sets the rmbar to 40% rmcount_count = self.rmcount.get() rmcount_count = 40 self.rmcount.set(rmcount_count) # this sets the temperature temperature_count = self.temperature.get() temperature_count = temperature_count+1 self.temperature.set(temperature_count) if temperature_count == 90: self.coolbar() self.overheat() else: state_stat = self.stat.get() state_stat = "" self.stat.set(state_stat) def on_keyrelease_f(self, evet): #this adds logic to say rate is zero if not firing #this automatically turns off rate bar moment key is released fixing a logic issue rmcount_count = self.rmcount.get() rmcount_count = 0 self.rmcount.set(rmcount_count) temperature_count = self.temperature.get() if temperature_count >= 20: self.coolbar() # this sets the gun terminal identification # this can also be expanded to do other things if you want to alter the script def on_keypress_a(self, evet): which_gun = self.gun.get() which_gun = "A" self.gun.set(which_gun) def on_keypress_b(self, evet): which_gun = self.gun.get() which_gun = "B" self.gun.set(which_gun) def on_keypress_c(self, evet): which_gun = self.gun.get() which_gun = "C" self.gun.set(which_gun) def on_keypress_d(self, evet): which_gun = self.gun.get() which_gun = "D" self.gun.set(which_gun) def on_keypress_space(self, evet): print("space pressed") # this reloads the window, you have to click it to make it the active window again def on_keypress_r(self, evet): self.destroy() self.__init__() # this quits and closes the window by hitting a single key def on_keypress_q(self, evet): self.quit() # this executes the main loop and tkinter self delcared class. It declares the function then runs it in the main loop. tk_app = TkApp() tk_app.mainloop()I am slowly figuring this out. |