How to call a method into a ticker Button as command - python

In the tkinter GUI I created a run Button. I liked to click the button then it should start counting. But When I call the method into the ttk.Button as command. it does not work. In this code two class was created. run method was created in the first class and it will be call into the second class. Could you please kindly check the code. Thanks in advance.
from tkinter import *
import threading
import queue
from time import sleep
import random
from tkinter import ttk
class Thread_0(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
count = 0
while True:
count +=1
hmi.thread_0_update(count)
sleep(random.random()/100)
class HMI:
def __init__(self):
self.master=Tk()
self.master.geometry('200x200+1+1')
self.f=ttk.Frame(self.master,height = 100, width = 100, relief= 'ridge')
self.f.grid(row=1,column=1, padx=20, pady=20)
self.l0=ttk.Label(self.f)
self.l0.grid(row=1,column=1)
self.button=ttk.Button(self.master, text = 'run')
self.button.grid(row=2,column=2)
self.q0=queue.Queue()
self.master.bind("<<Thread_0_Label_Update>>",self.thread_0_update_e)
def start(self):
self.master.mainloop()
self.master.destroy()
#################################
def thread_0_update(self,val):
self.q0.put(val)
self.master.event_generate('<<Thread_0_Label_Update>>',when='tail')
def thread_0_update_e(self,e):
while self.q0.qsize():
try:
val=self.q0.get()
self.l0.config(text=str(val), font = ('Times New Roman', 15))
except queue.Empty:
pass
##########################
if __name__=='__main__':
hmi=HMI()
t0=Thread_0()
t0.start()
hmi.start()

You can use
Button( ..., command=t0.start )
See: start is without (). But you have to create t0 before hmi
if __name__ == '__main__':
t0 = Thread_0()
hmi = HMI()
hmi.start()
Full code which works for me
from tkinter import *
import threading
import queue
from time import sleep
import random
from tkinter import ttk
class Thread_0(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
count = 0
while True:
count +=1
hmi.thread_0_update(count)
sleep(random.random()/100)
class HMI:
def __init__(self):
self.master=Tk()
self.master.geometry('200x200+1+1')
self.f = ttk.Frame(self.master, height=100, width=100, relief='ridge')
self.f.grid(row=1, column=1, padx=20, pady=20)
self.l0 = ttk.Label(self.f)
self.l0.grid(row=1, column=1)
self.button = ttk.Button(self.master, text='run', command=t0.start)
self.button.grid(row=2, column=2)
self.q0 = queue.Queue()
self.master.bind("<<Thread_0_Label_Update>>", self.thread_0_update_e)
def start(self):
self.master.mainloop()
self.master.destroy()
#################################
def thread_0_update(self,val):
self.q0.put(val)
self.master.event_generate('<<Thread_0_Label_Update>>', when='tail')
def thread_0_update_e(self,e):
while self.q0.qsize():
try:
val = self.q0.get()
self.l0.config(text=str(val), font=('Times New Roman', 15))
except queue.Empty:
pass
##########################
if __name__ == '__main__':
t0 = Thread_0()
hmi = HMI()
hmi.start()

Related

How to import a scrollable frame from one script into a frame in a different script tkinter

Sorry for the confusing title basically what I'm trying to figure out how to import a frame from one script into another. I'm not sure how I would call it since it has so many functions. Here are my two scripts:
File Name - wrapper:
import tkinter as tk
import workingcatch
from tkinter import *
root = tk.Tk()
outputframe = LabelFrame(master=root, width=800, height=700) #where i want to import the script
outputframe.pack(side=LEFT, padx=10,pady=10)
root.geometry('1280x720')
root.mainloop()
File Name - workingcatch:
from subprocess import Popen, PIPE, STDOUT
from threading import Thread
import tkinter as tk
import logging
import time
import sys
info = logging.getLogger(__name__).info
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(message)s")
platform = windows = 'mswin'
# define dummy subprocess to generate some output
cmd = [sys.executable or "python", "-u", "-c", """
import itertools, time
for i in itertools.count():
print(i)
time.sleep(0.5)
exit()
""", "exit"]
class OStream(Thread):
enable_print = True
def handel_line(self, line):
if platform == windows:
# Windows uses: "\r\n" instead of "\n" for new lines.
line = line.replace(b"\r\n", b"\n")
if self.enable_print:
info("got: %r", line)
if self.stream_print is not None:
self.stream_print(line)
def stop(self):
self.alive = False
def run(self):
while self.alive:
for s in self.ostrams:
line = s.stdout.readline()
if line:
self.handel_line(line)
time.sleep(0.2)
info("OStream Exit")
def pipe_proc(self, stream):
self.ostrams.append(stream)
def stream_callback(self, func):
self.stream_print = func
def __init__(self):
self.ostrams = []
self.alive = True
self.stream_print = None
Thread.__init__(self)
class Scrolable_Frame(tk.Frame):
def get(self):
return self.interior
def __init__(self, master):
tk.Frame.__init__(self, master)
self.scroll = tk.Scrollbar(self)
self.scroll.pack(side=tk.RIGHT, fill=tk.Y)
self.canvas = tk.Canvas(
self, bd=0, highlightthickness=0,
yscrollcommand=self.scroll.set)
self.canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=tk.TRUE)
self.scroll.config(command=self.canvas.yview)
self.canvas.xview_moveto(0)
self.canvas.yview_moveto(0)
self.interior = tk.Frame(self.canvas)
interior_id = self.canvas.create_window(
0, 0, window=self.interior, anchor=tk.NW
)
def _configure_interior(_):
size = (self.interior.winfo_reqwidth(), self.interior.winfo_reqheight())
self.canvas.config(scrollregion="0 0 %s %s" % size)
if self.interior.winfo_reqwidth() != self.canvas.winfo_width():
self.canvas.config(width=self.interior.winfo_reqwidth())
self.interior.bind('<Configure>', _configure_interior)
def _configure_canvas(_):
if self.interior.winfo_reqwidth() != self.canvas.winfo_width():
self.canvas.itemconfigure(interior_id, width=self.canvas.winfo_width())
self.canvas.bind('<Configure>', _configure_canvas)
def _on_mousewheel(event):
self.canvas.yview_scroll(int(-1 * (event.delta / 120)), 'units')
self.canvas.bind_all("<MouseWheel>", _on_mousewheel)
class ShowProcessOutputDemo(tk.Tk):
def __init__(self):
"""Start subprocess, make GUI widgets."""
tk.Tk.__init__(self)
self.geometry('300x200+500+300')
self.protocol("WM_DELETE_WINDOW", self.stop)
self.proc = Popen(cmd, stdout=PIPE, stderr=STDOUT)
self.ostream = OStream()
self.ostream.pipe_proc(self.proc)
self.ostream.stream_callback(self.add_label)
self.ostream.start()
self.exit_button = tk.Button(
self, text="Stop subprocess", command=self.stop
)
self.exit_button.pack(pady=20)
self.scolable_frame = Scrolable_Frame(self)
self.scolable_frame.pack(
expand=True, fill=tk.BOTH, pady=20, padx=20
)
def add_label(self, line):
line_text = 'OStream line content: {0}'.format(line[:-1].decode())
tk.Label(
self.scolable_frame.get(), text=line_text
).pack(anchor=tk.CENTER, expand=True, fill=tk.X)
def stop(self):
"""Stop subprocess and quit GUI."""
self.ostream.stop()
self.proc.kill()
self.proc.stdout.close()
self.proc.wait(timeout=2)
info("GUI Exit")
self.quit()
if __name__ == '__main__':
app = ShowProcessOutputDemo()
app.mainloop()
So what I'm trying to do is get the output from "workingcatch" into 'wrapper's frame.
Thanks for reading

How to create two timers in one tkinter window using multiprocessing?

I want to create two times in one tkinter window using multiprocessing. I want to run two timers simultaneously. Here is the code. First it shows the window with the given text and then it shows error.
Code:
from multiprocessing import Process
from time import time, sleep
from tkinter import *
class Main:
def __init__(self):
self.root = Tk()
self.root.geometry('300x300')
self.lab1 = Label(self.root, text='None')
self.lab1.place(x=10, y=10)
self.lab2 = Label(self.root, text='None')
self.lab2.place(x=10, y=50)
self.root.mainloop()
def c1(self):
st = time()
for _ in range(10):
self.lab1['text'] = int(time()-st)
self.root.update()
sleep(1)
def c2(self):
st = time()
for _ in range(10):
self.lab2['text'] = int(time()-st)
self.root.update()
sleep(1)
def main(self):
self.p1 = Process(target=self.c1)
self.p2 = Process(target=self.c2)
self.p1.start()
self.p2.start()
self.p1.join()
self.p2.join()
if __name__ == '__main__':
start = Main()
start.main()

Python: update tkinter canvas widget from thread events

I am trying to make a status light on my tkinter GUI. At this point I just want it to rotate from green to red to show that the script hasn't frozen. The python traceback errors that I get all point to __libraries that I don't understand. I feel like this must be a namespace problem, but I'm ripping out my hair trying to put my finger on it.
The eventCheck() method worked great at creating a label that toggled between 0 and 1 before I created the canvas object and tried passing c into it. There is so little information out there on what I am trying to do, maybe there is a better way?
Here is a condensed version of my script:
import tkinter as tk
from tkinter import Canvas
import time
import threading
class myGUI(tk.Frame):
def __init__(self, master, event):
self.master = master
self.event = event
super().__init__(master)
self.label = tk.Label(self, text="")
self.label.grid()
self.after(1, self.eventCheck)
c = tk.Canvas(self, bg='white', width=80, height=80)
c.grid()
self.eventCheck(c)
def redCircle(self, c):
c.create_oval(20, 20, 80, 80, width=0, fill='red')
print("redCircle Called")
def greenCircle(self,c):
c.create_oval(20, 20, 80, 80, width=0, fill='green')
print("greenCircle Called")
def eventCheck(self, c):
self.label['text'] = self.event.is_set()
if self.label['text'] == 0:
self.redCircle(c)
else:
self.greenCircle(c)
self.after(2000, self.eventCheck(c))
def timingLoop(event):
while True:
event.set()
time.sleep(2)
event.clear()
time.sleep(2)
def main():
root = tk.Tk()
root.title("myFirst GUI")
event = threading.Event()
t=threading.Thread(target=timingLoop, args=(event,))
t.daemon = True
t.start()
app = myGUI(root, event)
root.mainloop()
if __name__=="__main__":
main()
I found two major issues with your code. First, this isn't doing what you think it should:
def eventCheck(self, c):
# ...
self.after(2000, self.eventCheck(c))
Because you passed the result of a call to self.eventCheck(c) to after() instead of the method self.eventCheck, this is an infinite recursion that takes place immediately.
The second issue is that if you comment out all your timing and event stuff, your interface never actually comes up, so there's never anything to see. I've condensed (simplified) your example script even further into one that basically works:
import tkinter as tk
import threading
import time
class myGUI:
def __init__(self, master, event):
self.master = master
self.event = event
self.label = tk.Label(master, text="")
self.label.pack()
self.canvas = tk.Canvas(master, bg='white', width=80, height=80)
self.canvas.pack()
self.eventCheck()
def redCircle(self):
self.canvas.create_oval(20, 20, 80, 80, width=0, fill='red')
print("redCircle Called")
def greenCircle(self):
self.canvas.create_oval(20, 20, 80, 80, width=0, fill='green')
print("greenCircle Called")
def eventCheck(self):
flag = self.event.is_set()
self.label['text'] = flag
if flag:
self.greenCircle()
else:
self.redCircle()
self.master.after(2000, self.eventCheck)
def timingLoop(event):
while True:
event.set()
time.sleep(2)
event.clear()
time.sleep(2)
def main():
root = tk.Tk()
root.title("myFirst GUI")
event = threading.Event()
t = threading.Thread(target=timingLoop, args=(event,))
t.daemon = True
t.start()
app = myGUI(root, event)
root.mainloop()
if __name__ == "__main__":
main()
Now you should be able to add back your Frame superclass. Make sure to add the frame that is myGUI to your root object.

Trigger an event when a thread is finished

Hi Python and Tkinter Gurus,
I am trying to build a simple GUI which has two buttons. When the Button is clicked, a thread is started to do some work. This work normally takes 10s/15s. And the GUI also works fine.
But I want to implement a pop-up to notify which thread has been completed. I have checked t.isAlive() function and could not implement it because I don't know how to trigger an event based on isAlive in the main loop.
Here is my sample code
from threading import Thread
from time import sleep
import Tkinter
import ttk
class SmallGui:
def __init__(self, master):
self.master = master
self.master.title('test gui')
self.button_1 = ttk.Button(self.master,
text='Start 1',
command=lambda: self.init_thread(1))
self.button_2 = ttk.Button(self.master,
text='Start 2',
command=lambda: self.init_thread(2))
self.button_1.pack()
self.button_2.pack()
def init_thread(self, work):
if work == 1:
t = Thread(target=self.work_1)
t.start()
else:
t = Thread(target=self.work_2)
t.start()
#staticmethod
def work_1():
print 'Work 1 started'
# Do some Task and return a list
sleep(10)
#staticmethod
def work_2():
print 'Work 2 Started'
# Do some Task and return a list
sleep(15)
if __name__ == '__main__':
root = Tkinter.Tk()
run_gui = SmallGui(root)
root.mainloop()
You can use tkinter's messagebox. Tkinter has a built in method that can be used for all kinds of pop-up messages or questions. Here we will use messagebox.showinfo.
I am working on Python 3.X so I added a import method that will work for both 3.X and 2.X versions of python.
from threading import Thread
from time import sleep
try:
import Tkinter as tk
import tkMessageBox as mb
import ttk
except ImportError:
import tkinter as tk
from tkinter import messagebox as mb
import tkinter.ttk as ttk
class SmallGui:
def __init__(self, master):
self.master = master
self.master.title('test gui')
self.button_1 = ttk.Button(self.master,
text='Start 1',
command=lambda: self.init_thread(1))
self.button_2 = ttk.Button(self.master,
text='Start 2',
command=lambda: self.init_thread(2))
self.button_1.pack()
self.button_2.pack()
def init_thread(self, work):
if work == 1:
t = Thread(target=self.work_1)
t.start()
else:
t = Thread(target=self.work_2)
t.start()
#staticmethod
def work_1():
print ('Work 1 started')
# Do some Task and return a list
sleep(1)
mb.showinfo("test", "Work 1 complete")
#staticmethod
def work_2():
print ('Work 2 Started')
# Do some Task and return a list
sleep(1)
mb.showinfo("test", "Work 2 complete")
if __name__ == '__main__':
root = tk.Tk()
run_gui = SmallGui(root)
root.mainloop()
UPDATE:
For whatever reason my above solution works in python 3 but no in 2.7.14.
The below example however does work in 2.7.14 and should work for you.
What I have done here is create 2 class attributes to monitor each thread.
I have created a method that will check ever 1 second if a thread is active and if the thread becomes inactive a messagebox will popup.
from threading import Thread
from time import sleep
import Tkinter as tk
import tkMessageBox as mb
import ttk
class SmallGui(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
self.master = master
self.master.title('test gui')
self.button_1 = ttk.Button(self.master,
text='Start 1',
command=lambda: self.init_thread(1))
self.button_2 = ttk.Button(self.master,
text='Start 2',
command=lambda: self.init_thread(2))
self.button_1.pack()
self.button_2.pack()
self.work1_status = None
self.work2_status = None
def init_thread(self, work):
if work == 1:
self.work1_status = Thread(target=self.work_1)
self.work1_status.start()
self.check_thread(self.work1_status, work)
else:
self.work2_status = Thread(target=self.work_2)
self.work2_status.start()
self.check_thread(self.work2_status, work)
def check_thread(self, pass_thread, thread_name):
if pass_thread.isAlive() == False:
pass_thread = None
mb.showinfo("test", "Work {} complete".format(thread_name))
else:
self.after(1000, lambda: self.check_thread(pass_thread, thread_name))
#staticmethod
def work_1():
print ('Work 1 started')
# Do some Task and return a list
sleep(5)
#staticmethod
def work_2():
print ('Work 2 Started')
# Do some Task and return a list
sleep(5)
if __name__ == '__main__':
root = tk.Tk()
run_gui = SmallGui(root)
root.mainloop()

How to display the messages from the dictionary to tk text window

This code is to receive and display the text on the tk window.But what i want to achieve here is:
When the character is sent from master to slave. Receive the character on the slave, look up the character in the dict, display the value that corresponds to the key.
I tried but couldn't succeed, can any one help me with the correct code.
for example: when slave received a key called 'hw',It has to display "hello world",
when '0' received, should display "how are you?" on the tk text widget window.
thanks in advance.
import serial
import threading
import Queue
import Tkinter as tk
from Tkinter import *
import time
import sys
class SerialThread(threading.Thread):
def __init__(self, queue):
threading.Thread.__init__(self)
self.queue = queue
def run(self):
s = serial.Serial('COM11',9600)
while True:
if s.inWaiting():
text = s.readline(s.inWaiting())
self.queue.put(text)
class App(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.geometry("1360x750")
self.time = ''
self.clock = tk.Label(self, font=('times', 50, 'bold'), fg='black', bg='yellow')
self.clock.pack(side='bottom', anchor='se')
frameLabel = tk.Frame(self, padx=10, pady =50)
self.text = tk.Text(frameLabel, wrap='word', bg=self.cget('bg'), relief='flat')
frameLabel.pack()
self.text.pack()
self.queue = Queue.Queue()
thread = SerialThread(self.queue)
thread.start()
self.process_serial()
self.msgs = {
'hw':"hello world",
'wpp':"welcome to python programming",
'h':"hello",
0:"how are you?",
1:"bye....",
'egm': "english general message how are you",
'egm2':"If the world is flat be carefull not to fall off"
}
def process_serial(self):
self.time = time.strftime('%H:%M:%S')
self.clock.config(text=self.time)
firstitem = True
while self.queue.qsize():
try:
new = self.queue.get()
size = sys.getsizeof(new)
if size<40:
self.text.config(font='TimesNewRoman 100')
elif size>=40 and size<70:
self.text.config(font='TimesNewRoman 75')
else:
self.text.config(font='TimesNewRoman 50')
if firstitem:
self.text.delete(1.0, 'end')
firstitem = False
self.text.tag_configure("tag-center", justify='center')
#self.text.tag_add("center", 1.0, "end")
self.text.insert('end', my_dictionary.setdefault(signal, 'wrong signal'))
#self.text.insert('end', new, 'tag-center')
except Queue.Empty:
pass
self.after(1000, self.process_serial)
app = App()
app.mainloop()

Categories

Resources