1

編集:答えは以下です。 self.progress.update_idletasks()プログレスバーを更新するための秘密の握手でした。ありがとう、ミリソン。

私は現在、いくつかのやや大きな csv ファイル (場合によっては最大 700Mb) を処理していますが、ネットワーク ドライブからプルするのに時間がかかります。プロセスのステータスとして、ユーザーに何らかのフィードバックを提供できるようにしたいと考えています。これにより、ttk ステータスバーが表示されました。見つけられる限り多くの例を見て、それらをプログラムに適用しようとしましたが、成功しませんでした。私の問題は、forループを使用してcsvファイルを読み取っていることだと思いますが、それは問題ではないかもしれません。知らない。以下は、私のコードがどのように機能するかの例です。

import csv
import Tkinter as tk
import ttk

class MAIN(tk.Frame):
    def __init__(self, master, *args, **kwargs):
        n=0
        self.filename = 'some.csv'
        tk.Frame.__init__(self, *args, **kwargs)
        frame=tk.Frame(master, **kwargs)
        frame.grid()
        getdata = tk.Button(frame, text='Get Data', command=self.csvget)
        getdata.grid(row=n)
        n+=1
        self.progress = ttk.Progressbar(frame, orient='horizontal',
                                        length =200, mode='determinate')
        self.progress.grid(row=n)
    def prog(self):
        self.progress['value']=0
        try: f=open(self.filename, 'rb')
        except: return
        read = csv.reader(f, delimiter=',')
        self.maxrows=0
        for row in read: self.maxrows+=1
        self.progress['maximum']=self.maxrows
    def csvget(self):
        try: f=open(self.filename, 'rb')
        except: return
        read = csv.reader(f, delimiter=',')
        q=0
        for row in read:
            if q%100==0: self.progress['value']=q
            elif q==self.maxrows: self.progress['value']=q
            ... do some stuff (read into lists etc.)...

root=tk.Tk()
app=MAIN(root)
app.mainloop()

さて、それは私が予想したよりも長くなりました。私はファイルを2回読んでいることを知っています。(csvファイルの長さを他の方法で取得する方法がわかりませんでした。これに対する解決策があれば、私はすべて耳にします。)しかし、私の質問の主な目的は、進行状況バーを取得するにはどうすればよいかです。仕事。現在の構成では、ファイルの読み取りが完了するとすぐにゼロからフルになります。提案?

編集: mgilson の助けを借りて、私のコードはずっと良くなりました。ただし、ファイルの処理中にステータス バーがまだ更新されません。私は次のことを試しました:

self.completed = tk.IntVar()
self.completed.set(0)
self.progress = ttk.Progressbar(self.frame, orient='horizontal', length=200,
                   mode='determinate', maximum=100, variable=self.completed)
#in the function now
fsize = os.path.getsize(self.filename)
for r,row in enumerate(read):
    q=float(f.tell())/float(fsize)*100 
    if r%100 ==0:
        self.completed.set(q)

self.completedまた、単に呼び出すのではなく、入力として受け取り、それを に入れる を作成defしましqself.completed。また、 を使用するのではなく、 のkwarg をself.completed取り除き、 kwarg の「値」を直接および を介して呼び出すことに戻りました。も試行され、他のものと同じように動作します。variableself.progressdefself.progress.configure(value = q)

これらの試行はすべて、ファイルが完了した後にのみバーを更新します。

forデータが読み取られるループの前にバーのステータスを変更するとdef、ファイルの読み取りが完了するまでバーは更新されません。(実験的に50に設定してみましたが、ファイルが完了するとすぐになしから100%になりました。)

4

1 に答える 1

1

次のようなものが欲しいですか:

if q%100==0: 
    self.progress['value']=float(q)/100
    self.progress.update_idletasks()

多分:

self.progress.configure(value=q)
self.progress.update_idletasks()

以前のバージョンでは、100 行を読むとすぐにプログレス バーがいっぱいになります。

また、プログレス バーは、プログラム制御がメインループに戻ったときにのみ更新されることに注意してくださいupdate_idletasks()

ファイルを 2 回読み取らない限り、それを使用できる可能性file.tellがあります(保証はありません。動作しない場合はお知らせください。この提案は削除します)。

fsize=os.path.getsize(filename)
...
q=f.tell()/fsize

これが機能する場合、コンストラクターを次のように変更できる場合があります。

self.progress = ttk.Progressbar(frame, orient='horizontal',
                                length =200, mode='determinate',maximum=1.)

そしてあなたのループへ:

for i,row in enumerate(read):
    q=f.tell()/fsize
    if i%100==0: 
        self.progress['value']=q
        self.progress.update_idletasks()
    #do stuff
else:
    self.progress['value']=q
    self.progress.update_idletasks()

もう 1 つ注意点があります。一般に、むき出しのtry/except句を使用することはお勧めできません。あなたは通常欲しい:

try:
   #something
except SomeError: #IOError?  OSError? some combination of the two of them?
   #something else.

処理方法を知っている例外のみをキャッチします。

于 2012-07-02T15:20:21.487 に答える