Continuously pass Values in Tkinter and ammend it accordingly - python

The purpose is that input fn takes string input and pass it into GUI fn which runs the condition and ammend tkinter window accordingly.
#*********************************** IMPORTING MODULES*****************
import tkinter
from tkinter import*
import tkinter.messagebox
import sqlite3
import os
import threading
from time import sleep
from input import*
conn = sqlite3.connect('portal.db')
c = conn.cursor()
global a
#*************** TKINTER GUI CODE******************
def gui(a):
window = tkinter.Tk()
window.title("Smart Notice Board")
#********************** FRAMES OF MAIN WINDOW(HOME)******************
top = Canvas(window,width=1024,height=184)
top.pack(fill=X)
middle = Canvas(window, width=1024, height=450, bg='steelblue')
middle.pack(fill=X)
main_left = Canvas(middle, width=275, height=450, bg='lightgreen')
main_left.pack(side=LEFT)
main_right = Canvas(middle, width=800, height=450, bg='steelblue')
main_right.pack(side=RIGHT)
bottom = Canvas(window, width=1024, height=70, bg='black')
bottom.pack(fill=X)
#************************** IMAGES********************
i_top = tkinter.PhotoImage(file='F:\\C_backup\\fyp\\5 jan 2k19\\BG.png')
top.create_image(0,10, anchor=tkinter.NW,image = i_top)
i_right = tkinter.PhotoImage(file='F:\\C_backup\\fyp\\5 jan 2k19\\aus1.png')
main_right.create_image(0,0, anchor=tkinter.NW,image = i_right)
#i_left = tkinter.PhotoImage(file='F:\\C_backup\\fyp\\5 jan 2k19\\widget1.png')
#main_left.create_image(0,0, anchor=tkinter.NW,image = i_left)
t1 = tkinter.PhotoImage(file='F:\\C_backup\\fyp\\5 jan 2k19\\first.png')
t2 = tkinter.PhotoImage(file='F:\\C_backup\\fyp\\5 jan 2k19\\BG.png')
#***************** TIMETABLE IMAGE VIEWING FN***********************
def home():
main_right.create_image(0,0, anchor=tkinter.NW,image = t2)
#*********************** TIMETABLE BUTTON PRESS FN*************************
def timetable():
main_right.create_image(0,0, anchor=tkinter.NW,image = t1)
#******************************* CONDITIONS**********************
if a == "NULL":
timetable()
if a == "HOME":
home()
#*********************** MAIN MENU BUTTONS****************
button_1 = Button(text = ' HOME', anchor = 'w', height = 2, width = 8,activebackground = '#33B5e5',bg = 'brown',fg = 'white',command = home)
top.create_window(2,150,anchor = 'nw', window = button_1)
button_2 = Button(text='TIMETABLE', height = 2, width=12, activebackground = '#33B5e5', bg = 'brown', fg = 'white',command = timetable)
top.create_window(75,150, anchor='nw', window = button_2)
window.mainloop()
#************************** MAIN LOOP************************
if __name__ == "__main__":
#print(valuea())
a=valuea()
gui(a)
Now what I want is continuously run that thing and update Tkinter window; but the 2btn fn only takes it one time and pass it into GUI fn which runs tkinter and it stucks on window.mainloop as tkinter is infinity loop.
Please suggest me a solution also u can run this code by only setting pictures from your computer

The standard method to run code regularly in the mainloop is to register a timeout function using the after method of the root window.
But, whatever you do in such a timeout function (and indeed in all other callbacks), it should not block, because that would lock up the mainloop! So you cannot use input. But you could read from sys.stdin, which is a io.TextIOWrapper instance.
You could use input in a second thread. But since Tkinter isn't thread-safe, that second thread should not use Tkinter functions or methods. So you should not simply update a label from the second thread. You could save/append the input to a global variable, but you'd have to protect that with a lock or mutex. And you'd need to use a timeout function in the main Tkinter thread to test if the lock or mutex is released by the second thread so the Tkinter thread can claim it and access the data. As you can see this is really complicated. So mixing Tkinter and threads is generally not recommended.

In order to ammend tkinter window and show the text and open picture.I did slight change in the input.py file;and coded as below
def vala():
a=speech()
if a == "HOME":
home()
if a == "NULL":
timetable()
window.after(1000,vala)
what I have done is I convert it into recursive fn that call itself after 1000ms. In this way, it can be done.
Basically, I have done it with Pocketsphinx as Input (i.e. my project takes speech input and open file/image in tkinter screen and it runs continuously)

