我一直在慢慢地学习Tkinter和面向对象编程,但我已经用这个编程把自己逼到了一个角落。请原谅我在这个问题上缺乏批判性的思考,但我已经问过所有比我更了解python的人,我们在这里无法找到一个有效的解决方案。
我开发了一个gui应用程序im,它允许用户输入股票符号,为每个符号创建新标签,然后定期更新每个标签。(有点像一个真正基本的etrade应用程序之类的)。我发现没有gui很容易做到这一点,因为我可以说:
while True:
sPrice = get_stock_price(s)
print sPrice
但我已经将get_stock_price(s)函数绑定到一个按钮,该按钮将生成一个子帧和包含在其中的标签。我面临的问题是标签不会更新。一个朋友建议添加另一个方法来更新标签,但是我知道唯一的方法是做一个
while True:
# get new price
# update the label
# time.sleep(~1 minute?)
这会导致我的gui窗口永远冻结和旋转。 我已经阅读了与此特定情况相关的所有其他线程,并且看到了许多不同的建议;不要在主线程中调用sleep,不要使用root.update,使用events,调用root.something.after(500,function)和我尝试实现的。我只剩下一个弗兰肯斯坦代码,它仍然可以检索我的股票价值,但不会更新它们,还有一些方法我不知道如何更新,或者在哪里调用我的代码。
我希望的是一个(我知道,可能很长)。对不起!)解释我做错了什么,以及如何改正的建议。我真的很想自己理解并解决这个问题,但是只要解释了代码解决方案,它们就会非常棒。
提前谢谢你!!!
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()
你在找穿线。 将要运行的事件放到另一个线程中。请参见以下示例:
现在有一个函数与Tkinter窗口一起运行,该窗口每秒打印一次参数。
编辑:我不知道为什么会有这么多的反对票。Tkinter在处理线程方面做得很好,我已经多次使用这个技巧,没有问题。请参见以下示例:
下载一个10 MB的文件并将进度记录到Tkinter窗口。
无螺纹:
窗口将冻结,直到下载完成。
带螺纹:
不会冻结,文本会正常更新。
您已经有一个无限循环在运行,因此不应该尝试添加另一个循环。相反,可以使用
after
方法使函数每隔一段时间重复调用一次。在您的情况下,可以替换为:。。。有了这个:
这将得到一个报价,添加一个标签,然后安排在10秒(10000毫秒)内再次调用自己。
但是,我怀疑你是否想每10秒创建一个新标签,是吗?最后,窗口将充满标签。相反,您可以创建一次标签,然后在每次迭代中更新标签。例如,在init中创建一次
self.label
,然后在循环中可以执行以下操作:相关问题 更多 >
编程相关推荐