multiple processes to update to the correct grid location - python

I am trying to create three processes that will each eventually pull from a text file and do more complex calculations, but at the moment I am just experimenting with tkinter and multiprocessing. I want each of the three labels(lbl1,lbl2,lbl3) to add 1,2,or 3 to their label and return that value. I am new to pipeing and events and dont understand the way to return the values to the synchronize the values so that they return to the correct places, so the output is random in accordance to the position in the grid. How can I make it so that anything I return only returns to the correct position in the grid which I have already specified?
import matplotlib.pyplot as plt
import socket, time, datetime, sys, struct
from datetime import datetime
import numpy as np
import shutil
import os
from random import randint
import Tkinter as tk
from multiprocessing import *
#from Tkinter import *
def count1(pipe,stop):
x = 0
while not stop.is_set():
x+=1
pipe.send(x)
time.sleep(1)
def count2(pipe,stop):
y = 0
while not stop.is_set():
y+=2
pipe.send(y)
time.sleep(1)
def count3(pipe,stop):
z = 0
while not stop.is_set():
z+=3
pipe.send(z)
time.sleep(1)
class UpdatingGUI(tk.Frame):
def __init__(self,parent):
tk.Frame.__init__(self,parent)
self.parent = parent
self.parent_pipe, self.child_pipe = Pipe()
self.stop_event = Event()
self.num1=tk.Label(self, text="Number 1")
self.num1.grid(row=0, column=0)
self.num2=tk.Label(self, text="Number 2")
self.num2.grid(row=0, column=1)
self.num3=tk.Label(self, text="Number 3")
self.num3.grid(row=0, column=2)
# label to show count value
self.updating_int1 = tk.IntVar()
self.updating_int1.set(0)
self.updating_lbl1 = tk.Label(self,textvariable=self.updating_int1)
self.updating_lbl1.grid(row=1, column=0)
self.updating_int2 = tk.IntVar()
self.updating_int2.set(0)
self.updating_lbl2 = tk.Label(self,textvariable=self.updating_int2)
self.updating_lbl2.grid(row=1, column=1)
self.updating_int3 = tk.IntVar()
self.updating_int3.set(0)
self.updating_lbl3 = tk.Label(self,textvariable=self.updating_int3)
self.updating_lbl3.grid(row=1, column=2)
# launch count as a process
self.counter1 = Process(target=count1,args=(self.child_pipe,self.stop_event))
self.counter1.start()
self.update()
self.counter2 = Process(target=count2,args=(self.child_pipe,self.stop_event))
self.counter2.start()
self.update()
self.counter3 = Process(target=count3,args=(self.child_pipe,self.stop_event))
self.counter3.start()
self.update()
def update(self):
# While the pipe has data, read and update the StringVar
while self.parent_pipe.poll():
self.updating_int1.set(self.parent_pipe.recv())
self.updating_int2.set(self.parent_pipe.recv())
self.updating_int3.set(self.parent_pipe.recv())
self.parent.after(1000,self.update)
def main():
root = tk.Tk()
root.geometry("400x200")
gui = UpdatingGUI(root)
gui.pack()
root.mainloop()
if __name__ == "__main__":
main()

