gpt4 book ai didi

python - Tkinter 窗口与线程不能很好地配合

转载 作者:行者123 更新时间:2023-12-01 05:09:36 25 4
gpt4 key购买 nike

我有一个程序,最终将通过串行方式从外部源接收数据,但我正在尝试首先开发显示端。

我有这个“主”模块,它具有模拟数据发送和接收的功能。它更新 Matplotlib 带状图使用的全局变量。所有这些都有效。

#-------------------------------------------------------------------------------
# Name: BBQData
# Purpose: Gets the data from the Arduino, and runs the threads.
#-------------------------------------------------------------------------------
import time
import math
import random
from threading import Thread
import my_globals as bbq
import sys
import BBQStripChart as sc
import serial
import BBQControl as control


ser = serial.serial_for_url('loop://', timeout=10)

def simData():
newTime = time.time()
if not hasattr(simData, "lastUpdate"):
simData.lastUpdate = newTime # it doesn't exist yet, so initialize it
simData.firstTime = newTime # it doesn't exist yet, so initialize it
if newTime > simData.lastUpdate:
simData.lastUpdate = newTime
return (140 + 0.05*(simData.lastUpdate - simData.firstTime), \
145 + 0.022*(simData.lastUpdate - simData.firstTime), \
210 + random.randrange(-10, 10))
else:
return None

def serialDataPump():
testCtr = 0;
while not bbq.closing and testCtr<100:
newData = simData()
if newData != None:
reportStr = "D " + "".join(['{:3.0f} ' for x in newData]) + '\n'
reportStr = reportStr.format(*newData)
ser.write(bytes(reportStr, 'ascii'))
testCtr+=1
time.sleep(1)
bbq.closing = True

def serialDataRcv():
while not bbq.closing:
line = ser.readline()
rcvdTime = time.time()
temps = str(line, 'ascii').split(" ")
temps = temps[1:-1]
for j, x in enumerate(temps):
bbq.temps[j].append(float(x))
bbq.plotTimes.append(rcvdTime)

def main():
sendThread = Thread(target = serialDataPump)
receiveThread = Thread(target = serialDataRcv)
sendThread.start()
receiveThread.start()
# sc.runUI()
control.runControl() #blocks until user closes window
bbq.closing = True
time.sleep(2)
exit()


if __name__ == '__main__':
main()
## testSerMain()

但是,我想添加一个单独的 tkinter 窗口,其中仅包含最新数据、关闭按钮等。我可以让该窗口出现,并最初显示数据,但没有其他窗口线程运行。 (当我尝试同时运行窗口和绘图时,没有任何效果。)

#-------------------------------------------------------------------------------
# Name: BBQ Display/Control
# Purpose: displays current temp data, and control options
#-------------------------------------------------------------------------------

import tkinter as tk
import tkinter.font
import my_globals as bbq
import threading

fontSize = 78

class BBQControl(tk.Tk):
def __init__(self,parent):
tk.Tk.__init__(self,parent)
self.parent = parent
self.labelFont = tkinter.font.Font(family='Helvetica', size=int(fontSize*0.8))
self.dataFont = tkinter.font.Font(family='Helvetica', size=fontSize, weight = 'bold')
self.makeWindow()


def makeWindow(self):
self.grid()

btnClose = tk.Button(self,text=u"Close")
btnClose.grid(column=1,row=5)

lblFood = tk.Label(self,anchor=tk.CENTER, text="Food Temps", \
font = self.labelFont)
lblFood.grid(column=0,row=0)
lblPit = tk.Label(self,anchor=tk.CENTER, text="Pit Temps", \
font = self.labelFont)
lblPit.grid(column=1,row=0)

self.food1Temp = tk.StringVar()
lblFoodTemp1 = tk.Label(self,anchor=tk.E, \
textvariable=self.food1Temp, font = self.dataFont)
lblFoodTemp1.grid(column=0,row=1)

#spawn thread to update temps
updateThread = threading.Thread(target = self.updateLoop)
updateThread.start()

def updateLoop(self):
self.food1Temp.set(str(bbq.temps[1][-1]))

def runControl():
app = BBQControl(None)
app.title('BBQ Display')
app.after(0, app.updateLoop)
app.mainloop()
bbq.closing = True

if __name__ == '__main__':
runControl()

最佳答案

你的标题很好地总结了这个问题:Tkinter 不能很好地处理线程。这不是问题,这就是答案。

您只能从创建小部件的同一线程访问 tkinter 小部件。如果您想使用线程,则需要非 gui 线程将数据放入队列,并让 gui 线程定期轮询队列。

关于python - Tkinter 窗口与线程不能很好地配合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24459886/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com