Related

after clicking my window goes not responding can any one hlep?

when I click the button it call's cpuTemp function and it has a after loop init which causes my not responding window and it is show values of cpu percent in my python console so the question is why it is not working
'''
from tkinter import *
import psutil
import statistics
window = Tk()
# window size
screen_width = window.winfo_screenwidth()
screen_height = window.winfo_screenheight()
# window
window.attributes('-transparentcolor', 'blue')
window.resizable(True, True)
window.attributes('-alpha', 0.96)
window.config(cursor='crosshair')
window.attributes('-topmost', 0)
window.geometry(f"{screen_width}x{screen_height}+20+20")
window.state('zoomed')
window.title('Hello Python')
# windTemp
def cpuTemp(event):
#gettin temps
cpuTemps = [psutil.cpu_percent(0.5), psutil.cpu_percent(0.5), psutil.cpu_percent(0.5),
psutil.cpu_percent(0.5), psutil.cpu_percent(0.5)]
meanVal = statistics.mean(cpuTemps)
print(meanVal)
lbl.configure(text=f'{meanVal}%')
window.after(1000 , cpuTemp(event))
#button
btn = Button(window, text="This is Button widget", fg='blue')
btn.place(x=80, y=100)
btn.bind('<Button-1>', cpuTemp)
#label
lbl = Label(window , text='hi' , fg = "#0009ff0fc")
lblPlace = [ screen_width/2 , screen_height/2]
lbl.place(x=f'{lblPlace[0]}', y=f'{lblPlace[1]}')
window.mainloop()
# temp
this is not working can anyone fix this for me I would appreciate that.
it stills print in my pycharm consloe so why is my window not responding.
i am using pycharm as you might know now.
and I want to make this code working .
i am a python newbie so pls help it would mean a lot to me...
window.after(1000 , cpuTemp(event)) immediately runs cpuTemp(event) and passes the result to window.after. This creates an infinite loop since each call results in another call to the function.
The code needs to look something like this:
window.after(1000, cpuTemp, None)
The reason for None is that the function doesn't use the event, and the current event is relatively useless except for when the original event is being processed.

Trigger creation of other tkinter windows

I am trying to create a python script that will trigger a tkinter window every time a certain event happens. The python script will have a while true loop and during the loop the tkinter event may or may not happen (if-else block). Right now the actual loop part isn't done, so I am currently testing the tkinter part but I can't seem to open more than tkinter window.
Below is the test script I am using.
from tkinter import *
from sys import exit
import os
onetwo = "C:/Users/I/Downloads/Transfer_Out_1016_Outlook.txt"
def popupError(s):
popupRoot = Tk()
##popupRoot.after(20000, exit)
popupButton = Button(popupRoot, text = s, font = ("Verdana", 12), bg = "yellow", command = lambda: os.system(onetwo))
popupButton.pack()
popupRoot.geometry('400x50+700+500')
popupRoot.mainloop()
popupError("HelloWORLD")
def popupTwo(s):
popupRoot = Tk()
##popupRoot.after(20000, exit)
popupButton = Button(popupRoot, text = s, font = ("Verdana", 12), bg = "yellow", command = lambda: os.system(onetwo))
popupButton.pack()
popupRoot.geometry('400x50+700+500')
popupRoot.mainloop()
popupTwo("HEWWWWWEWEWKOO")
I apologize for the lack of an actual piece of code but this is the best I can do right now given the dev status of the other parts of the overall python script.
Note that the tkinter window may be triggered more than once in a single loop session.
If any other details are needed, I'll try my best to add more in.
Here’s what you can do:
from tkinter import *
def popup(winName):
newWin = Toplevel()
btn2 = Button(newWin, text=winName)
btn2.pack()
root = Tk()
btn = Button(root, text=“Popup”, command=lambda: popup(“text”))
btn.pack()
root.mainloop()

Tkinter with another infinite loop ( For speech to text conversion)

Tkinter GUI don't shows up when running in parallel with another infinity loop;i have tried Threading and multiprocessing techniques, whereas used GUI in main code and calling livespeech code or vice versa ; and defining both codes in function and calling from the main thread.But the problem remains; different result are attached below although u find it comment but have tried that method too,
#*********************************** IMPORTING MODULES*****************
import tkinter
from tkinter import*
import tkinter.messagebox
import sqlite3
import os
from multiprocessing import Process
from pocketsphinx import LiveSpeech, get_model_path
import threading
from time import sleep
model_path = get_model_path()
#*************** TKINTER GUI CODE******************
def gui():
window = tkinter.Tk()
window.title("Smart Notice Board")
top = Canvas(window,width=400,height=200)
top.pack(fill=X)
button_5 = Button(text='PORTAL SYSTEM', height = 2, width=17, activebackground = '#33B5e5', bg = 'brown', fg = 'white',command = portal )
top.create_window(80,80, anchor='nw', window = button_5)
def portal():
print("2")
#**************** speech TO text CODE***************
def speech():
speech = LiveSpeech(
verbose=False,
sampling_rate=16000,
buffer_size=2048,
no_search=False,
full_utt=False,
hmm=os.path.join(model_path, 'en-us'),
lm=os.path.join(model_path, '8582.lm'),
dic=os.path.join(model_path, '8582.dict')
)
for phrase in speech:
print(phrase)
a=str(phrase)
print(a)
#************************** MAIN LOOP************************
if __name__ == "__main__":
#************ FOR THREADING************
#thread1 = threading.Thread(target=gui)
#thread2 = threading.Thread(target=speech)
#thread1.daemon = True
#thread1.start()
#thread2.start()
#thread1.join()
#thread2.join()
#************ FOR MULTIPROCESSING****************
#processes=[]
#P1 = Process(target=gui)
#P2 = Process(target=speech)
#processes.append(P1)
#processes.append(P2)
#P2.daemon = True
# Will execute both in parallel
#P1.start()
#P2.start()
# Joins threads back to the parent process, which is this
# program
#P1.join()
#P2.join()
#****************** live speech code*************
window = tkinter.Tk()
window.title("Smart Notice Board")
top = Canvas(window,width=400,height=200)
top.pack(fill=X)
button_5 = Button(text='PORTAL SYSTEM', height = 2, width=17, activebackground = '#33B5e5', bg = 'brown', fg = 'white',command = portal )
top.create_window(80,80, anchor='nw', window = button_5)
IN multiprocessing case; no error but nothing works
This is the code I use to get mouse move event's cursor position from queue and act accordingly:
def check_mouse(self):
while True:
item = self.mouse.get_item()
if item is None:
break
else:
self.master.after_idle(self.mouse_move, *item)
self.master.after(INTERVAL, self.check_mouse)
and it's first time called just before mainloop call, with yet another self.master.after(INTERVAL, self.check_mouse).
So make you Tkinter GUI do its work in the mainloop and you should create another loop with a task that will run after INTERVAL (in miliseconds) and it will call itself every INTERVAL period after its job is finished.

Tkinter GUI freezes while running looping

I'm new to python coding and I have been working on a project which could click on an image based on a chosen color. I have been using a program which loops the search 50 times when I click the start button. However, I have been trying to implement a stop button, but the problem is that my code freezes when the loop is running. Any ideas?
I have heard to try threading but it seems very complicated and I have been unable to follow any tutorials properly in relation to my code. By the way, the image searched has been testing images I've been using stored inside the program files.
from imagesearch import *
import pyautogui
import tkinter as tk
from tkinter import *
from tkinter.ttk import *
import time
import threading
# ---Defined Programs---
def run():
global enterColor
enterColor = str(enterColorField.get())
program(enterColor)
def program(color):
whitePos = imagesearch_numLoop(str(color) + ".PNG", 0, 50)
pyautogui.moveTo(whitePos[0] + 20, whitePos[1] + 10)
pyautogui.click()
def stop():
print("Placeholder")
# ---Main Runner---
window = tk.Tk()
window.geometry("250x250")
window.configure(background="#181b54")
app = tk.Frame(window)
app.grid()
enterColorLabel = tk.Label(window, text="Enter Color:", bg="#181b54", fg="white")
enterColorLabel.place(x=10, y=50)
enterColorField = Combobox(window)
enterColorField['values'] = ("Black", "White")
enterColorField.current("0") # set the selected item
enterColorField.place(x=10, y=70)
submitButton = tk.Button(window, text="Start", bg="#66ff00", command=run)
submitButton.place(x=10, y=130)
stopButton = tk.Button(window, text="Stop", bg="red", command=stop)
stopButton.place(x=50, y=130)
window.mainloop()
#---New Python Script---
import cv2
import numpy as np
import pyautogui
import random
import time
def imagesearch_numLoop(image, timesample, maxSamples, precision=0.8):
pos = imagesearch(image, precision)
count = 0
while pos[0] == -1:
print(image+" not found, waiting")
count = count + 1
if count>maxSamples:
break
pos = imagesearch(image, precision)
return pos
Whenever clicking start, the whole code freezes. I can't even (x) out.
Here's a hopefully simple multiprocessing recipe that will work for you. We'll have three main functions. The first will be an example loop that you would put your processing inside. I included arguments in the function to show you that it's possible to pass args and kwargs while using multiprocessing.
def loop(a, b, c, d):
# Will just sleep for 3 seconds.. simulates whatever processing you do.
time.sleep(3)
return
Next is a function we will use to queue the multiprocessing process.
def queue_loop():
p = multiprocessing.Process(target = loop,
args = (1, 2),
kwargs = {"c": 3, "d": 4})
# You can pass args and kwargs to the target function like that
# Note that the process isn't started yet. You call p.start() to activate it.
p.start()
check_status(p) # This is the next function we'll define.
return
Then, you may be interested in knowing the status of your process throughout its execution. For example it is sometimes desirable to disable certain buttons while a command is being run.
def check_status(p):
""" p is the multiprocessing.Process object """
if p.is_alive(): # Then the process is still running
label.config(text = "MP Running")
mp_button.config(state = "disabled")
not_mp_button.config(state = "disabled")
root.after(200, lambda p=p: check_status(p)) # After 200 ms, it will check the status again.
else:
label.config(text = "MP Not Running")
mp_button.config(state = "normal")
not_mp_button.config(state = "normal")
return
Throwing this all together into one snippet:
import tkinter as tk
import multiprocessing
import time
def loop(a, b, c, d):
# Will just sleep for 3 seconds.. simulates whatever processing you do.
time.sleep(3)
return
def queue_loop():
p = multiprocessing.Process(target = loop,
args = (1, 2),
kwargs = {"c": 3, "d": 4})
# You can pass args and kwargs to the target function like that
# Note that the process isn't started yet. You call p.start() to activate it.
p.start()
check_status(p) # This is the next function we'll define.
return
def check_status(p):
""" p is the multiprocessing.Process object """
if p.is_alive(): # Then the process is still running
label.config(text = "MP Running")
mp_button.config(state = "disabled")
not_mp_button.config(state = "disabled")
root.after(200, lambda p=p: check_status(p)) # After 200 ms, it will check the status again.
else:
label.config(text = "MP Not Running")
mp_button.config(state = "normal")
not_mp_button.config(state = "normal")
return
if __name__ == "__main__":
root = tk.Tk()
mp_button = tk.Button(master = root, text = "Using MP", command = queue_loop)
mp_button.pack()
label = tk.Label(master = root, text = "MP Not Running")
label.pack()
not_mp_button = tk.Button(master = root, text = "Not MP", command = lambda: loop(1,2,3,4))
not_mp_button.pack()
root.mainloop()
The result is that when you click the "Using MP" button, the command buttons will be disabled and the process will be started without freezing your UI. Clicking the "Not MP" button will start the function like 'normal' and will freeze your UI as you noticed in your own code.
A simple answer is you cannot use while loop in GUI design.
But you can use the method .after(delay, callback=None) instead.
Here is an example:
from tkinter import *
root = Tk()
def loop():
print("Hi!")
root.after(1000, loop) # 1000 is equal to 1 second.
root.after(1000, loop) # This line is to call loop() in 1 second.
root.mainloop()

Python tkinter GUI freezing/crashing

from Tkinter import *
import tkFileDialog
import tkMessageBox
import os
import ttk
import serial
import timeit
import time
######################################################################################
class MyApp:
def __init__(self, parent):
########################################################
#Setup Frames
self.MiddleFrame = Frame(parent) #Middle Frame
self.MiddleFrame.pack()
#GLOBAL VARIABLES
self.chip_number = 0 #number of chip testing
###########################################
#Middle Frame setup
Label(self.MiddleFrame, text='Done').grid(row=8, column=1, sticky = E)
self.Done = Canvas(self.MiddleFrame, bg="yellow", width=10, height=10)
self.Done.grid(row=8, column=2)
Label(self.MiddleFrame, text='Chip Number:').grid(row=9, column=1, sticky = E)
#start button
self.button1 = Button(self.MiddleFrame,state=NORMAL, command= self.start_pre)
self.button1["text"]= "START"
self.button1.grid(row=1, column=2, sticky = E)
###########################################
#Action of Start Button
def start_pre(self):
x = 0
while x<10000:
self.start_button()
x=x+1
#Talking to Board
def start_button(self):
#increase chip count number and update
self.chip_number += 1
Label(self.MiddleFrame, text=str(self.chip_number)).grid(row=9, column=2, sticky = E)
#reset-yellow
self.reset_color()
print "Still Working", self.chip_number
self.Done.configure(background="green")
self.Done.update_idletasks()
###############################################################
#Color Boxes
#Reset
def reset_color(self):
self.Done.configure(background="yellow")
self.Done.update_idletasks()
###############################################################################################################
#Start Programs
root = Tk() #makes window
root.title("Interface")
myapp = MyApp(root) #this really runs program
root.mainloop() #keep window open
With my program, i first push the start button.
I will print "still working" and the GUi will update chip number and blink done light over and over. The start button go to function that will execute 10000 times. However after 3000 iterations, the gui freeze, but the program is still print "still working". How do I keep the gui from crashing?
There are many problems with your code. For one, this is fundamentally flawed:
while self.stop == True:
self.start_button()
time.sleep(0.5)
You simply can't expect a GUI to behave properly with code like that. As a general rule of thumb you should never have the main thread of a GUI call sleep. Causing sleep prevents the event loop from processing any events, including low level events such as requests to refresh the screen.
The use of sleep has been asked and answered many times on stackoverflow. You might find some of those questions useful. For example,
windows thinks tkinter is not responding
Python Tkinter coords function not moving canvas objects inside loop
How do widgets update in Tkinter?
Tkinter multiple operations
Python Tkinter Stopwatch Error
You have another problem that falls into the category of a memory leak. From that while loop, you call self.start_button() indefinitely. This happens about once a second, due to sleep being called for half a second in the loop, and another half a second in start_button.
Each time you call start_button, you create another label widget that you stack on top of all previous widgets in row 9, column 2. Eventually this will cause your program to crash. I'm surprised that it causes your program to fail so quickly, but that's beside the point.
My recommendation is to start over with a simple example that does nothing but update a label every second. Get that working so that you understand the basic mechanism. Then, once it's working, you can add in your code that reads from the serial port.
May I suggest that you start over with the following code? You can port in back to Python 2 if needed, but your program has been rewritten to use Python 3 and has been designed to use tkinter's ability to schedule future events with the after methods. Hopefully, you will find the code easier to follow.
import collections
import timeit
import tkinter
def main():
root = Application()
root.setup()
root.mainloop()
class Application(tkinter.Tk):
def setup(self):
mf = self.__middle_frame = tkinter.Frame(self)
self.__middle_frame.grid()
bf = self.__bot_frame = tkinter.Frame(self)
self.__bot_frame.grid()
self.__port_set = False
self.__chip_number = 0
self.__chip_pass_num = 0
self.__chip_fail_num = 0
self.__chip_yield_num = 0
self.__stop = True
self.__widgets = collections.OrderedDict((
('COT', 'Continuity Test'), ('CHE', 'Chip Erase'),
('ERT', 'Erase Test'), ('WRT', 'Write Test'),
('WIRT', 'Wire Reading Test'), ('WIT', 'Wire Reading Test'),
('WRAT', 'Write All Test'), ('DO', 'Done')))
for row, (key, value) in enumerate(self.__widgets.items()):
label = tkinter.Label(mf, text=value+':')
label.grid(row=row, column=0, sticky=tkinter.E)
canvas = tkinter.Canvas(mf, bg='yellow', width=10, height=10)
canvas.grid(row=row, column=1)
self.__widgets[key] = label, canvas
self.__cn = tkinter.Label(mf, text='Chip Number:')
self.__cn.grid(row=8, column=0, sticky=tkinter.E)
self.__display = tkinter.Label(mf)
self.__display.grid(row=8, column=1, sticky=tkinter.E)
self.__button = tkinter.Button(bf, text='START',
command=self.__start_pre)
self.__button.grid(sticky=tkinter.E)
def __start_pre(self):
self.__button['state'] = tkinter.DISABLED
self.__start_button(0)
def __start_button(self, count):
if count < 100:
self.__chip_number += 1
self.__display['text'] = str(self.__chip_number)
self.__widgets['DO'][1]['bg'] = 'yellow'
start_time = timeit.default_timer()
print('Still Working:', self.__chip_number)
self.after(500, self.__end_button, count)
else:
self.__button['state'] = tkinter.NORMAL
def __end_button(self, count):
self.__widgets['DO'][1]['bg'] = 'green'
self.after(500, self.__start_button, count + 1)
if __name__ == '__main__':
main()

Categories

Resources