python - Tkinter 管理我的事件循环和我的主循环

标签 python loops user-interface widget tkinter

我一直在慢慢学习 Tkinter 和面向对象的编程,但我已经将自己编程到一个角落。请原谅我在这方面缺乏批判性思考,但我已经问过所有我认识的比我更了解 Python 的人,我们无法在这里找到可行的解决方案。

我正在开发一个图形用户界面应用程序,它允许用户输入股票代码,为每个代码创建新标签,然后定期更新每个标签。 (有点像一个非常基本的 etrade 应用程序之类的东西)。我发现没有图形用户界面就很容易做到这一点,因为我可以说:

while True:
   sPrice = get_stock_price(s)
   print sPrice

但我已将我的 get_stock_price(s) 函数绑定(bind)到一个按钮,该按钮生成一个子框架和一个包含在其中的标签。我遇到的问题是标签不会更新。一位 friend 建议添加另一种方法来更新标签,但我知道如何持续更新它的唯一方法是做一个

while True:
    # get new price
    # update the label
    # time.sleep(~1 minute?)

这会导致我的 gui 窗口永远卡住和旋转。 我一直在阅读与这种特殊情况相关的所有其他主题,并且看到了许多不同的建议;不要在主线程中调用 sleep,不要使用 root.update,使用事件,调用 root.something.after(500, function) 并且我已经尝试实现。我剩下的是一个科学怪人的代码,它仍然会检索我的股票值(value),但不会更新它们,还有一些我不知道如何更新或在哪里调用我的代码的方法。

我希望的是(可能很长,我知道。抱歉!)对我做错了什么的解释,以及如何解决它的建议。我真的很想自己理解并解决问题,但只要解释清楚,代码解决方案就很棒。

提前致谢!!!

PS:到目前为止,这是我的代码:

from Tkinter import *
import urllib
import re
import time

class MyApp(object):
    def __init__(self, parent):
        self.myParent = parent
        self.myContainer1 = Frame(parent)
        self.myContainer1.pack()
        self.createWidgets()
        button1 = Button(self.myContainer1, command = self.addStockToTrack)
        self.myContainer1.bind("<Return>", self.addStockToTrack)
        button1.configure(text = "Add Symbol")
        button1.pack()  

    def createWidgets(self):
        # title name
        root.title("Stock App")
        # creates a frame inside myContainer1
        self.widgetFrame = Frame(self.myContainer1)
        self.widgetFrame.pack()
        # User enters stock symbol here:
        self.symbol = Entry(self.widgetFrame) 
        self.symbol.pack()
        self.symbol.focus_set()

    def addStockToTrack(self):
        s = self.symbol.get()
        labelName = str(s) + "Label"
        self.symbol.delete(0, END)
        stockPrice = get_quote(s)
        self.labelName = Label(self.myContainer1, text = s.upper() + ": " + str(stockPrice))
        self.labelName.pack()
        self.myContainer1.after(500, self.get_quote)

    def updateStock(self):
        while True:
            labelName = str(s) + "Label"
            stockPrice = get_quote(s)
            self.labelName = Label(self.myContainer1, text = s.upper() + ": " + str(stockPrice))
            self.labelName.pack()
            time.sleep(10)

def get_quote(symbol):
    base_url = 'http://finance.google.com/finance?q='
    content = urllib.urlopen(base_url + symbol).read()
    m = re.search('id="ref_\d*_l".*?>(.*?)<', content)
    if m:
        quote = m.group(1)
    else:
        quote = 'Not found: ' + symbol
    return quote

root = Tk()
myapp = MyApp(root)
root.mainloop()

最佳答案

您已经有一个无限循环在运行,因此您不应该尝试添加另一个。相反,您可以使用 after 方法使函数每隔一段时间被重复调用一次。在你的情况下,你可以替换这个:

def updateStock(self):
   while True:
        labelName = str(s) + "Label"
        stockPrice = get_quote(s)
        self.labelName = Label(self.myContainer1, text = s.upper() + ": " + str(stockPrice))
        self.labelName.pack()
        time.sleep(10)

...用这个:

def updateStock(self):
    labelName = str(s) + "Label"
    stockPrice = get_quote()
    self.labelName = Label(self.myContainer1, text = s.upper() + ": " + str(stockPrice))
    self.labelName.pack()
    self.after(10000, self.updateStock)

这会得到报价,添加标签,然后安排自己在 10 秒(10,000 毫秒)后再次被调用。

但是,我怀疑您想每 10 秒创建一个新标签,对吗?最终窗口将填满标签。相反,您可以创建一次标签,然后在每次迭代中更新标签。例如,在 init 中创建一次 self.label,然后在循环中你可以这样做:

self.labelName.configure(text=s.upper() + ": " + str(stockPrice))

关于python - Tkinter 管理我的事件循环和我的主循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18679102/

相关文章:

java - 调用 pack() 后如何在面板上画一条线?

windows - 支持正则表达式的免费 Windows GUI 文本编辑器,适用于程序员?

java - 根据操作系统更改 LaF

python - 如何在 Python 中使用 LDAP 将新用户添加到组中?

python - 如何有效地访问另一个可迭代的 Python 可迭代索引证明

python - 如何迭代数据列的每个单元格,转换并追加每个单元格?

javascript - 查找数组中的一个或多个数字是否可以加起来等于某个数字

javascript - 使用高速公路 python 发送 json

python - 如何正常调用点击包装功能?

python - 我怎样才能拼接一个字符串?