gpt4 book ai didi

python - 如何使 Tkinter GUI 线程安全?

转载 作者:太空宇宙 更新时间:2023-11-04 00:05:33 25 4
gpt4 key购买 nike

我写了一段代码,其中有一个带 Canvas 的简单 GUI。在这个 Canvas 上我画了一个 Matplot。 Matplot 每秒更新一次来自 SQ Lite DB 的数据,我填充了一些虚假的传感器信息(目前仅用于测试)。

我的问题是 Canvas 的重绘导致我的窗口/GUI 每秒都滞后。我什至试图在另一个线程中更新情节。但即使在那里我也有滞后。

使用我的最新代码,我的大部分工作都正常进行了。线程有助于防止我的 GUI/窗口在更新 Canvas 时卡住。

我想念的最后一件事是让它成为线程安全的。

这是我收到的消息:

RuntimeError: main thread is not in main loop

这是我最新的线程代码:

from tkinter import *
import random
from random import randint
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import time
import threading
from datetime import datetime

continuePlotting = False

def change_state():
global continuePlotting
if continuePlotting == True:
continuePlotting = False
else:
continuePlotting = True

def data_points():
yList = []
for x in range (0, 20):
yList.append(random.randint(0, 100))

return yList

def app():
# initialise a window and creating the GUI
root = Tk()
root.config(background='white')
root.geometry("1000x700")

lab = Label(root, text="Live Plotting", bg = 'white').pack()

fig = Figure()

ax = fig.add_subplot(111)
ax.set_ylim(0,100)
ax.set_xlim(1,30)
ax.grid()

graph = FigureCanvasTkAgg(fig, master=root)
graph.get_tk_widget().pack(side="top",fill='both',expand=True)

# Updated the Canvas
def plotter():
while continuePlotting:
ax.cla()
ax.grid()
ax.set_ylim(0,100)
ax.set_xlim(1,20)

dpts = data_points()
ax.plot(range(20), dpts, marker='o', color='orange')
graph.draw()
time.sleep(1)

def gui_handler():
change_state()
threading.Thread(target=plotter).start()

b = Button(root, text="Start/Stop", command=gui_handler, bg="red", fg="white")
b.pack()

root.mainloop()

if __name__ == '__main__':
app()

这里没有线程的想法:

from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import tkinter as tk
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import sqlite3
from datetime import datetime
from random import randint

class MainApplication(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.parent = parent

root.update_idletasks()

f = Figure(figsize=(5,5), dpi=100)
x=1
ax = f.add_subplot(111)
line = ax.plot(x, np.sin(x))

def animate(i):
# Open Database
conn = sqlite3.connect('Sensor_Data.db')
c = conn.cursor()
# Create some fake Sensor Data
NowIs = datetime.now()
Temperature = randint(0, 100)
Humidity = randint(0, 100)
# Add Data to the Database
c = conn.cursor()
# Insert a row of data
c.execute("insert into Sensor_Stream_1 (Date, Temperature, Humidity) values (?, ?, ?)",
(NowIs, Temperature, Humidity))
# Save (commit) the changes
conn.commit()
# Select Data from the Database
c.execute("SELECT Temperature FROM Sensor_Stream_1 LIMIT 10 OFFSET (SELECT COUNT(*) FROM Sensor_Stream_1)-10")
# Gives a list of all temperature values
x = 1
Temperatures = []

for record in c.fetchall():
Temperatures.append(str(x)+','+str(record[0]))
x+=1
# Setting up the Plot with X and Y Values
xList = []
yList = []

for eachLine in Temperatures:
if len(eachLine) > 1:
x, y = eachLine.split(',')
xList.append(int(x))
yList.append(int(y))

ax.clear()

ax.plot(xList, yList)

ax.set_ylim(0,100)
ax.set_xlim(1,10)
ax.grid(b=None, which='major', axis='both', **kwargs)


label = tk.Label(root,text="Temperature / Humidity").pack(side="top", fill="both", expand=True)

canvas = FigureCanvasTkAgg(f, master=root)
canvas.get_tk_widget().pack(side="left", fill="both", expand=True)

root.ani = animation.FuncAnimation(f, animate, interval=1000)

if __name__ == "__main__":
root = tk.Tk()
MainApplication(root).pack(side="top", fill="both", expand=True)
root.mainloop()

这是我的数据库架构:

CREATE TABLE `Sensor_Stream_1` (
`Date` TEXT,
`Temperature` INTEGER,
`Humidity` INTEGER
);

最佳答案

您的 GUI 进程不得在任何线程中运行。只有数据采集必须是线程化的。

当需要时,将获取的数据传输到 gui 进程(或从新数据可用通知的 gui 进程)。我可能需要使用互斥锁在获取线程和 gui 之间共享数据资源(复制时)

主循环看起来像:

running = True
while running:
root.update()
if data_available:
copydata_to_gui()
root.quit()

关于python - 如何使 Tkinter GUI 线程安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54237067/

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