TkInter Command makes Python crash when using lambda - python

I have a problem using lambda: ... in my program. As I don't want my TkInter GUI to execute the functions automatically, I am using lambda. Problem is though that for Button3 it makes my program crash and I have no idea why. Without lambda it works absolutely fine. Here is my code:
import ogr, osr, sys, os
import psycopg2
import ppygis
from datetime import datetime, date
import time
import re
from Tkinter import *
import tkFileDialog
from tkFileDialog import askopenfilename # Open dialog box
from tkMessageBox import showerror
class trip_calculator:
def __init__(self):
global root
root = Tk()
def open_file_dialog():
returned_values = {}
returned_values['filename'] = askopenfilename()
Label(root, text= returned_values.get('filename')[52:] + ' selected').grid(row=2)
filepath = returned_values.get('filename')
#OPEN GPX DRIVER
driver = ogr.GetDriverByName('GPX')
datasource = driver.Open(filepath)
if datasource is None:
print 'not open'
else:
print 'open'
#GEOMETRY
datasource_layer = datasource.GetLayer(2)
#GRAB TIMESTAMPS, ELEVATION, CADENCE ETC.
datasource_layer2 = datasource.GetLayer(4)
#GRAB GEOMETRY INFORMATION AND TRANSFORM TO UTM
datasource_feature = datasource_layer.GetNextFeature()
geoSR = osr.SpatialReference()
geoSR.ImportFromEPSG(4326)
utmSR = osr.SpatialReference()
utmSR.ImportFromEPSG(32633)
coordTrans = osr.CoordinateTransformation(geoSR, utmSR)
geom = datasource_feature.GetGeometryRef()
geom1 = geom.Simplify(0)
geom.Transform(coordTrans)
geom1.Transform(coordTrans)
Label(root, text= 'geometries transformed successfully').grid(row=2, column=5)
#
# This is where the crash of Python occurs,
# `lambda: calculation(...)` won't start.
# It crashes at `features = iter(datasource_layer2)`
#
self.button3 = Button(root, text='calculate attributes', command=lambda:calculation(self,geom1,datasource_layer2)).grid(row=10, column=10, pady=10, padx=10)
def quit_me():
root.quit()
def calculation(self, geom1, datasource_layer2):
#NET AND GROSS TIME CALCULATION
timestamps_net = []
timestamps_net_helper = []
timestamps_elapsed = []
elevation_helper = []
print datasource_layer2
features = iter(datasource_layer2)
next(features)
for feature in features:
if len(timestamps_net_helper) == 2:
timestamps_net_helper = timestamps_net_helper[-1:]
timestamp = feature.GetField(4)
elevation = feature.GetField(3)
elevation_helper.append(elevation)
timestamp_stripped = timestamp[:-3]
day = timestamp[:-11]
#FOR GROSS CALCULATION
timestamps_elapsed.append(timestamp_stripped)
#FOR NET CALCULATION
timestamps_net_helper.append(timestamp_stripped)
if len(timestamps_net_helper) == 2:
#CALCULATE SECONDS BETWEEN
time_a = datetime.strptime(timestamps_net_helper[0], "%Y/%m/%d %H:%M:%S")
time_b = datetime.strptime(timestamps_net_helper[1], "%Y/%m/%d %H:%M:%S")
time_difference = time.mktime(time_b.timetuple()) - time.mktime(time_a.timetuple())
#IF SECONDS LESS THAN 20 BETWEEN GPS TIMESTAMP THEN ADD UP NET TIME
if time_difference < 20:
timestamps_net.append(time_difference)
seconds = sum(timestamps_net)
hours = seconds/60/60
time_length_net = time.strftime('%H:%M:%S', time.gmtime(seconds))
#CLIMB.....
positive_climb = []
negative_climb = []
for a, b in zip(elevation_helper, elevation_helper[1:]):
if a > 0.0 and b > 0.0:
if b > a:
positive_climb.append(b-a)
elif b == a:
pass
else:
negative_climb.append(a-b)
positive_climb = sum(positive_climb)
negative_climb = sum(negative_climb)
#GROSS (ELAPSED TIME)
start = datetime.strptime(timestamps_elapsed[0], "%Y/%m/%d %H:%M:%S")
end = datetime.strptime(timestamps_elapsed[-1], "%Y/%m/%d %H:%M:%S")
time_length = end - start
#LENGTH
length_km = float(geom1.Length()/1000)
#AVERAGE SPEED
avg_speed = (geom1.Length()/1000)/hours
#CREATE LINESTRING FOR PPYGIS AND OGR LINESTRING
myLine = ogr.Geometry(ogr.wkbLineString)
polyline = []
for z in range(geom1.GetPointCount()):
x = geom1.GetX(z)
y = geom1.GetY(z)
myLine.AddPoint(x, y)
point = ppygis.Point(x, y)
polyline.append(point)
myLine_ppy = ppygis.LineString(polyline)
Label(root, text= time_length).grid(row=10, column=5)
Label(root, text= length_km).grid(row=11, column=5)
Label(root, text= avg_speed).grid(row=12, column=5)
self.button1 = Button(root, text='browse', command= open_file_dialog).grid(row=0,pady=10, padx=25)
self.button2 = Button(root, text='close', command= quit_me).grid(row=3, pady=10, padx=25)
root.mainloop()
trip_calculator()
The error occuring is libc++abi.dylib: pure virtual method called but only using lambda in the command of button3. Any ideas how to fix this?

