Tkinter与我的mainloop一起管理我的事件循环 [英] Tkinter managing my event loops alongside my mainloop

查看:198
本文介绍了Tkinter与我的mainloop一起管理我的事件循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在慢慢学习Tkinter和面向对象的编程,但是我已经将自己编程与此有关.请原谅我缺乏关于python的批判性思维,但是我问过我认识的每个人,谁比我更了解python,所以我们在这里找不到可行的解决方案.

I've been slowly learning Tkinter and object-oriented programming but I've programmed myself into a corner with this one. please forgive my lack of critical thinking on this one, but i've asked everyone I know who knows python better than me and we can't get to a working solution here.

我有一个正在运行的gui应用程序,它允许用户输入股票代码,为每个代码创建新标签,然后定期更新每个标签. (有点像一个非常基本的电子贸易应用程序之类的东西).我发现没有gui确实很容易做到这一点,因为我只能说:

I've got a gui app im working on that is meant to allow the user to input stock symbols, create new labels for each symbol, and then update each label periodically. (kinda like a really basic etrade app or something). I've found it's really easy to do this without a gui because I can just say:

while True:
   sPrice = get_stock_price(s)
   print sPrice

但是我将get_stock_price(s)函数绑定到了一个按钮,该按钮产生了一个子框架和其中包含的标签.我遇到的问题是标签不会更新.一位朋友建议添加另一种仅用于更新标签的方法,但是我知道如何不断更新标签的唯一方法是执行

but i've bound my get_stock_price(s) function to a button, which spawns a sub-frame and a label contained inside it. The problem i've faced is the label will not update. A friend recommended to add another method solely to update the label, however the only way I know how to continuously update it is do a

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

这会使我的GUI窗口永久冻结并旋转. 我一直在阅读与该特定情况相关的所有其他线程,并且看到了许多不同的建议.不要在主线程中调用sleep,不要使用root.update,不要使用事件,不要调用root.something.after(500,function)并且我已经尝试实现.我剩下的是弗兰肯斯坦的代码,仍然可以检索我的股票价值,但不会更新它们,还有一些我不知道如何更新或在代码中调用的方法.

this causes my gui window to freeze and spin forever. I've been reading up on all the other threads related to this particular situation, and I've seen many different advices; don't call sleep in your main thread, don't use root.update, use events, call root.something.after(500, function) and i've tried to implement. What i've been left with is a frankenstein of code that will still retrieve my stock values, but wont update them, and a few methods that I don't know how to update, or where to call in my code.

我所希望的是(可能很长,我知道.很抱歉!)我做错了什么的解释,以及有关如何解决它的建议.我真的想亲自了解并解决该问题,但是只要能解释它们,代码解决方案就很棒.

What im hoping for is a (potentially long, I know. Sorry!) explanation of what i'm doing wrong, and suggestions on how to fix it. I'm really looking to understand and fix the issue myself, but code-solutions would be awesome so long as they are explained.

非常感谢!

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

PS: Here is my code so far:

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方法来使函数经常被重复调用.根据您的情况,您可以替换为:

You already have an infinite loop running, so you shouldn't be trying to add another one. Instead, you can use the after method to cause a function to be repeatedly called every so often. In your case, you can replace this:

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毫秒)内再次被调用.

This will get a quote, add a label, then arrange for itself to be called again in 10 seconds (10,000 ms).

但是,我怀疑您是否想每10秒创建一个新标签,对吗?最终,窗口将充满标签.相反,您可以创建一次标签,然后在每次迭代中更新标签.例如,在init中创建一次self.label,然后在循环中可以执行以下操作:

However, I doubt that you want to create a new label every 10 seconds, do you? Eventually the window will fill up with labels. Instead, you can create a label once, then update the label in each iteration. For example, create self.label once in the init, then in the loop you can do:

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

这篇关于Tkinter与我的mainloop一起管理我的事件循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