【问题标题】:Python: How do you obtain variables from another script which are constantly being updatedPython:如何从另一个不断更新的脚本中获取变量
【发布时间】:2020-07-19 17:13:02
【问题描述】:

我制作了一个脚本,该脚本使用 while True 循环根据我不断收到的 UDP 数据包不断更新一系列变量。我想最终创建一个显示该数据并不断更新屏幕的 GUI,我打算用 tkinter 来做这件事(在一个函数中使用 my_label.after 然后调用自身,不确定这是否是一个好计划)。

这是一些我无法正常工作的测试脚本:

GUI2.py(我的测试循环脚本)

import time
var = 0
while True:
   var += 1
   time.sleep(0.1)

GUI Testing.py(将访问这些变量的脚本)

from GUI2 import *
import time
print('never')
print(var)
time.sleep(1)

我认为第二个脚本永远不会到达 print('never') 行,因为它卡在另一个脚本的 while True 循环中并且永远不会返回。

我应该怎么做?我有一个脚本,我希望在一个恒定循环中根据传入的数据包将我的变量更新为正确的值,然后另一个脚本更新一个 tkinter 窗口。我这样做是因为我可以找到使用 Tkinter 的大多数示例都没有使用任何类型的 while True 循环。我可以将我的数据包接收代码放在 Tkinter 主循环中吗?这样会有效地充当 while True 吗?

EDIT(添加了我无法工作的 Tkinter 循环):

这会打开一个 Tkinter 窗口,但标签保持在 99,然后当我用新的 x 值(即 98、97 等)关闭它时重新打开一个窗口。我希望标签每秒更新一次。

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()

【问题讨论】:

  • 陷入无限循环的 IMO 得分为 10,评分为 0-10 的不良进口副作用。您应该使用if __name__ == "__main__": 成语。 (这只是一个评论,它并不能解决你的问题)

标签: python loops variables tkinter


【解决方案1】:

下面是一个示例脚本,向您展示如何以特定时间间隔更新标签小部件中的值。我为您提供了超链接以帮助您了解 tkinter 的方法。最好的问候。

关键点:

  • 使用tk.Label widgettextvariable 选项。
  • 使用tkinter's control variable。我已经向您展示了如何设置和获取它的值。
  • 您可以使用名为.after() 的tkinter 小部件方法,而无需显式使用while 语句和time.sleep() 方法。 Tkinter 有它自己的事件循环供你使用。
  • 将您的 tkinter GUI 编写为一个类可以更轻松地实现您需要的功能。

示例脚本:

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

编辑:

  • 作为澄清,此答案显示了如何利用 GUI Testing.py 中的 .after().mainloop() 方法,即使用 tkinter 事件循环而不使用两个 while 循环来实现您想要做的事情。这是一种简化 GUI 脚本的方法。
  • 对于更复杂的算法,例如涉及多个while循环,您必须考虑使用线程(注意它有其问题),或者最近我发现了一种使用python的Asyncio方法来做到这一点的方法。这两种方法的学习曲线要​​陡峭得多。要使用 asyncio 方法,您可以探索修改我的 answer 以执行您想要的操作。

【讨论】:

    【解决方案2】:

    最好的解决方案是使用线程,但是如果您打算以最简单的方式进行操作,那么在您的 Tkinter GUI 中实现主循环,一旦您读取数据包,只需在同一循环中在您的 GUI 上更新它。这是更新后的工作代码。

    import tkinter as tk
    import time
    
    
    def setvalue(self, x):
        self.label.config(text=x, )
        root.update()
        time.sleep(1)
    
    def changevalues(self):
        x = 99
        self.label = tk.Label(root, text=x)
        self.label.pack()
        while x >0:
            x -= 1
            setvalue(root,x)
    
    root = tk.Tk()
    changevalues(root)
    root.mainloop()
    

    【讨论】:

    • 据我所知,线程看起来很复杂而且很容易做错,所以我可能会避开这个选项。你所解释的正是我想做的,但我不知道该怎么做。如果我有一个用于读取数据包的 while True 循环,我应该将 Tkinter .mainloop 放在哪里?我将用一个我无法正确处理的 Tkinter 窗口示例来更新我的原始问题。
    • 好的,请在此处发布您的代码以便更好地理解
    • 在您发布原始代码时,我已对我的答案进行了修改。
    猜你喜欢
    • 2016-09-02
    • 2013-03-02
    • 2015-09-14
    • 2021-12-20
    • 1970-01-01
    • 2018-01-06
    • 2020-01-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多