The problem is likely due to the fact that some of the arguments you have in thelambdaexpression -- namelygeom1anddatasource_layer2-- are variables local to the nestedopen_file_dialog() function and don't exist later when the button is pressed and it has returned.
A simple fix would be to make them attributes of the trip_calculator instance, by adding a self.datasource_layer2 = datasource_layer2andself.geom1 = geom1 statements somewhere before the function returns (or just assigning them toselfand referencing them that way everywhere else).

Related

GUI Tkinter Alarm Clock not responding

I created a tkinter alarm clock which is not responding after setting the alarm. The alarm sound is playing but after that I have to exit the application and re-run the code to set alarm once again .I have shared the code and screenshot of the app.
from tkinter import
import datetime
import time
from playsound import playsound
def Alarm(set_alarm_timer):
while True:
time.sleep(1)
actual_time = datetime.datetime.now()
cur_time = actual_time.strftime("%H:%M:%S")
cur_date = actual_time.strftime("%d/%m/%Y")
msg="Current Time: "+str(cur_time)
print(msg)
if cur_time == set_alarm_timer:
playsound("Audio.mp3")
break
def get_alarm_time():
alarm_set_time = f"{hour.get()}:{min.get()}:{sec.get()}"
Alarm(alarm_set_time)
window = Tk()
window.title("Alarm Clock")
window.geometry("400x160")
window.config(bg="#922B21")
window.resizable(width=False,height=False)
time_format=Label(window, text= "Remember to set time in 24 hour format!", fg="white",bg="#922B21",font=("Arial",15)).place(x=20,y=120)
addTime = Label(window,text = "Hour Min Sec",font=60,fg="white",bg="black").place(x = 210)
setYourAlarm = Label(window,text = "Set Time for Alarm: ",fg="white",bg="#922B21",relief = "solid",font=("Helevetica",15,"bold")).place(x=10, y=40)
hour = StringVar()
min = StringVar()
sec = StringVar()
hourTime= Entry(window,textvariable = hour,bg = "#48C9B0",width = 4,font=(20)).place(x=210,y=40)
minTime= Entry(window,textvariable = min,bg = "#48C9B0",width = 4,font=(20)).place(x=270,y=40)
secTime = Entry(window,textvariable = sec,bg = "#48C9B0",width = 4,font=(20)).place(x=330,y=40)
submit = Button(window,text = "Set Your Alarm",fg="Black",bg="#D4AC0D",width = 15,command = get_alarm_time,font=(20)).place(x =100,y=80)
window.mainloop()
.mainloop is some sort of while loop. So time.sleep() and while ... will mess with it. Use .after().
Edit: .place(),.pack() and .grid() geometry managers return None. And in python, the value of the last function is assigned.
here, it would be None, and might raise errors in future
def Alarm(set_alarm_timer):
actual_time = datetime.datetime.now()
cur_time = actual_time.strftime("%H:%M:%S")
if cur_time != set_alarm_timer:
msg="Current Time: "+str(cur_time)
print(msg)
window.after(1000,Alarm, set_alarm_timer)
else:
playsound("Audio.mp3")
...
submit = Button(window,text = "Set Your Alarm",fg="Black",bg="#D4AC0D",width = 15,command = lambda: Alarm(f"{hour.get()}:{min.get()}:{sec.get()}"),font=(20))
submit.place(x =100,y=80)

