2

私はゆっくりと Tkinter とオブジェクト指向プログラミングを学んできましたが、これで隅に追いやられてしまいました。これに関する私の批判的思考の欠如を許してください。しかし、私よりもPythonをよく知っている知っているすべての人に尋ねましたが、ここで実用的な解決策にたどり着くことができません.

ユーザーが株式記号を入力し、各記号の新しいラベルを作成し、各ラベルを定期的に更新できるようにするための gui アプリを開発中です。(本当に基本的な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ウィンドウがフリーズして永久に回転します。この特定の状況に関連する他のすべてのスレッドを読んでいて、さまざまなアドバイスを見てきました。メインスレッドでスリープを呼び出さないでください。root.update を使用せず、イベントを使用し、root.something.after(500, 関数) を呼び出して、実装しようとしました。私が残したのは、株価を取得するがそれらを更新しないフランケンシュタインのコードと、更新方法やコードのどこを呼び出すかわからないいくつかのメソッドです。

私が望んでいるのは、私が間違っていることの説明と、それを修正する方法についての提案です (長くなる可能性があります。申し訳ありません!)。私は本当に自分で問題を理解して修正したいと思っていますが、説明されている限り、コードソリューションは素晴らしいでしょう.

よろしくお願いします!!!

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

2 に答える 2

0

あなたはスレッドを探しています。実行したいイベントを別のスレッドに入れます。次の例を参照してください。

import thread, time
def myfunc(a1,a2):
    while True:
      print a1,a2
      time.sleep(1)
thread.start_new_thread(myfunc,("test","arg2")
tkroot.mainloop()

これで、毎秒引数を出力する Tkinter ウィンドウと共に実行される関数ができました。

編集: なぜ反対票が多いのかわかりません。Tkinter DOES はスレッドでうまく機能します。私はすでにこのトリックを何度か問題なく使用しています。次の例を参照してください。

10 MB のファイルをダウンロードし、進行状況を Tkinter ウィンドウに記録します。

ねじ切りなし:

import urllib2,thread
import Tkinter as tk

class Example(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)   

        self.parent = parent        
        self.initUI()

    def initUI(self):

        self.pack(fill=tk.BOTH, expand=1)

        canvas = tk.Canvas(self)

        self.text = canvas.create_text(18,18,anchor=tk.W,font="Purisa",text="Status: Press start to download...")
        but=tk.Button(text="Start",command=self.start)
        canvas.create_window((270,18),window=but)

        canvas.pack(fill=tk.BOTH, expand=1)
        self.canvas=canvas

    def start(self):
        #thread.start_new_thread(
        self.download("http://ipv4.download.thinkbroadband.com/10MB.zip","10mb.zip")
        #)

    def onEnd(self):
            self.canvas.itemconfig(self.text, text="Status: done!")

    def download(self,url,file_name):
        u = urllib2.urlopen(url) 
        f = open(file_name, 'wb')
        meta = u.info()
        file_size = int(meta.getheaders("Content-Length")[0])
        print "Downloading: %s Bytes: %s" % (file_name, file_size)

        file_size_dl = 0
        block_sz = 1024*50 #50 kb
        while True:
            buffer = u.read(block_sz)
            if not buffer:
                break

            file_size_dl += len(buffer)
            f.write(buffer)
            status = r"[%3.2f%%]" % (file_size_dl * 100. / file_size)
            self.canvas.itemconfig(self.text,text="Status: downloading..."+status)

        f.close()

        self.onEnd()

def main():
    root = tk.Tk()
    root.resizable(0,0)
    ex = Example(root)
    root.geometry("300x70")
    root.mainloop()  

main()

ダウンロードが完了するまでウィンドウがフリーズします。

スレッド付き:

import urllib2,thread
import Tkinter as tk

class Example(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)   

        self.parent = parent        
        self.initUI()

    def initUI(self):

        self.pack(fill=tk.BOTH, expand=1)

        canvas = tk.Canvas(self)

        self.text = canvas.create_text(18,18,anchor=tk.W,font="Purisa",text="Status: Press start to download...")
        but=tk.Button(text="Start",command=self.start)
        canvas.create_window((270,18),window=but)

        canvas.pack(fill=tk.BOTH, expand=1)
        self.canvas=canvas

    def start(self):
        thread.start_new_thread(
        self.download("http://ipv4.download.thinkbroadband.com/10MB.zip","10mb.zip")
        )

    def onEnd(self):
            self.canvas.itemconfig(self.text, text="Status: done!")

    def download(self,url,file_name):
        u = urllib2.urlopen(url) 
        f = open(file_name, 'wb')
        meta = u.info()
        file_size = int(meta.getheaders("Content-Length")[0])
        print "Downloading: %s Bytes: %s" % (file_name, file_size)

        file_size_dl = 0
        block_sz = 1024*50 #50 kb
        while True:
            buffer = u.read(block_sz)
            if not buffer:
                break

            file_size_dl += len(buffer)
            f.write(buffer)
            status = r"[%3.2f%%]" % (file_size_dl * 100. / file_size)
            self.canvas.itemconfig(self.text,text="Status: downloading..."+status)

        f.close()

        self.onEnd()

def main():
    root = tk.Tk()
    root.resizable(0,0)
    ex = Example(root)
    root.geometry("300x70")
    root.mainloop()  

main()

フリーズせず、テキストは正常に更新されます。

于 2013-09-08T00:32:50.893 に答える