0

i am trying to learning python gui with programming some mini projects. so now i tried to program a water alarm but the problem is that at one part my program did not go in the if loop. here is my code

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

#Eingabefeld=EF / Button= BN/ Label= LB

import csv
import datetime
import os
import sys
import csv 
import time
import webbrowser
import threading
from tkinter import *
from tkinter import messagebox


path= '\\Users\YIF5WI\water alert\wateralarm'
filename= 'godhelpme.csv'
global fullpath
fullpath= os.path.join(path,filename)

class Waterentry:
    def __init__(self, master):
        self.master = master    

        master.title('Water controller')
        master.configure(bg='light blue')

        ws = master.winfo_screenwidth()         
        hs = master.winfo_screenheight() 
        x = ws - 350
        y = hs - 300
        self.master.geometry('%dx%d+%d+%d' % (350, 300, x, y))

        self.frame = Frame(master)
        self.frame.configure(bg='light blue')
        self.frame.pack()

        self.LB_txt= Label(self.frame,bg='light blue', text='Choose how much you drink or \n Write the amount of water in ml!!!')
        self.LB_txt.pack(side=TOP)

        self.txtDisplay = Entry(self.frame,bd= 20, insertwidth=1, font= 30)
        self.txtDisplay.pack(side= TOP)
        self.txtDisplay.bind("<KeyRelease>", self.checkifdigit)

        self.frame2=Frame(master)
        self.frame2.configure(bg='light blue')
        self.frame2.pack(side = TOP)
        self.BN_txtOk= Button(self.frame2,text ='OK',bg = 'green',fg='white', padx=38, pady= 8, bd= 8, command = lambda : self.txtOk(self.txtDisplay))
        self.BN_txtOk.grid(row=0, column= 0)


        self.LB_info= Label(self.frame2,bg='light blue', text='1 Suppenloffel=10ml/ Ein Schluck  min = 20ml,max=40ml')
        self.LB_info.grid(row=1)

        self.frame3= Frame(master)
        self.frame3.configure(bg='light blue')
        self.frame3.pack(side=TOP)
        self.BN_water= Button(self.frame3, text ='100ml',bg ='blue',fg = 'white',padx=8, pady= 8, bd= 8, command = lambda : self.addNumber('100ml'))
        self.BN_water.pack(side = LEFT)
        self.BN_water1= Button(self.frame3, text ='200ml',bg ='blue',fg = 'white',padx=8, pady= 8, bd= 8, command = lambda : self.addNumber('200ml'))
        self.BN_water1.pack(side = LEFT)        
        self.BN_water2= Button(self.frame3, text ='300ml',bg ='blue',fg = 'white',padx=8, pady= 8, bd= 8, command = lambda : self.addNumber('300ml'))
        self.BN_water2.pack(side = LEFT)        
        self.BN_water3= Button(self.frame3, text ='0,5L',bg ='blue',fg = 'white',padx=8, pady= 8, bd= 8, command = lambda : self.addNumber('500ml'))
        self.BN_water3.pack(side = LEFT)
        self.BN_water4= Button(self.frame3, text ='1L',bg ='blue',fg = 'white',padx=8, pady= 8, bd= 8, command = lambda : self.addNumber('1000ml'))
        self.BN_water4.pack(side = LEFT)

    def checkifdigit(self, EN_number):
        if not self.txtDisplay.get().isdigit():
            txt = self.txtDisplay.get()[:-1]
            self.txtDisplay.delete(0, END)
            self.txtDisplay.insert(0, txt)
        else:
            self.txtDisplay.get()


    def txtOk(self,EN_number):
        EN_number = self.txtDisplay.get()    
        print(EN_number)

        with open(fullpath,'a',) as f:  
            writer = csv.writer(f)     
            ohne_ml=re.sub(r'\D', '',EN_number)  
            writer.writerow(ohne_ml.split(','))                
        return

    def addNumber(self,BN_number):         
        print(BN_number)        
        with open(fullpath,'a') as f:
            writer1=csv.writer(f)
            new= re.sub(r'\D', '',BN_number)
            writer1.writerow(new.split(','))                    
        return  

def entry():
    root1= Tk()
    waterentry= Waterentry(root1)

    root1.mainloop()

here at the main function i have the problem

def opentkformessage():   
    root=Tk()
    root.withdraw()