Building a application with TKInter, need some assistance

Basically, I've made a GUI application for personal use related to an online gaming community, and I'm kind've stuck currently. It is working as intended, apart from one thing. I need it to be able to track multiple "Activations" and start separate timers but keep track of the previous timers as well, so it can total it up at the end. For example, if I Activate "Service 1" it currently starts a timer, but when I deactivate it and activate it once again, it will disregard the initial timer and just start a new one. How can I make it so it adds the two timers together to print out a "total time spent".
Here is the code relevant to my query
def time_convert3(sec):
global PALenght
mins = sec // 60
sec = round(sec % 60)
hours = mins // 60
mins = mins % 60
SIDLenght = ("{0}H:{1}M:{2}S".format(int(hours),int(mins),sec))
print(PALenght)
def selectPA():
global PAStart
global PALenght
global PACount
if var.get() == 1:
PAStart = time.time()
print(PAStart)
PACount = PACount + 1
root.after(10, lambda: Label(root, text= 'PA Activations: ' + str(PACount), bg='#1aa3ff', fg='Black' ).place(relx=0.1, rely=0.85, relwidth=0.3, relheight=0.05))
root.after(1000, lambda: portA.place(relx=0.4, rely=0.55, relwidth=0.2, relheight=0.05))
root.after(3000, lambda: portA.place_forget())
elif var.get() == 0:
PAEnd = time.time()
PATotal = PAEnd - PAStart
time_convert3(PATotal)
root.after(1000, lambda: portB.place(relx=0.4, rely=0.55, relwidth=0.2, relheight=0.05))
root.after(3000, lambda: portB.place_forget())
var = IntVar()
PACheck = Checkbutton(root, text="Activate/Deactivate PA ", variable = var,bg='#1aa3ff', fg='Black', command = selectPA).place(relx=0.13, rely=0.55, relwidth=0.2, relheight=0.05)
At start you should set
PATotal = 0
and later add new time to total
PATotal += (PAEnd - PAStart)
Minimal working example
import tkinter as tk
import time
# --- functions ---
def func():
global total
global time_start
if cb_var.get():
time_start = time.time()
else:
total += (time.time() - time_start)
label['text'] = 'Total: {:.2f}s'.format(total)
# --- main ---
total = 0
time_start = 0
root = tk.Tk()
cb_var = tk.BooleanVar()
label = tk.Label(root, text='Total: 0.00s')
label.pack()
cb = tk.Checkbutton(root, text='Running ...', variable=cb_var, command=func)
cb.pack()
root.mainloop()
Or at start you create list
all_times = []
and later append PAEnd - PAStart to this list
all_times.append(PAEnd - PAStart)
and you can sum all values on list.
PATotal = sum(all_times)
Minimal working example
import tkinter as tk
import time
# --- functions ---
def func():
global total
global time_start
if cb_var.get():
time_start = time.time()
else:
all_times.append(time.time() - time_start)
label_times['text'] += '\n{:.2f}'.format(all_times[-1])
total = sum(all_times)
label_total['text'] = 'Total: {:.2f}s'.format(total)
# --- main ---
all_times = []
total = 0
time_start = 0
root = tk.Tk()
cb_var = tk.BooleanVar()
label_times = tk.Label(root, text='Times')
label_times.pack()
label_total = tk.Label(root, text='Total: 0.00s')
label_total.pack()
cb = tk.Checkbutton(root, text='Running ...', variable=cb_var, command=func)
cb.pack()
root.mainloop()

Creating Graphs in Python GUI

