问题描述
我制作了一个使用while True循环的脚本,该脚本根据我不断收到的UDP数据包不断更新一系列变量.我最终想要创建一个显示数据并不断更新屏幕的GUI,我计划使用tkinter进行此操作(在函数中使用my_label.after进行调用,然后调用自身,不确定这是否是一个好的计划).>
以下是一些我无法正常使用的测试脚本:
GUI2.py(我的测试循环脚本)
导入时间var = 0而True:var + = 1time.sleep(0.1)
GUI Testing.py(将访问这些变量的脚本)
从GUI2导入 *导入时间打印('从不')打印(var)time.sleep(1)
我认为第二个脚本永远不会到达print('never')行,因为它在True循环时卡在另一个脚本的行中,并且永不返回.
我应该怎么做?我有一个脚本希望以恒定循环的形式根据传入的数据包将变量更新为正确的值,然后有另一个脚本更新tkinter窗口.我采用这种方式,是因为使用Tkinter可以找到的大多数示例都没有使用任何类型的while True循环.我可以将接收数据包的代码放在Tkinter主循环中,这样可以有效地充当True吗?
编辑(添加了我无法使用的Tkinter循环):
这将打开一个Tkinter窗口,但标签停留在99,然后当我使用新的x值(即98、97等)关闭该窗口时,重新打开一个窗口.我希望标签每秒更新一次.
将tkinter导入为tk导入时间x = 99而True:根= tk.Tk()标签= tk.Label(root,text = x)label.pack()x-= 1time.sleep(1)root.mainloop()
下面是一个示例脚本,向您展示如何在特定时间间隔内更新标签小部件中的值.我为您提供了超链接,以帮助您了解tkinter的方法.最好的问候.
要点:
- 使用 textvariable 选项> tk.Label小部件.
- 使用 tkinter的控制变量.我已经向您展示了如何设置和获取其价值.
- 您可以使用名为
的tkinter的小部件方法.after()
,而不必显式使用while语句和time.sleep()
方法.Tkinter具有自己的事件循环,您可以使用. - 将tkinter GUI编写为类可以更轻松地实现所需的内容.
示例脚本:
将tkinter导入为tkApp(tk.Frame)类:def __init __(self,master,* args,** kw):super().__ init __(master)self.master =主self.create_label()self.update_label()def create_label(self):self.var = tk.IntVar()#持有一个int;默认值 0self.label = tk.Label(self,textvariable = self.var)#使用textvariable而不是textself.label.pack()def update_label(self):值= self.get_value()self.var.set(value)#设置标签控件的文本变量值.self.after(1000,self.update_label)#在1000毫秒后调用此方法.def get_value(self):'''模拟调用函数以返回值'''值= self.var.get()+ 1返回值如果__name__ =="__main__":根= tk.Tk()root.geometry('100x100+0+24')app = App(root)app.pack()root.mainloop()#此命令激活tkinter的事件循环
- 为澄清起见,此答案显示了如何利用
GUI Testing.py
中的.after()
和.mainloop()
方法,即使用tkinter事件循环而不使用两个while循环来实现您想要的操作.这是一种简化GUI脚本的方法. - 对于更复杂的算法,例如涉及多个循环,您必须研究使用线程(注意存在问题),或者最近我发现了一种使用python的Asyncio方法进行操作的方法.这两种方法的学习曲线要陡得多.要使用异步方法,您可以探索修改我的 answer 以完成您想要的事情.
I've made a script that uses a while True loop to constantly update a series of variables based on UDP packets that I am constantly recieving. I want to ultimately create a GUI that displays that data and updates the screen constantly, which I plan to do with tkinter (using my_label.after in a function which then calls itself, not sure if this is a good plan).
Here is some testing scripts that I can't get to work properly:
GUI2.py (my test looping script)
import time
var = 0
while True:
var += 1
time.sleep(0.1)
GUI Testing.py (the script that would be accessing those variables)
from GUI2 import *
import time
print('never')
print(var)
time.sleep(1)
The second script never reaches the print('never') line, I think because it gets stuck in the other script's while True loop and never returns.
How should I go about this? I have one script that I want in a constant loop to update my variables to the correct values based on incoming packets, and then another script updating a tkinter window. I went this way as most examples I could find using Tkinter didn't use any sort of while True loops. Could I just put my packet recieving code inside the Tkinter mainloop, and would that effectively act as a while True?
EDIT (added Tkinter loop that I can't get working):
This opens a Tkinter window, but the label stays at 99, then reopens a window when I close it with the new x value (ie. 98, 97, etc). I want the label to update every second.
import tkinter as tk
import time
x = 99
while True:
root = tk.Tk()
label = tk.Label(root, text=x)
label.pack()
x -= 1
time.sleep(1)
root.mainloop()
Below is a sample script to show you how you can update the value in the label widget at a certain time interval. I have provided you the hyperlinks to help you understand tkinter's methods. Best regards.
Key points:
- use the
textvariable
option of the tk.Label widget. - use tkinter's control variable. I have shown you how to set and get it's value.
- you can use tkinter's widget method called
.after()
without having to explicitly use a while-statement andtime.sleep()
method. Tkinter has it's own event loop that you can use. - writing your tkinter GUI as a class makes it easier to implement what you need.
Example Script:
import tkinter as tk
class App(tk.Frame):
def __init__( self, master, *args, **kw ):
super().__init__( master )
self.master = master
self.create_label()
self.update_label()
def create_label( self ):
self.var = tk.IntVar() # Holds an int; default value 0
self.label = tk.Label(self, textvariable=self.var ) # Use textvariable not text
self.label.pack()
def update_label( self ):
value = self.get_value()
self.var.set( value ) # Set the label widget textvariable value.
self.after(1000, self.update_label) # Call this method after 1000 ms.
def get_value( self ):
'''To simulate calling a function to return a value'''
value = self.var.get() + 1
return value
if __name__ == "__main__":
root = tk.Tk()
root.geometry('100x100+0+24')
app = App( root )
app.pack()
root.mainloop() #This command activates tkinter's event loop
Edit:
- As a clarification, this answer shows how to utilize the
.after()
and.mainloop()
methods inGUI Testing.py
, i.e. using tkinter event loop and not use two while-loops, to achieve what you wanted to do. This is a way to simplify your GUI script. - For more sophisticated algorithms, e.g. more than one while-loop is involved, you have to look into using threads(note it has its issues) or more recently I found a way of using python's Asyncio approach to do it. The learning curve for these two approaches is a lot steeper. To use the asyncio approach, you can explore modifying my answer to do what you want.
这篇关于Python:如何从不断更新的另一个脚本中获取变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!