def checkentry():
    try:
        with open('godhelpme.csv') as input, open('godhelpme1.csv', 'w') as output:
            non_blank = (line for line in input if line.strip())
            output.writelines(non_blank)

        with open("godhelpme1.csv") as fin:
            total = 0
            for row in csv.reader(fin):
                total += int(row[0])
                global total_liter
                total_liter= total * 0.001
        print(total_liter)
    except:
        opentkformessage()
        messagebox.showinfo('Water drink program','You must add your drunked water')
        entry()


def main():

    checkentry()
    opentkformessage()   
    global total_liter

    if (total_liter < 0.5):      
        messagebox.showinfo('WARNING','Drunked water:' +str(total_liter)+' L\nGOOO and take  minumum 0.2Liter WATER!!!\n You have 60 seconds!!')
        entry()  
        #time.sleep(10)
        **# HERE IS MY PROBLEM AFTER I CALL THE ENTRY() FUNCTION 
        # the if total_liter<0.2 will passed**
        checkentry()
        time.sleep(5)
        if (total_liter < 0.2):
            count = 0
            while count <5:
                os.system('water.jpg')
                time.sleep(5)
                webbrowser.open('https://www.youtube.com/watch?v=cRYMOIn45uE')
                time.sleep(15)
                os.system('water.png')
                time.sleep(5)
                os.system('water.jpg')
                time.sleep(5)
                count +=1
            entry()    

        else:
            messagebox.showinfo('INFO','Good you reach 0.5Liter')


    elif(0.501 < total_liter < 1.0):
        messagebox.showinfo('INFO', 'Drunked water:' +str(total_liter)+' L\nTry to drink approximately 0.3 liter\nfor the next hour' )
        entry() 

    elif(1.01 < total_liter < 2.0):
        messagebox.showinfo('INFO', 'Drunked water:' +str(total_liter)+' L\n Try to reach min water level.\n' )
        entry() 

    #elif (2.01 < total_liter):
        #messagebox.showinfo('INFO','Good!\n You reach the minumum water level.\nYou totally drink:'+str(total_liter)+' L')
        #entry()
    elif (2.1 < total_liter ): 
        messagebox.showinfo('INFO','Good!\n You reach the minumum water level.\nYou totally drink:'+str(total_liter)+' L\n Now your saved drunked water will cleaned')
        os.remove('godhelpme.csv')

    else:
        messagebox.showinfo('Something is wrong but, i don t now what:-)')

    #threading.Timer(10.0, main).start()
if __name__ == '__main__':  
    main()

after the keyinterrupt i get:

Traceback(most recent call last):
File"finish.py", line 181, in<module>
 main()
File"finish.py", line 138,in main
 entry()
File"finish.py", line 103,in entry
 root1.mainloop()
kpl33
  • 13
  • 6

1 Answers1

0

You're starting a tkinter mainloop. The mainloop is an infinite loop that controls everything about tkinter- once you enter, you're in the event loop and further code doesn't execute unless you give input that's bound to run code or scheduled callbacks in the event loop. This is a good reference on the matter.

The main point is that you have to mentally substitute any tkinter .mainloop() as though it were while True: do tkinter_updates. The best way to run things is to register a majority of your main() function as its own function. You can then call root.after(1000, main) to schedule the function to run after the mainloop starts up.


A word of warning: your code can start multiple mainloops. This is a bad thing, as they will be improperly scoped (one mainloop can't see the data of its parent mainloop) and can cause myriad bugs and leak memory (since you're allocating the stuff for a new mainloop, but the old stuff is still accessible; you're using recursion). Make sure your code cannot start more than one mainloop or you will have problems with it.

Also, never use time.sleep() with tkinter; while Python is sleeping, tkinter cannot update or receive input. Use root.after() to schedule things to happen in the future- it's roughly as consistent as time.sleep(), doesn't freeze the whole GUI, and works better in general with tkinter.

Community
  • 1
  • 1
Delioth
  • 1,564
  • 10
  • 16
  • thank you for the good information with the root.after method. i will not use time.sleep but i didn´t understand why my program doesnt go in the loop.-->if (total_liter < 0.2): – kpl33 Apr 24 '17 at 09:07
  • @kpl33 because it can't. It's stuck in the tkinter mainloop- when you execute `root.mainloop`, it's in a `while true` loop. It only exits this loop when all of tkinter is finished- i.e. when there are no more windows to draw/update/track (or when you manage to detach the windows from the interpreter, which is a problem- don't try to do that, it'll break things). – Delioth Apr 24 '17 at 18:19
  • hmm ok i understand i ask that again because it works if i have seperata programs . When in one is the gui and on the other is my main and if i call the gui with the command subprocess.Popen() it works. I just thought its looking better if i have this in one program. – kpl33 Apr 27 '17 at 07:40