質問

Webからファイルをダウンロードしている間に進行状況バーを表示したい urllib.urlretrive 方法。

どのように使用できますか ttk.Progressbar このタスクを行うには?

これが私がこれまでに行ったことです:

from tkinter import ttk
from tkinter import *

root = Tk()

pb = ttk.Progressbar(root, orient="horizontal", length=200, mode="determinate")
pb.pack()
pb.start()

root.mainloop()

しかし、それはただループを続けます。

役に立ちましたか?

解決

決定的なモードの場合は、電話をかけたくありません start. 。代わりに、単に構成します value ウィジェットまたは電話をかけます step 方法。

ダウンロードするバイトの数を事前に知っている場合(そして、あなたが決定的なモードを使用しているのであなたがすると思います)、最も簡単なことは設定することです maxvalue 読み取る番号のオプション。その後、チャンクを読むたびに構成する value 読み取られるバイトの総数になること。その後、Progress Barはパーセンテージを把握します。

これがあなたに大まかなアイデアを与えるためのシミュレーションです:

import tkinter as tk
from tkinter import ttk


class SampleApp(tk.Tk):

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        self.button = ttk.Button(text="start", command=self.start)
        self.button.pack()
        self.progress = ttk.Progressbar(self, orient="horizontal",
                                        length=200, mode="determinate")
        self.progress.pack()

        self.bytes = 0
        self.maxbytes = 0

    def start(self):
        self.progress["value"] = 0
        self.maxbytes = 50000
        self.progress["maximum"] = 50000
        self.read_bytes()

    def read_bytes(self):
        '''simulate reading 500 bytes; update progress bar'''
        self.bytes += 500
        self.progress["value"] = self.bytes
        if self.bytes < self.maxbytes:
            # read more bytes after 100 ms
            self.after(100, self.read_bytes)

app = SampleApp()
app.mainloop()

これが機能するには、GUIスレッドをブロックしないようにする必要があります。つまり、チャンクで(例のように)読むか、別のスレッドで読み取りを行うことを意味します。スレッドを使用する場合、TKINTERは単一のスレッドであるため、ProgressBarメソッドを直接呼び出すことができません。

あなたが見つけるかもしれません ProgressBarの例 の上 tkdocs.com 役に立つように。

他のヒント

私はあなたのためにコードを簡素化しました。

import sys
import ttk
from Tkinter import *

mGui = Tk()

mGui.geometry('450x450')
mGui.title('Hanix Downloader')

mpb = ttk.Progressbar(mGui,orient ="horizontal",length = 200, mode ="determinate")
mpb.pack()
mpb["maximum"] = 100
mpb["value"] = 50

mGui.mainloop()

交換 50 ダウンロードの割合。

プログラムが忙しいことを示すために進行状況バーが必要な場合/動作するだけで、モードを決定から不確定に変更するだけです

pb = ttk.Progressbar(root,orient ="horizontal",length = 200, mode ="indeterminate")