I have created a GUI in which I read a CSV file and calculate the liquid output from the data. Now I want to do two things:
1) I want to generate the output based on time just like date
2) I want to generate graphs on a separate window in my GUI for a user specific time or date
This is my code:
import csv
from tkinter import *
from tkinter.filedialog import askopenfilename
from tkinter.messagebox import showwarning, showinfo
import datetime
#csv_file = csv.reader(open("C:\Users\Lala Rushan\Downloads\ARIF Drop Monitoring Final\ARIF Drop Monitoring Final\DataLog.csv"))
from Tools.scripts.treesync import raw_input
class App(Frame):
def __init__(self, master):
Frame.__init__(self, master)
button1 = Button(self, text="Browse for a file", command=self.askfilename)
button2 = Button(self, text="Count the file", command=self.takedate)
button3 = Button(self, text="Exit", command=master.destroy)
button1.grid()
button2.grid()
button3.grid()
self.userInputFromRaw = Entry(self)
self.userInputFromRaw.grid()
self.userInputToRaw = Entry(self)
self.userInputToRaw.grid()
self.grid()
def askfilename(self):
in_file = askopenfilename()
if not in_file.endswith(('.CSV')):
showwarning('Are you trying to annoy me?', 'How about giving me a CSV file, genius?')
else:
self.in_file=in_file
def CsvImport(self,csv_file):
dist = 0
for row in csv_file:
_dist = row[0]
try:
_dist = float(_dist)
except ValueError:
_dist = 0
dist += _dist
print ("Urine Volume is: %.2f" % (_dist*0.05))
def takedate(self):
from_raw = self.userInputFromRaw.get()
from_date = datetime.date(*map(int, from_raw.split('/')))
print ('From date: = ' + str(from_date))
to_raw = self.userInputToRaw.get()
to_date = datetime.date(*map(int, to_raw.split('/')))
in_file = ("H:\DataLog.csv")
in_file= csv.reader(open(in_file,"r"))
for line in in_file:
_dist = line[0]
try:
file_date = datetime.date(*map(int, line[1].split(' ')[1].split('/')))
if from_date <= file_date <= to_date:
self.CsvImport(in_file)
except IndexError:
pass
root = Tk()
root.title("Urine Measurement")
root.geometry("500x500")
app = App(root)
root.mainloop()
How can I achieve the above 2 tasks?
I must agree with Jacques de Hooge, you should be using matplotlib for that.
At the beggining of your file, import it:
import matplotlib.pyplot as plt
As you only want to open a new window with the plot, a matplotlib window should suffice. You can use a scatter plot:
plt.scatter(X, Y)
Where X is an iteratable with the x coordinates and Y an iteratable with the y coordinates. Since you want to do something with a constant change in time, you can, having a values list with the values to plot, do the following:
plt.scatter(range(len(values)), values)
plt.show()
You might also want to run this inside a thread, so that the rest of the program doesn't "freeze" while the matplotlib window is open. There are plenty of places where this is explained.

threading tkinter add label in frame during function execution

