How can I maintain the execution of my program whilst the following loop is executing?
def callback():
var=OpenHour.get()
var1=CloseHour.get()
actual = 0
if not validateDate(var, var1):
tkMessageBox.showinfo("Error","Datos o formato incorrecto, deberia ser hh:mm")
else:
while var != actual:
actual = datetime.datetime.now().time().strftime('%H:%M')
print "ya acabe voy al second while"
while var1 != actual:
actual = datetime.datetime.now().time().strftime('%H:%M')
tkMessageBox.showinfo("Exito","Se ha terminado el ciclo")
#tkMessageBox.showinfo("Exito","La programacion se ha \nrealizado de la manera correcta")
b = Button(VentanaPersiana, text="Programar", width=10, command=callback)
b.pack()
You can use root.after(miliseconds, function_name, argument) to execute function with delay and root.mainloop() (and program) will work normally.
You can use datetime to convert text to datetime object, substract two dates and get difference in milliseconds.
try:
import tkinter as tk
import tkinter.messagebox as tkMessageBox
print("Python 3")
except:
import Tkinter as tk
import tkMessageBox
print("Python 2")
from datetime import datetime as dt
# --- functions ---
def callback():
var_open = open_hour.get()
var_close = close_hour.get()
if not validateDate(var_open, var_close):
tkMessageBox.showinfo("Error", "Incorrect times")
else:
# current date and time
current = dt.now()
print('current:', current)
# convert strings to `time` object
time_open = dt.strptime(var_open, '%H:%M').time()
time_close = dt.strptime(var_close, '%H:%M').time()
print('time_open:', time_open)
print('time_close:', time_close)
# combine `current date` with `time`
today_open = dt.combine(current, time_open)
today_close = dt.combine(current, time_close)
print('today_open:', today_open)
print('today_close:', today_close)
# substract dates and get milliseconds
milliseconds_open = (today_open - current).seconds * 1000
milliseconds_close = (today_close - current).seconds * 1000
print('milliseconds_open:', milliseconds_open)
print('milliseconds_close:', milliseconds_close)
# run functions with delay
root.after(milliseconds_open, show_open_message, var_open)
root.after(milliseconds_close, show_close_message, var_close)
def validateDate(time1, time2):
# TODO: check dates
return True
def show_open_message(arg):
tkMessageBox.showinfo("Info", "Open time: " + arg)
def show_close_message(arg):
tkMessageBox.showinfo("Info", "Close time: " + arg)
# --- main ---
root = tk.Tk()
open_hour = tk.StringVar()
close_hour = tk.StringVar()
e1 = tk.Entry(root, textvariable=open_hour)
e1.pack()
e2 = tk.Entry(root, textvariable=close_hour)
e2.pack()
b = tk.Button(root, text="Start", command=callback)
b.pack()
root.mainloop()
Related
variable "code" doesn't change (str) when i check and if i put checkbox() above codeget() there will be no checkbox
how to fix there is code
from tkinter import *
from tkinter import messagebox
from tkinter.ttk import *
#Window
window = Tk()
window.title("Register") #set window title
window.geometry('900x500')
code = 'None'
def codeget():
if (var1.get() == 1) and (var2.get() == 0):
code = 'Python'
elif (var1.get() == 0) and (var2.get() == 1):
code = 'C++'
elif (var1.get() == 0) and (var2.get() == 0):
code = 'None'
else:
code = 'Both'
var1 = IntVar()
var2 = IntVar()
c1 = Checkbutton(window, text='Python',variable=var1, onvalue=1, offvalue=0, command=codeget)
c1.place(x=650,y=120)
c2 = Checkbutton(window, text='C++',variable=var2, onvalue=1, offvalue=0, command=codeget)
c2.place(x=720,y=120)
def luu():
s=open("saveaccount", 'a+')
accountin4 = '\n' + 'Code: ' + code
s.write(accountin4)
message = Button(window,text = "Register", command = luu)
message.place(x = 500, y = 370)
mainloop()
if and else may not be related to my question so you can ignore it, even if I use = to assign " " to the code, the result will still be "None"
codeget() creates local variable code. You have to add global code inside this function to inform function that it has to assign value to global variable code instead of creating local variable code.
Minimal working code with small other changes.
import tkinter as tk # PEP8: `import *` is not preferred
from tkinter import messagebox
import tkinter.ttk as ttk
# --- functions --- # PEP8: all functions before main code
def get_code(): # PEP8: `lower_case_names` for functions and variables
global code # inform function to assign to global variable `code` instead of creating local variable `code`
if var1.get() == 0 and var2.get() == 0:
code = 'None'
elif var1.get() == 1 and var2.get() == 0:
code = 'Python'
elif var1.get() == 0 and var2.get() == 1:
code = 'C++'
else:
code = 'Both'
def register(): # PEP8: readable name
s = open("saveaccount", 'a+')
text = '\n' + 'Code: ' + code
s.write(text)
s.close() # better close file because system may keep data in buffer in RAM and write data when you close file
print(text)
# --- main ---
code = 'None' # it is global variable
window = tk.Tk()
var1 = tk.IntVar()
var2 = tk.IntVar()
c1 = tk.Checkbutton(window, text='Python', variable=var1, onvalue=1, offvalue=0, command=get_code)
c1.pack()
c2 = tk.Checkbutton(window, text='C++', variable=var2, onvalue=1, offvalue=0, command=get_code)
c2.pack()
message = tk.Button(window, text="Register", command=register)
message.pack()
window.mainloop()
PEP 8 -- Style Guide for Python Code
EDIT:
If you want to use more checkbuttons then you could use for-loop to create them, and StringVar to use string onvalue="Python" instead of integers 0/1
import tkinter as tk # PEP8: `import *` is not preferred
from tkinter import messagebox
import tkinter.ttk as ttk
# --- functions --- # PEP8: all functions before main code
def get_code():
global code # inform function to assign to global variable `code` instead of creating local variable `code`
selected = []
for v in string_vars:
if v.get():
selected.append(v.get())
if not selected:
code = 'None'
else:
code = ','.join(selected)
def register():
s = open("saveaccount", 'a+')
text = '\n' + 'Code: ' + code
print(text)
s.write(text)
s.close()
# --- main ---
code = 'None' # it is global variable
window = tk.Tk()
string_vars = []
for item in ['Python', 'C++', 'Java', 'PHP', 'Rust', 'Go']:
v = tk.StringVar(window)
c = tk.Checkbutton(window, text=item, variable=v, onvalue=item, offvalue='', command=get_code)
c.pack()
string_vars.append(v)
message = tk.Button(window, text="Register", command=register)
message.pack()
window.mainloop()
This question already has an answer here:
Clock with date and time in tkinter hangs
(1 answer)
Closed 8 months ago.
Digital clock is running based on system time. But after 10 seconds it stops.
Before this you can even see that the last 'tick' is 2 seconds instead of 1 second. That means it slows down somehow.
Why does it happen?
from tkinter import *
from tkinter import ttk
from time import strftime
import datetime
root = Tk()
root.title('Clock')
tabs = ttk.Notebook(root)
tabs.pack()
clock_tab = ttk.Frame(tabs)
timer_tab = ttk.Frame(tabs)
stopwatch_tab = ttk.Frame(tabs)
alarm_tab = ttk.Frame(tabs)
international_time_tab = ttk.Frame(tabs)
tabs.add(clock_tab, text='Clock')
tabs.add(timer_tab, text='Timer')
tabs.add(stopwatch_tab, text='Stopwatch')
tabs.add(alarm_tab, text='Alarm')
tabs.add(international_time_tab, text='International time')
def time():
time_str = datetime.datetime.now().strftime("%H:%M:%S")
date_str = datetime.datetime.now().strftime("%d.%m.%Y")
time_label.config(text = time_str)
time_label.after(1000, time)
date_label.config(text = date_str)
date_label.after(1000, time)
time_label = Label(root,font = ('calibri', 20))
time_label.pack()
date_label = Label(root,font = ('calibri', 15))
date_label.pack()
exit_btn = ttk.Button(
root,
text = 'Exit',
command = lambda: root.quit()
)
exit_btn.pack(fill = 'x')
def exit_func(event):
root.quit()
root.bind('<Return>', exit_func)
time()
mainloop()
Add this root.mainloop. Btw, when I typed time period, I didn't get any intellisense. There is no intellisense. But I can see intellisense in my example.
import sys
from tkinter import *
import time
def timing():
current_time = time.strftime("%H : %M : %S")
clock.config(text=current_time)
clock.after(200,timing)
root=Tk()
root.geometry("600x300")
clock=Label(root,font=("times",60,"bold"),bg="blue")
clock.grid(row=2,column=2,pady=25,padx=100)
timing()
root.mainloop()
So Im trying to create a count down timer in the form of mm:ss and start counting down in an interval of 1 second when the button is being pressed. Im trying to make the timer show on the button too when counting down. This is what I have so far and I'm not sure what to do.
import tkinter as tk
root = tk.Tk()
monsterTimer = '00:02'
def converter(sec):
m, s = map(int, sec.split(":"))
sec = m * 60 + s
sec -= 1
m, s = divmod(sec, 60)
sec = (f'{m:02d}:{s:02d}')
if sec != '00:00':
sec = 'end'
root.after(1000, converter)
return sec
def update_btn_text():
btn_text.set(converter(monsterTimer))
btn_text = tk.StringVar()
btn_text.set(monsterTimer)
btn = tk.Button(root, textvariable=btn_text, command=lambda: update_btn_text())
btn.place(x=10, y=10)
root.mainloop()
Your solution was close, and using after instead of threads is the right way to go.
The first problem is that when you use root.after, you are calling converter but you aren't passing in an argument. You need to change the line to look like the following, which will call converter(sec) every second.
root.after(1000, converter, sec)
Another problem you have is that you are setting set to 'end' if it is not 00:00. You need to set it only if it is 00:00:
if sec == '00:00':
sec = 'end'
Third, you need to update the button text inside of converter, sometime before calling after:
...
btn_text.set(sec)
root.after(1000, converter, sec)
Finally, you don't need update_btn at all. It can be removed, and you can call converter from your button command.
btn = tk.Button(root, textvariable=btn_text, command=lambda: converter(monsterTimer))
Putting it all together, it looks like this:
import tkinter as tk
root = tk.Tk()
monsterTimer = '00:10'
def converter(sec):
m, s = map(int, sec.split(":"))
sec = m * 60 + s
sec -= 1
m, s = divmod(sec, 60)
sec = (f'{m:02d}:{s:02d}')
if sec == '00:00':
sec = 'end'
btn_text.set(sec)
if sec != "end":
root.after(1000, converter, sec)
btn_text = tk.StringVar()
btn_text.set(monsterTimer)
btn = tk.Button(root, textvariable=btn_text, command=lambda: converter(monsterTimer))
btn.place(x=10, y=10)
root.mainloop()
Try this code:
import tkinter as tk
import time
import threading
root = tk.Tk()
monsterTimer = '00:00'
run_tm = 5
def update_btn_text(sec):
while sec:
m, s = divmod(sec, 60)
m, s = str(m).zfill(2), str(s).zfill(2)
tm = f'{m}:{s}'
btn_text.set(tm)
time.sleep(1)
sec -= 1
btn_text.set("00:00")
def startThread(t):
th1 = threading.Thread(target=update_btn_text, args=(t, ))
th1.start()
btn_text = tk.StringVar()
btn_text.set(monsterTimer)
btn = tk.Button(root, textvariable=btn_text, command=lambda: startThread(run_tm))
btn.place(x=50, y=50)
root.mainloop()
In python 2.7, I want to print the price of a place depending on the given user input of people. The price should vary each time the user input a different amount of people.
from Tkinter import *
top = Tk()
top.geometry("500x500")
a = Label(text="Adult:")
a.place(x=50,y=100)
adult_input = Entry(top)
adult_input.place(x=100,y=100)
adult_num = Label (text="x RM 5.00 per pax :")
adult_num.place(x=250,y=100)
top.mainloop()
How should I go about printing the the price depending on the user input?
Here is the simplest solution for your situation. Add the following lines just before top.mainloop():
b = Button(top,
text="Confirm",
command=lambda: adult_num.config(text=adult_input.get()))
b.place('''anywhere''')
This will update your adult_num label when clicking the button.
If this is not enough, and you need to compute a value before displaying it, then you'll need a function.
Suppose you have an f function:
def f(adults_number):
adults_number = int(adults_number)
return '''the result of some formula'''
Then you'll have to call it in the button's command:
b = Button(top,
text="Confirm",
command=lambda: adult_num.config(text=str(f(adult_input.get()))))
Also, your adult_num label should be attached to top, so the declaration should be:
adult_num = Label(top, text="...")
You can use Button to execute function which will calculate value
import Tkinter as tk
# --- functions ---
def recalc():
value = e.get()
if value != '':
l['text'] = float(value) * 5.00
# --- main ---
root = tk.Tk()
e = tk.Entry(root)
e.pack()
e.bind('<KeyRelease>', recalc)
l = tk.Label(root)
l.pack()
b = tk.Button(root, text="Recalc", command=recalc)
b.pack()
root.mainloop()
or you can bind event to Entry and it will be calculated after every key.
import Tkinter as tk
# --- functions ---
def recalc(event): # bind executes function with argument `event`
#value = e.get()
value = event.widget.get()
if value != '':
l['text'] = float(value) * 5.00
# --- main ---
root = tk.Tk()
e = tk.Entry(root)
e.pack()
e.bind('<KeyRelease>', recalc)
l = tk.Label(root)
l.pack()
root.mainloop()
I am very new on Python and I have a problem.
I try to read my temperature sensor and set the Value in to my Tkinter GUI.
I don't know how to update my label LT with the new value if I update it with my Button B1.
I have tried everything from StringVar to get() and this stuff.
I hope you can help me to find my failure.
Here is my code:
from tkinter import *
import os
Main = Tk()
Main.title("Hauptmenü")
Main.geometry("500x400")
class Fenster():
def Credit():
messagebox.showinfo(title="Credits",message="created by T.N v0.1")
return
def Beenden():
pExit = messagebox.askyesno(title="Beenden",message="Möchten Sie\n wirklich beenden?")
if pExit > 0:
Main.destroy()
return
def auslesen(event):
file = open("/sys/bus/w1/devices/28-041635ad4cff/w1_slave")
inhalt = file.read()
trennwoerter = inhalt.split(" ")
Wert = (trennwoerter[20])
Temp = (Wert[2:4])
file.close()
labelauslesen = Label(Main,text="Aktuelle Temperatur :")
labelauslesen.pack()
LT = Label(Main,text=Inhalt)
LT.pack()
B1 = Button(Main,text="Temperatur auslesen")
B1.pack()
B1.bind("<Button-1>",auslesen)
menubar=Menu(Main)
filemenu = Menu(menubar)
filemenu.add_command(label="Sensoren auslesen")
filemenu.add_command(label="Diagram anzeigen")
filemenu.add_command(label="Credits",command = Credit)
filemenu.add_command(label="Beenden",command = Beenden)
menubar.add_cascade(label="Datei",menu=filemenu)
Main.config(menu=menubar)
mainloop()
A minimal example that you can adapt to your code.
import tkinter as tk
root=tk.Tk()
temp = 10.0
def update_temp():
global temp
temp += 1.3
tlabel['text'] = '%s degrees C' % round(temp, 1)
tlabel = tk.Label(root, text='unknown')
tbutton = tk.Button(root, text='new temp', command=update_temp)
tlabel.pack()
tbutton.pack()
root.mainloop()