Question: ... anything I return only returns to the correct position
Generalize your def count (..., to do so add a position Parameter.
For instance:
def count(position, pipe, stop):
x = 0
while not stop.is_set():
x += 1
pipe.send((position, x))
time.sleep(1)
def update(self):
# While the pipe has data, read and update the StringVar
while self.parent_pipe.poll():
position, data = self.parent_pipe.recv()
if position == 1:
self.updating_int1.set(data)
elif position == 2:
# and so on

Related

Getting input from another window in tkinter

I am having a little trouble with this project that I am working on. My project is this GUI application. In my test.py file, I call another file that contains instructions for another GUI window. This is where I am having trouble. In the test.py file, if you click run, a small window will appear. Click TEST in the small window. Then another window will appear that contains text fields if you enter numbers into the text fields for the window and then click enter. My IDE gets these error messages. It says that " ValueError: could not convert string to float: ' ' " My question is how do I fix this so that I do not get this error message? It is supposed to print the input that was entered into the window. I have two files, test.py, and model_objects.py. If you run model_objects.py by itself, it works perfectly. But when I try to import this file into test.py, it does not want to work right. This is programmed in Python. Also, my model_objects.py file is placed in a folder called util in the project. The values that I entered are floating-point values. I am having trouble with this. If you can help, I would greatly appreciate it.
Here is my code:
model_objects.py (This is in a folder called util in the project.)
import tkinter as tk
from tkinter import ttk
from tkinter.ttk import Style
import numpy as np
from util import InputData
class Harmonic_Oscillator:
def __init__(self):
self.type = 0
self.name = "Harmonic Oscillator"
self.nparam = 2
self.label = ["\u03BC", "k"]
self.param = np.zeros(self.nparam, float)
def set_param(self, param_list):
for i in range(self.nparam):
self.param[i] = param_list[i]
return
class Morse_Oscillator:
def __init__(self):
self.type = 1
self.name = "Morse Oscillator"
self.nparam = 3
self.label = ["\u03BC", "De", "a"]
self.param = np.zeros(self.nparam, float)
def set_param(self, param_list):
for i in range(self.nparam):
self.param[i] = param_list[i]
return
class Test_Oscillator:
def __init__(self):
self.type = 2
self.name = "Test Oscillator"
self.nparam = 4
self.mu = 0
self.label = ["a", "b", "c", "d"]
self.param = np.zeros(self.nparam, float)
def set_param(self, param_list):
for i in range(self.nparam):
self.param[i] = param_list[i]
return
def model_prompt(potential_model):
window1 = tk.Tk()
style = Style()
window1.title('PyFGH Parameters')
box_length = 103
for q in range(3):
box_length = box_length + 33 * potential_model[q].nparam
box_len_str = '300x' + str(box_length)
window1.geometry(box_len_str)
entries = []
qvar = np.empty(3, dtype=list)
for i in range(3):
qvar[i] = []
j = 0
y = 5
for q in range(3):
for qparam in range(potential_model[q].nparam):
qvar[q].append(tk.StringVar())
ttk.Label(window1, text=potential_model[q].label[qparam] + " for Q:" + str(q + 1) + ":",
font=("Times New Roman", 15)).place(x=50, y=y)
# set text variable as q1var[j] , each entry will have separate index in the list
a1 = ttk.Entry(window1, textvariable=qvar[q][qparam], font=("Times New Roman", 10)).place(x=140, y=y)
j += 1
y += 35
def enter_button():
for q in range(3):
param_list = []
for qparam in range(potential_model[q].nparam):
param_list.append(qvar[q][qparam].get())
potential_model[q].set_param(param_list) # This is giving me error. Not working properly!!!
for q in range(3):
for qparam in range(potential_model[q].nparam):
print(potential_model[q].param[qparam])
InputData.output.items.model_data = potential_model
print(InputData.output.items.model_data)
window1.destroy()
enter = tk.Button(window1, text='Enter', bd='20', bg='green', fg='white',
command=enter_button).place(x=110, y=y)
window1.mainloop()
def output2():
sections = []
for i in range(3):
if InputData.output.items.v[i] == "Model-Harmonic Oscillator":
sections.append(Harmonic_Oscillator())
elif InputData.output.items.v[i] == "Model-Morse Oscillator":
sections.append(Harmonic_Oscillator())
elif InputData.output.items.v[i] == "Model-Test Oscillator":
sections.append(Harmonic_Oscillator())
#test = [Harmonic_Oscillator(), Morse_Oscillator(), Test_Oscillator()]
#model_prompt(test)
Here is another file called test.py
from util import InputData
from util import model_objects
from util import model_objects
from util.model_objects import Harmonic_Oscillator, Morse_Oscillator, Test_Oscillator, model_prompt
import tkinter as tk
def write_slogan():
test = [Harmonic_Oscillator(), Morse_Oscillator(), Test_Oscillator()]
model_prompt(test)
root = tk.Tk()
frame = tk.Frame(root)
frame.pack()
button = tk.Button(frame,
text="QUIT",
fg="red",
command=quit)
button.pack(side=tk.LEFT)
slogan = tk.Button(frame,
text="TEST",
command=write_slogan)
slogan.pack(side=tk.LEFT)
root.mainloop()
It's a bit esoteric, but the issue is this line in your model_prompt function:
qvar[q].append(tk.StringVar())
The quick fix would be:
qvar[q].append(tk.StringVar(window1))
The tkinter variable types' constructors accept an optional parameter - a handle to the window to which the associated entry widget is attached. If none is supplied, by default, it will pick the first tk.Tk window that was instantiated (in your case, that was root in test.py). The StringVars will update themselves whenever the event queue of the bound window has cleared. Since you spawned a new tk.Tk, this interrupted your root event queue, and since your variables were bound to root, they did not update despite text being entered in the entries.
If you wanted to be super proper, you should look into tk.Toplevel or tkinter.simpledialog to spawn child windows. Your program should never have more than one tk.Tk window in the first place.
i made a little example, i hope it matches yourr mainproblem. if you want to work with classes, in the most cases you need references.
from tkinter import *
class MainWindow(Tk):
def __init__(self):
super(MainWindow, self).__init__()
self.test = Test(self) # test class import
self.outputLbl = Label(self) # output Label
self.outputLbl.pack(side="top", fill="x", ipady=20)
class Test(Frame):
def __init__(self, parent):
super(Test, self).__init__()
self.parent = parent # you can use this way to call between classes
self._input = Entry(self.parent)
self._input.pack()
self._input.bind("<Return>", self.outputMW)
def outputMW(self, event): # function, when pressing return it gives changes the text in your label
var = self._input.get()
self.parent.outputLbl.config(text=var) # self.parent makes the reference to your other class
if __name__ == '__main__':
mw = MainWindow()
mw.geometry("500x500")
mw.mainloop()

only last modification to Label being shown in Python - Tkinter . Why?

I am learning GUI development using Tkinter. I want to show multiple messages on the label which I have stored in a string. I used sleep to view the changes.However only the last message string is shown at execution.
from tkinter import *
import time
master = Tk()
def onClick():
for i in range(0,len(list_of_str)):
w.configure(text=list_of_str[i])
time.sleep(5)
list_of_str = ['first','second','third','fourth','fifth']
w = Label(master, text="Hello, world!")
b = Button(master,text='Click me',command = onClick)
w.pack()
b.pack()
mainloop()
I am a noobie. So thanks for helping !
A simple solution to your problem is to use a combination of the try/except method and using after().
In tkinter sleep() will pause the application instead of providing a timer. For tkinter you want to use the after() method to scheduled an event after a set amount of time instead. The after() method is meant for this exact problem and is what you will always use in tkinter for a delayed event.
In my below example I modified your onClick function to take 1 argument and to use that in our after() method to select the next item in the list after 5 seconds. Note that for the after() method time is done in milliseconds so 5000 is 5 seconds.
from tkinter import *
master = Tk()
def onClick(ndex):
try:
w.configure(text=list_of_str[ndex])
master.after(5000, onClick, ndex+1)
except:
print("End of list")
list_of_str = ['first','second','third','fourth','fifth']
w = Label(master, text="Hello, world!")
b = Button(master,text='Click me',command = lambda: onClick(0))
w.pack()
b.pack()
mainloop()
I think you want this:
from tkinter import *
import time
master = Tk()
global i
i = 0
def onClick():
master.after(1, change)
def change():
global i
if i == len(list_of_str):
pass
else:
w.configure(text=list_of_str[i])
i += 1
master.after(1000, onClick)
list_of_str = ['first','second','third','fourth','fifth']
w = Label(master, text="Hello, world!")
b = Button(master,text='Click me',command = onClick)
w.pack()
b.pack()
mainloop()
time.sleep is a no-no in tkinter. I advise you make your gui in a class and it wil be easier.
example with class:
import tkinter as tk
from tkinter import *
class GUI:
def __init__(self, master):
self.list_of_str = ['first','second','third','fourth','fifth']
self.count = 0
self.master = master
self.w = Label(master, text="Hello, world!")
self.w.pack()
self.b = Button(master,text='Click me',command = self.onClick)
self.b.pack()
def onClick(self, event=None):
if self.count == len(self.list_of_str):
pass
else:
self.w.configure(text=self.list_of_str[self.count])
self.count += 1
self.master.after(1000, self.onClick)
def main():
root = tk.Tk()
app = GUI(root)
root.mainloop()
if __name__ == '__main__':
main()

update the maximum value of ttk.Progressbar

I am struggling with a seemingly simple problem: I want to be able to update the maximum value of a progress bar in tkinter by manually changing the value of an entry. What happens is that the initial value, 100, does not change. OK, I thought that by invoking set in the method count I would be able to update the maximum value. It didn't work. What is the problem?
import tkinter as tk
from tkinter import ttk
from time import sleep
class Window():
def __init__(self, master):
self.master = master
self.configure()
self.create_widgets()
def configure(self):
self.master.title('Progress bar')
self.master.minsize(height=100, width=500)
def create_widgets(self):
self.progress = tk.DoubleVar()
self.number = tk.StringVar()
self.number.set('100')
self.max = tk.IntVar()
self.max.set(eval(self.number.get()))
b1 = tk.Button(self.master, text='Count!', command=self.count)
b1.pack()
e1 = tk.Entry(self.master, textvariable=self.number, width=5)
e1.pack()
p = ttk.Progressbar(self.master, orient='horizontal', length=200, mode='determinate', variable=self.progress, value=1, maximum=self.max.get())
p.pack()
def count(self):
self.max.set(eval(self.number.get()))
for i in range(eval(self.number.get())):
sleep(0.01)
print(i)
self.progress.set(i)
self.master.update()
def main():
root = tk.Tk()
app = Window(root)
root.mainloop()
main()
You're struggling probably because you've overcomplicated the issue. Why do you use 3 separate Variable classes when you need none? Currently what happens is you create a progress bar with a static maximum of 100, and then you're changing how long to progress in that window by setting the entry's value.
Here's a minimal example that updates the maximum value of progress bar:
try: # In order to be able to import tkinter for
import tkinter as tk # either in python 2 or in python 3
import tkinter.ttk as ttk
except ImportError:
import Tkinter as tk
import ttk
class RestartableProgress(tk.Frame):
def __init__(self, master, *args, **kwargs):
tk.Frame.__init__(self, master, *args, **kwargs)
self.max_input = tk.Entry(self)
self.restart_button = tk.Button(self, text="Restart",
command=self.restart)
self.progressbar = ttk.Progressbar(self)
self.max_input.pack()
self.restart_button.pack()
self.progressbar.pack()
def restart(self):
self.progressbar['value'] = 0
self.progress()
def progress(self):
max_val = self.max_input.get()
if max_val:
self.progressbar['maximum'] = int(max_val)
if self.progressbar['value'] < self.progressbar['maximum']:
self.progressbar['value'] += 1
self.after(10, self.progress)
def main():
root = tk.Tk()
rp = RestartableProgress(root)
rp.pack()
tk.mainloop()
if __name__ == '__main__':
main()

Label Is Not Shown When Called From Other Tkinter Program

I was writing a program with a start page, and two programs that are called from that start page. Both of the subprograms work by themselves. However, when I put them into my start page, the stopwatch timing label doesn't show up. If you are wondering, I put them into my program by doing:
import program
program.function()
Here is my start page program:
from Tkinter import *
class start_page:
def __init__(self,master):
self.master = master
self.frame = Frame(self.master)
self.countdown = Button(master, text = "Timer", command = self.c).pack()
self.stopwatch_butt = Button(master,text="Stopwatch",command=self.g).pack()
def g(self):
import stopwatch
stopwatch.f()
def c(self):
import timer_prog
timer_prog.timer()
self.master.after_cancel(timer_prog)
def main():
root = Tk()
s = start_page(root)
root.title("Timer Suite: Brian Ton")
root.mainloop()
main()
If I run this program, the timer program works fine, but the stopwatch doesn't show its label, only its buttons. I tried to clear all Tk after functions, and that didn't work, and I also tried to run the stopwatch program first, to no avail.
Here is my stopwatch program:
from Tkinter import *
import datetime
def s():
start.config(state='disabled')
stop.config(state="normal")
reset.config(state='disabled')
Start()
def Start():
if reset['state'] == 'disabled' and stop['state'] == 'normal':
hidden.set(str(int(hidden.get())+1))
root.update()
root.after(1000,Start)
curr = hidden.get()
g.set(str(datetime.timedelta(seconds=int(curr))))
print g.get()
else:
return None
def Stop():
start.config(state='disabled')
stop.config(state='disabled')
reset.config(state="normal")
def Reset():
start.config(state="normal")
stop.config(state="disabled")
reset.config(state='disabled')
hidden.set('0')
g.set(str(datetime.timedelta(seconds=0)))
def f():
global root,frame,master,hidden,g,timelabel,start,stop,reset
root = Tk()
frame = Frame(root)
master = root
hidden = StringVar()
g = StringVar()
hidden.set('0')
timelabel = Label(master,textvariable=g)
g.set(str(datetime.timedelta(seconds=int(0))))
timelabel.grid(row=1,column=2)
start = Button(master,text="Start",command = s,state="normal")
stop = Button(master,text="Stop",command = Stop,state = "disabled")
reset = Button(master,text="Reset",command = Reset,state = "disabled")
start.grid(row=2,column=1)
stop.grid(row=2,column=2)
reset.grid(row=2,column=3)
root.update()
root.mainloop()
And here is my timer program:
from Tkinter import *
import datetime
def get_seconds(h,m,s):
hr_sec = h * 3600
m_sec = m * 60
return hr_sec+m_sec+s
def timerstartstop():
hours = hour_entry.get()
minutes = minute_entry.get()
sec = second_entry.get()
if hours == "":
hours = 0
hour_entry.insert(0,"0")
if minutes == "":
minutes = 0
minute_entry.insert(0,"0")
if sec == "":
sec = 0
second_entry.insert(0,"0")
c = get_seconds(int(hours), int(minutes), int(sec))
global s
s = StringVar(master)
s.set(c)
if startstop['text'] == 'Stop':
global curr
curr = shown
s.set(-1)
if startstop['text'] == 'Reset':
startstop.config(text="Start")
s.set(c)
root.update()
shown.set(str(datetime.timedelta(seconds=int(s.get()))))
return None
countdown()
import winsound
def countdown():
startstop.config(text="Stop")
global shown
good = True
shown = StringVar(master)
shown.set(str(datetime.timedelta(seconds=int(s.get()))))
L = Label(master,textvariable=shown).grid(row=1,column=2)
if int(s.get()) == 0:
startstop.config(text="Reset")
while startstop['text'] != "Start":
root.update()
winsound.Beep(500,500)
elif int(s.get()) < 0:
good = False
shown.set(curr.get())
startstop.config(text="Reset")
else:
if good:
s.set(str(int(s.get())-1))
root.after(1000,countdown)
def ex():
root.after_cancel(countdown)
root.destroy()
def timer():
global root
global master
global frame
root = Tk()
master = root
frame = Frame(master)
global hour_entry
hour_entry = Entry(master,width=3)
hour_entry.grid(row=0,column=0)
colon_l = Label(master,text=':').grid(row=0,column=1)
global minute_entry
minute_entry = Entry(master,width=2)
minute_entry.grid(row=0,column=2)
colon_l2 = Label(master,text=':').grid(row=0,column=3)
global second_entry
second_entry = Entry(master,width=2)
second_entry.grid(row=0,column=4)
global startstop
startstop = Button(master,text="Start",command=timerstartstop)
e = Button(master,text="Exit",command=ex).grid(row=1,column=3)
startstop.grid(row=0,column=5)
root.mainloop()
In addition, I tried to run these two programs from a different starting menu that used the console, which worked.
The console program is:
import timer_prog
timer_prog.timer()
raw_input('next')
import stopwatch
stopwatch.f()
Attached are some screenshots of what the stopwatch program should look like vs what it does look like when called from the starting program.
Note: I can tell the program is running from the starting page, as it prints the current time each second. Also, I attached some screenshots
Stopwatch Program Run Directly
Stopwatch Program Run From The Start Page
Tkinter program should use only one Tk() - to create main window - and one mainloop() - to control all windows and widgets. If you use two Tk() and two mainloop() then it has problem - for example get()/set() may not work.
Subwindows should use Toplevel() instead of Tk().
Function which starts program (ie. run()) could run with parameter window (def run(window)) and then you can execute it as standalone program with
root = Tk()
run(root)
root.mainloop()
or after importing
run(Toplevel())
(without maniloop())
You can use if __name__ == "__main__" to recognize if program starts as standalone.
Example
main.py
from Tkinter import *
class StartPage:
def __init__(self, master):
self.master = master
master.title("Timer Suite: Brian Ton")
Button(master, text="Timer", command=self.run_timer).pack()
Button(master, text="Stopwatch", command=self.run_stopwatch).pack()
def run_stopwatch(self):
import stopwatch
window = Toplevel()
stopwatch.run(window)
def run_timer(self):
import timer_prog
window = Toplevel()
timer_prog.timer(window)
self.master.after_cancel(timer_prog)
def main():
root = Tk()
StartPage(root)
root.mainloop()
main()
stopwatch.py
from Tkinter import *
import datetime
def pre_start():
start_button.config(state='disabled')
stop_button.config(state='normal')
reset_button.config(state='disabled')
start()
def start():
global current_time
# stop_button['state'] can be 'normal' or 'active' so better use ` != 'disabled'`
if reset_button['state'] == 'disabled' and stop_button['state'] != 'disabled':
current_time += 1
time_var.set(str(datetime.timedelta(seconds=current_time)))
print(time_var.get())
master.after(1000, start)
def stop():
start_button.config(state='disabled')
stop_button.config(state='disabled')
reset_button.config(state='normal')
def reset():
global current_time
start_button.config(state='normal')
stop_button.config(state='disabled')
reset_button.config(state='disabled')
current_time = 0
time_var.set(str(datetime.timedelta(seconds=0)))
def run(window):
global master
global current_time, time_var
global start_button, stop_button, reset_button
master = window
current_time = 0
time_var = StringVar()
time_var.set(str(datetime.timedelta(seconds=0)))
time_label = Label(window, textvariable=time_var)
time_label.grid(row=1, column=2)
start_button = Button(master, text='Start', command=pre_start, state='normal')
stop_button = Button(master, text='Stop', command=stop, state='disabled')
reset_button = Button(master, text='Reset', command=reset, state='disabled')
start_button.grid(row=2, column=1)
stop_button.grid(row=2, column=2)
reset_button.grid(row=2, column=3)
if __name__ == '__main__':
# it runs only in standalone program
root = Tk()
run(root)
root.mainloop()

Python TKinter GUI updates from multiple threads -- is it thread-safe? Some example code

I've been doing some research on this one issue I've been having with TKinter, which is updating the GUI based on data from other threads. As many have suggested online, I resorted to using the queue polling strategy with the self.root.after() method.
This works pretty well, but I have a problem in which I need to update matplotlib plots embedded in a TKinter GUI, and doing so "deactivates" / draws focus away from / perhaps blocks the other aspects of the GUI. Specifically, if I'm typing something in a TKinter entry and the matplotlib figure updates, the cursor is no longer in the entry and my typing process has been interrupted.
To solve this issue, I figured I'd try to update TKinter in a separate thread altogether. Now, I have seen online many people who claim that TKinter is not thread-safe, but I have also seen others who say it is thread-safe. I went ahead and made an example program, which seems to run pretty well: the cursor can remain in the entry even when the plot updates. But what I'd like to know is, is this program safe? Or is it susceptible to failures, random or predictable? What can I do to have a thread-safe GUI?
Here's my example code:
import Tkinter as tk
import threading
import Queue
import datetime
import math
import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
import matplotlib.gridspec as gridspec
gui_queue = Queue.Queue()
GUI_THEME_COLOR = 'lightblue'
##################################################
class MainGUI:
def __init__(self, root):
self.root = root
self.root.title('TKinter GUI with Threaded Updates')
self.root.minsize(width=800, height=300)
self.root.config(background=GUI_THEME_COLOR)
self.big_frame = tk.Frame(master=root)
self.big_frame.pack(fill=tk.BOTH, expand=tk.YES, padx=10, pady=10)
self.button1 = tk.Button(master=self.big_frame, text='Button 1', command=self.button1_command)
self.button1.grid(row=0, column=0)
self.entry1 = tk.Entry(master=self.big_frame)
self.entry1.bind('<Return>', self.entry1_event)
self.entry1.grid(row=1, column=0)
def entry1_event(self, event):
self.button1.config(text=str(self.entry1.get()))
self.entry1.delete(0, tk.END)
def button1_command(self):
print 'Button 1 clicked'
class GUIManipulator(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.app = None
self.start_time = datetime.datetime.utcnow()
self.sec_checker = 1
self.num_loops = 0
self.x_list = []
self.y_list = []
def run(self):
print 'Starting GUIManipulator thread...'
while gui_queue.empty(): # Wait here until we receive the MainGUI instance
pass
self.app = gui_queue.get()
while True:
diff_time = (datetime.datetime.utcnow() - self.start_time).total_seconds()
floor_diff_time = math.floor(diff_time)
if floor_diff_time >= self.sec_checker: # Configure button1 text every second
self.app.button1.config(text=str(floor_diff_time))
self.sec_checker += 1
self.plot_figure()
def plot_figure(self):
self.num_loops += 1
self.x_list.append(self.num_loops)
self.y_list.append(math.sin(self.num_loops/5.0))
if self.num_loops == 1:
self.fig1 = Figure(figsize=(12, 6), facecolor=GUI_THEME_COLOR)
self.fig1.suptitle('Figure 1',
fontsize=14,
fontweight='bold')
self.gs = gridspec.GridSpec(2, 2)
self.plot1 = self.fig1.add_subplot(self.gs[:, 0])
self.plot1.set_title('Plot 1')
self.plot1.set_xlabel('x')
self.plot1.set_ylabel('sin(x)', labelpad=-10)
self.plot1.grid(True)
if self.num_loops > 1:
self.plot1.cla()
self.plot1.plot(self.x_list, self.y_list)
if self.num_loops == 1:
self.canvas = FigureCanvasTkAgg(self.fig1, master=self.app.big_frame)
self.canvas.draw()
self.canvas.get_tk_widget().grid(row=2, column=0)
else:
self.canvas.draw()
def main():
root = tk.Tk()
app = MainGUI(root)
gui_queue.put(app)
gui_manipulator_thread = GUIManipulator()
gui_manipulator_thread.daemon = True
gui_manipulator_thread.start()
root.mainloop()
if __name__ == '__main__':
main()

Categories