Я пытаюсь создать графический интерфейс, который постоянно отображает сигнал, полученный от микропроцессора. Я пытался сделать это, используя только классы, но это не удалось, поскольку был открыт только класс GUI. Теперь я реализовал многопоточность (или, по крайней мере, я так думаю!?), но каждый поток запускается только один раз. что заставляет меня поверить, что я не понимаю, как работает основной цикл в tkinter, поэтому могу ли я переделать свой код так, чтобы потоки стали активными?
import Tkinter
import tkMessageBox as messagebox
from serial import *
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import numpy as np
import time
import threading
go=0
x=[0.0001,0.0002,0.0003]
y=[3600,1000,2000]
stid=time.time()
root = Tkinter.Tk()
root.title("Serial gui")
class SensorThread(threading.Thread):
def run(self):
global run
global x
global y
global stid
print "run er ok"
if go==1:
print "go er ok"
ser = Serial(5, 9600, timeout=1)
f=ser.read(4)
ser.close()
x.append(time.time()-stid)
y.append(f)
class Foo:
def __init__(self, master):
print "foo ok"
frame = Tkinter.Frame(root)
self.button_left = Tkinter.Button(frame,text="Start",
command=self.start)
self.button_left.pack(side="left")
self.button_right = Tkinter.Button(frame,text="Stop",
command=self.stop)
self.button_right.pack(side="right")
self.button_midt = Tkinter.Button(frame, text='Quit', command=self.terminate)
self.button_midt.pack(side="bottom")
fig = Figure()
ax = fig.add_subplot(111, axisbg='black')
canvas = FigureCanvasTkAgg(fig,master=master)
canvas.show()
canvas.get_tk_widget().pack(side='top', fill='both', expand=1)
frame.pack()
line1, = ax.plot(x, y, 'r-') # Returns a tuple of line objects, thus the comma
line1.set_ydata(y)
fig.canvas.draw()
def start(self):
global go
go=1
print go
def stop(self):
global go
go=0
print go
def terminate(self):
root.quit() # stops mainloop
root.destroy() # this is necessary on Windows to prevent
# Fatal Python Error: PyEval_RestoreThread: NULL tstate
if __name__ == "__main__":
SensorThread().run()
Foo(root)
root.mainloop()
Я надеюсь, что некоторые из вас помогут мне превратить этот код в программу, которая обновляет сюжет в реальном времени.
Супер, я изменил следующее в программе,
class SensorThread(threading.Thread):
def run(self):
global run
global x
global y
global stid
#print "run er ok"
if go==1:
print "go er ok"
ser = Serial(17, 9600, timeout=1)
f=ser.read(4)
ser.close()
x.append(time.time()-stid)
y.append(f)
SensorThread().start()
else:
SensorThread().start()
class Foo:
....
if __name__ == "__main__":
SensorThread().start()
Foo(root)
root.mainloop()
но он по-прежнему не обновляет фигуру, которую рисуют, разве это не должно делать это в классе Foo? Кроме того, теперь, когда я выхожу из скрипта Python, он по-прежнему использует 50% мощности ЦП, вероятно, потому, что поток датчиков теперь работает вечно!?
threading
; вы должны звонить не.run()
, а.start()
. Подробнее см. docs.python.org/2/library/threading.html. Информация. - person mmgp   schedule 23.01.2013start
внутри методаrun
:/ Здесь есть пара недоразумений. Например, вы вызываетеplot
только один раз внутри__init__
; почему вы ожидали, что сюжет будет обновляться автоматически, просто потому, что вы изменили списки /после того, как сюжет был выполнен, и никогда не обновляли его снова? - person mmgp   schedule 23.01.2013after
. - person Bryan Oakley   schedule 05.11.2014