これも、進行状況の動きを示している別の簡単な例です。 (で与えられた例を簡素化しました https://gist.github.com/kochie/9f0b60384cc1ab434eb)

import Tkinter
import ttk

root = Tkinter.Tk()
pb = ttk.Progressbar(root, orient='horizontal', mode='determinate')
pb.pack(expand=True, fill=Tkinter.BOTH, side=Tkinter.TOP)
pb.start(50)
root.mainloop()

より大きなプロジェクトのためのProgressBarを使用したモーダルダイアログウィンドウ

この例は少し長いですが、Python 3.6でテストされており、より大きなプロジェクトで使用できます。

# -*- coding: utf-8 -*-
# Modal dialog window with Progressbar for the bigger project
import time
import tkinter as tk
from tkinter import ttk
from tkinter import simpledialog

class MainGUI(ttk.Frame):
    ''' Main GUI window '''
    def __init__(self, master):
        ''' Init main window '''
        ttk.Frame.__init__(self, master=master)
        self.master.title('Main GUI')
        self.master.geometry('300x200')
        self.lst = [
            'Bushes01.png',  'Bushes02.png', 'Bushes03.png', 'Bushes04.png', 'Bushes05.png',
            'Forest01.png',  'Forest02.png', 'Forest03.png', 'Forest04.png', 'Road01.png',
            'Road02.png',    'Road03.png',   'Lake01.png',   'Lake02.png',   'Field01.png']
        b = ttk.Button(self.master, text='Start', command=self.start_progress)
        b.pack()
        b.focus_set()

    def start_progress(self):
        ''' Open modal window '''
        s = ProgressWindow(self, 'MyTest', self.lst)  # create progress window
        self.master.wait_window(s)  # display the window and wait for it to close

class ProgressWindow(simpledialog.Dialog):
    def __init__(self, parent, name, lst):
        ''' Init progress window '''
        tk.Toplevel.__init__(self, master=parent)
        self.name = name
        self.lst = lst
        self.length = 400
        #
        self.create_window()
        self.create_widgets()

    def create_window(self):
        ''' Create progress window '''
        self.focus_set()  # set focus on the ProgressWindow
        self.grab_set()  # make a modal window, so all events go to the ProgressWindow
        self.transient(self.master)  # show only one window in the task bar
        #
        self.title(u'Calculate something for {}'.format(self.name))
        self.resizable(False, False)  # window is not resizable
        # self.close gets fired when the window is destroyed
        self.protocol(u'WM_DELETE_WINDOW', self.close)
        # Set proper position over the parent window
        dx = (self.master.master.winfo_width() >> 1) - (self.length >> 1)
        dy = (self.master.master.winfo_height() >> 1) - 50
        self.geometry(u'+{x}+{y}'.format(x = self.master.winfo_rootx() + dx,
                                         y = self.master.winfo_rooty() + dy))
        self.bind(u'<Escape>', self.close)  # cancel progress when <Escape> key is pressed

    def create_widgets(self):
        ''' Widgets for progress window are created here '''
        self.var1 = tk.StringVar()
        self.var2 = tk.StringVar()
        self.num = tk.IntVar()
        self.maximum = len(self.lst)
        self.tmp_str = ' / ' + str(self.maximum)
        #
        # pady=(0,5) means margin 5 pixels to bottom and 0 to top
        ttk.Label(self, textvariable=self.var1).pack(anchor='w', padx=2)
        self.progress = ttk.Progressbar(self, maximum=self.maximum, orient='horizontal',
                                        length=self.length, variable=self.num, mode='determinate')
        self.progress.pack(padx=2, pady=2)
        ttk.Label(self, textvariable=self.var2).pack(side='left', padx=2)
        ttk.Button(self, text='Cancel', command=self.close).pack(anchor='e', padx=1, pady=(0, 1))
        #
        self.next()

    def next(self):
        ''' Take next file from the list and do something with it '''
        n = self.num.get()
        self.do_something_with_file(n+1, self.lst[n])  # some useful operation
        self.var1.set('File name: ' + self.lst[n])
        n += 1
        self.var2.set(str(n) + self.tmp_str)
        self.num.set(n)
        if n < self.maximum:
            self.after(500, self.next)  # call itself after some time
        else:
            self.close()  # close window

    def do_something_with_file(self, number, name):
        print(number, name)

    def close(self, event=None):
        ''' Close progress window '''
        if self.progress['value'] == self.maximum:
            print('Ok: process finished successfully')
        else:
            print('Cancel: process is cancelled')
        self.master.focus_set()  # put focus back to the parent window
        self.destroy()  # destroy progress window

root = tk.Tk()
feedback = MainGUI(root)
root.mainloop()

シミュレーションから明らかではない何かを指摘したいと思います。一部のオペレーティングシステムでは、ファイルハンドルが閉じられるまで、書き込みのために空のファイルが開かれた場合、OS.Stat()が0を返します。これにより、ダウンロードされたファイルの進行状況を示す進行状況バーの能力が無効になります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top