I write a pipeline for a lab, so I know it is impossible to insert a "console" in a GUI, so I made it with a Frame and I put label on it.
But the problem is, I am a beginner in threading, and I don't know how to use it to put my label into my frame after a function execution in a loop.
So this is my code (python 3.x) :
########
# IMPORTS #
########
from tkinter import *
from tkinter import ttk
from tkinter.filedialog import *
from tkinter.messagebox import *
import os
import glob
from datetime import date, time, datetime
#########
# FUNCTION #
#########
def OneFile(path1,DB,path2,seq,seq2,typ,path3):
"""
This function is very long, take all the sequences of the input file and BLAST it to the Library DATABASE
path : path to the library databse
DB : library database name
path2 : path of the file with the query sequences
seq : name of the file with the query sequences append with a job ID
seq2 : name of the file with the query sequence
Typ : Nucleotide or Proteine
"""
from datetime import date, time, datetime
import subprocess
import platform
import time
OS = platform.system()
if OS == 'Linux' or OS == 'Darwin':
pathLibrary = path1+'/'
pathSequence = path2+'/'
pathFolder = path3+'/'
if OS == 'Windows':
pathLibrary = path1+'\\'
pathSequence = path2+'\\'
if typ not in [(1,1),(2,2),(1,2),(2,1)]:
showerror('Error : Missing Type !', "You do not choose your type\n(nucleotides or proteins)")
else:
library = DB
if os.path.isfile(pathLibrary+library) != True:
showerror('Error : Missing File !', "You must choose a Library Database file")
else:
if os.path.isfile(pathSequence+seq2) != True:
showerror('Error : Missing File !', "You must choose your sequence file")
else:
if typ == (1,1):
typ = "blastn"
if typ == (2,2):
typ = "blastp"
if typ == (1,2):
typ = "blastx"
if typ == (2,1):
typ = "tblastn"
if OS == 'Linux' or OS == 'Darwin':
t0 = time.time()
query = str(seq2)
blast = str(seq)+'_Blast.txt'
seqs = str(seq)+'_seqs.txt'
subprocess.call(typ+" -query "+pathSequence+query+" -db "+pathLibrary+library+" -evalue 1e-10 -out "+pathFolder+blast, shell=True)
subprocess.call("grep '\(Sbjct\|>\)' "+pathFolder+blast+" > "+pathFolder+seqs, shell=True)
t1 = time.time()
print('Job finish in '+str(round(t1-t0,2))+' seconds')
if OS == 'Windows':
t0 = time.time()
query = str(seq2)
blast = str(seq)+'_Blast.txt'
seqs = str(seq)+'_seqs.txt'
subprocess.call(typ+' -query '+pathSequence+query+' -db '+pathLibrary+library+' -evalue 1e-10 -out '+pathSequence+blast, shell=True)
print('Fichier n° '+str(1)+' '+str(seq2))
subprocess.Popen('findstr "Sbjct >" '+pathSequence+blast+' > '+pathSequence+seqs, shell=True)
t1 = time.time()
print('Job finish in '+str(round(t1-t0,2))+' seconds')
#######
# CLASS #
#######
class GraphicalUserInterface():
#principal application
def __init__(self):
#constructor
self.fen = Tk()
self.fen.title("Starch Enzyme Pipeline")
#first label
self.label1 = Label(self.fen, text="Folder with your set(s) : ")
self.label1.grid(row=0, columnspan=2, sticky="W")
#first button
self.browse1 = Button(self.fen)
self.browse1.config(text="Browse",command=self.folderPath)
self.browse1.grid(row=1,column=0, sticky="W")
#label to show the path
self.varLabel1 = StringVar()
self.pathLabel1 = Label(self.fen, textvariable=self.varLabel1, relief=SUNKEN)
self.pathLabel1.grid(row=1,column=1, sticky="EW")
#second title
self.label2 = Label(self.fen, text="Folder with your library database(s) ")
self.label2.grid(row=2,column = 0, columnspan=2 , sticky="W")
#second button
self.browse2 = Button(self.fen)
self.browse2.config(text="Browse",command=self.folderPath2)
self.browse2.grid(row=3,column=0, sticky="W")
#label to show the path for database
self.varLabel2 = StringVar()
self.pathLabel2 = Label(self.fen, textvariable=self.varLabel2, relief=SUNKEN)
self.pathLabel2.grid(row=3,column=1, sticky = "EW")
#Frame wrappe listBox and other
self.frameListBoxAll = Frame(self.fen)
self.frameListBoxAll.grid(row=6,columnspan=2)
#list box label
self.labListBox1 = Label(self.frameListBoxAll, text="Your sets :",padx=10)
self.labListBox1.grid(row=0,column=0)
self.labListBox2 = Label(self.frameListBoxAll, text="Your library database :",padx=10)
self.labListBox2.grid(row=0,column=1)
#frame with listbox1
self.frame1 = Frame(self.frameListBoxAll, bd=2, relief=SUNKEN)
self.frame1.grid(row=1,column=0)
#frame with listbox1
self.frame2 = Frame(self.frameListBoxAll, bd=2, relief=SUNKEN)
self.frame2.grid(row=1,column=1)
#scrollbar listbox1
self.scrollbar1 = Scrollbar(self.frame1)
self.scrollbar1.grid(row=0,column=1, sticky="NS")
self.scrollbar2 = Scrollbar(self.frame2)
self.scrollbar2.grid(row=0,column=3, sticky="NS")
self.scrollbar3 = Scrollbar(self.frame1, orient=HORIZONTAL)
self.scrollbar3.grid(row=1,column=0, sticky="WE")
self.scrollbar4 = Scrollbar(self.frame2, orient=HORIZONTAL)
self.scrollbar4.grid(row=1,column=2, sticky="WE")
#liste box
self.listeBox1 = Listbox(self.frame1, selectmode=EXTENDED, exportselection=0, yscrollcommand=self.scrollbar1.set, xscrollcommand=self.scrollbar3.set)
self.listeBox1.grid(row=0,column = 0)
self.scrollbar1.config(command=self.listeBox1.yview)
self.scrollbar3.config(command=self.listeBox1.xview)
#liste box2
self.listeBox2 = Listbox(self.frame2, selectmode=EXTENDED, exportselection=0, yscrollcommand=self.scrollbar2.set, xscrollcommand=self.scrollbar4.set)
self.listeBox2.grid(row=0,column = 2)
self.scrollbar2.config(command=self.listeBox2.yview)
self.scrollbar4.config(command=self.listeBox2.xview)
#radioboutton list box 1
self.var = IntVar()
for item in [1,2]:
if item == 1:
self.rb = Radiobutton(self.frameListBoxAll, text='Nucleotides',value=item,variable=self.var)
self.rb.grid(row=2, column=0)
if item == 2:
self.rb = Radiobutton(self.frameListBoxAll, text='Proteins',value=item,variable=self.var)
self.rb.grid(row=3, column=0)
#radioboutton list box 2
self.var2 = IntVar()
for item in [1,2]:
if item == 1:
self.rb2 = Radiobutton(self.frameListBoxAll, text='Nucleotides',value=item,variable=self.var2)
self.rb2.grid(row=2, column=1)
if item == 2:
self.rb2 = Radiobutton(self.frameListBoxAll, text='Proteins',value=item,variable=self.var2)
self.rb2.grid(row=3, column=1)
#variables
self.path1 = str()
self.path2 = str()
self.path3 = str()
#RUN Buttun
self.runbutton = Button(self.fen, text="RUN",command=self.start_foo_thread).grid(row=7,column=0,columnspan=2)
#FRAME CONSOLE
self.console = Frame(self.fen)
self.console.config(relief=SUNKEN, bg="black", height=200, width=400)
self.console.grid(row=8, columnspan=10)
self.console.grid_propagate(False) #to block the size of the frame
#QUIT BUTTON
self.quitButton = Button(self.fen)
self.quitButton.config(text="QUIT", command=self.fen.destroy)
self.quitButton.grid(row=100,column=0)
def folderPath(self):
path = askdirectory(title='Choose your set folder')
self.varLabel1.set(path)
self.listeBox1.delete(0, END)
for filename in sorted(glob.glob(path+'/*')):
if os.path.isfile(filename):
#stockage of path
self.path1 = os.path.split(filename)[0]
name = os.path.split(filename)[1]
self.listeBox1.insert(END, name)
def folderPath2(self):
path = askdirectory(title="Choose your library database folder")
self.varLabel2.set(path)
self.listeBox2.delete(0, END)
for filename in sorted(glob.glob(path+'/*')):
if os.path.isfile(filename):
#stockage of path
self.path2 = os.path.split(filename)[0]
name = os.path.split(filename)[1]
self.listeBox2.insert(END, name)
def run(self):
self.fen.mainloop()
def createJobName():
job = str(datetime.now())
job = job.replace(" ","-")
return job
def typeNP(self):
liste = []
#selection of query files
valListBox1 = [self.listeBox1.get(idx) for idx in self.listeBox1.curselection()]
#selection of database file
valListBox2 = [self.listeBox2.get(idx) for idx in self.listeBox2.curselection()]
#selection of sequence type
typ = (self.var.get(),self.var2.get())
# loop
for i in range(len(valListBox2)):
job = GraphicalUserInterface.createJobName()
path1 = self.path2
path2 = self.path1
DB = valListBox2[i]
path3 = os.getcwd()+"/"+DB+job
if os.path.isdir(DB+job) == True:
showwarning('Warning', "The folder already exist \n or they are no folder name !\nChange or get the folder name")
else:
os.mkdir(DB+job)
for filename in valListBox1:
seq = filename+job
seq2 = filename
#stock data for OneFile function
liste.append([path1,DB,path2,seq,seq2,typ,path3])
return liste
def start_foo_thread(self):
liste = self.typeNP()
for i in range(len(liste)):
global foo_thread
import threading
print('Fichier n°'+str(i+1)+' '+str(liste[i][4]))
stringLabel = Label(self.console,text='Fichier n°'+str(i+1)+' '+str(liste[i][4]),bg='black', fg='white')
stringLabel.grid(row=i,sticky="W")
foo_thread = threading.Thread(target=OneFile(liste[i][0],liste[i][1],liste[i][2],liste[i][3],liste[i][4],liste[i][5],liste[i][6]))
foo_thread.daemon = True
foo_thread.start()
#########
# AUTORUN #
#########
if __name__ == '__main__':
app = GraphicalUserInterface()
app.run()
The problem is when the loop began in:
def start_foo_thread(self):
liste = self.typeNP()
for i in range(len(liste)):
With the print function, I see the function run, but the label does not go in the frame when the iteration finishes. When the loops are completed, I see my label in the frame.
What is the correct code to have my label in my frame at the same time my function runs in my loop?
You sometimes have to manually update the widget. You have posted too much code to wade through, so this simple example should show the problem. Run as is, the labels don't show up until the function returns. Run with update_idletasks() uncommented does what I think you want. Also note that the program stops until the call to subprocess returns.
import sys
if sys.version_info[0] < 3:
import Tkinter as tk ## Python 2.x
else:
import tkinter as tk ## Python 3.x
class GraphicalUserInterface():
def __init__(self):
#constructor
self.fen = tk.Tk()
self.fen.title("Starch Enzyme Pipeline")
self.console=tk.Frame(self.fen)
self.console.grid()
self.liste=["one", "two", "three"]
tk.Button(self.fen, text="Exit", command=self.fen.quit).grid(row=1)
self.start_foo_thread()
self.fen.mainloop()
def start_foo_thread(self):
for ctr in range(len(self.liste)):
lit='Fichier n %s' % (ctr)
print(lit)
stringLabel = tk.Label(self.console, text=lit,
bg='black', fg='white')
stringLabel.grid(row=ctr,sticky="W")
##self.console.update_idletasks()
print("Waiting 2 seconds")
self.fen.after(2000) ## wait 2 seconds to show effect
print("Return from function")
if __name__ == '__main__':
app = GraphicalUserInterface()

Any way to pass a variable to a function without using parameters?

I'm trying to make an alarm clock in Python. The problem I'm having lies in the displayTime function. It's supposed to count down the number of seconds until the alarm will go off.
I need the aTime variable to be passed into the displayTime function. However, if I make aTime a parameter of the displayTime function, then I can't use displayTime as a parameter for timelabel.after(timelabel.after(1000, displayTime(aTime))), as it will make it an instance of displayTime rather than a parameter.
Since displayTime is nested within the alarm function, why doesn't it inherit aTime from alarm()?
Also how else can I get aTime into displayTime? Is there any other way besides using a parameter?
Here is the code:
from Tkinter import *
import time
def alarm() :
cHours = float(nHours.get())
cHours = cHours * 3600
cMinutes = float(nMinutes.get())
cMinutes = cMinutes * 60
aTime = cHours + cMinutes
print aTime
def displayTime():
timelabel = Label(alarmGUI, text = "%d seconds until it's time to wake up" % aTime)
timelabel.grid(row=9, column=0)
aTime -=1
timelabel.after(1000, displayTime)
displayTime()
alarmGUI = Tk()
alarmGUI.geometry('500x400')
alarmGUI.title("Alarm Clock")
nHours = IntVar()
nMinutes = IntVar()
label1 = Label(alarmGUI, text = "Enter the number of hours and number of minutes that you want to sleep").grid(row=1, column=1)
label2 = Label(alarmGUI, text = "Hours").grid(row = 3, column = 0)
label3 = Label(alarmGUI, text = "Minutes").grid(row = 5, column = 0)
hours = Entry(alarmGUI, textvariable = nHours).grid(row = 3, column = 1)
minutes = Entry(alarmGUI, textvariable = nMinutes).grid(row = 5, column = 1)
button1 = Button(alarmGUI, text = "Start", command = alarm).grid(row = 7, column = 0)
alarmGUI.mainloop()

Categories

Resources