0

So I am working on this program that is supposed to be downloading stuff from the web using tkinter and urllib.request but it is lacking a download bar(or a progress bar if that is the true word). So I found out that you can create a progress bar using TQDM but there are two problems: first of all, I didn't seem to find a way to use it in a tkinter program. Second of all, It doesn't show the download speed, you just set a limit and it fills up until it reaches that limit. I did a bit of research again and I found out that you can create a progress bar using ttk but it still has the second problem(It does not show the user's internet(download) speed and that how much of the file has been downloaded like chrome's download bar). Can someone help me out on this? My code(BTW if you have any suggestions how to make my program better I would appreciate it):

from tkinter import *
from tkinter import font as tkFont
import random
import urllib.request
import requests
from tqdm import tqdm
from tqdm.auto import tqdm


def printsth():
    print("Yay it works! ")


def main_menu():
    root = Tk()
    # the top menu
    num = IntVar()
    # var = IntVar()
    menu = Menu(root)
    root.config(menu=menu)
    submenu = Menu(menu)
    menu.add_cascade(label="Settings", menu=submenu)

    def custom_op():
        custom = Tk()

        custom.mainloop()
    submenu.add_command(label="Customization ", command=custom_op)

    def settings_op():
        set_win = Tk()

        set_win.mainloop()
    submenu.add_command(label="Settings ", command=settings_op)
    submenu.add_separator()
    submenu.add_command(label="Exit", command=root.destroy)

    # the edit menu
    editmenu = Menu(menu)
    menu.add_cascade(label="Edit", menu=editmenu)
    editmenu.add_command(label="Redo...", command=printsth)

    # the tool bar
    toolbar = Frame(root, bg="light gray")
    insert_button = Button(toolbar, text="Insert an image", command=printsth)
    insert_button.pack(side=LEFT, padx=2, pady=2)
    print_button = Button(toolbar, text="Print", command=printsth)
    print_button.pack(side=LEFT, padx=2, pady=2)
    toolbar.pack(side=TOP, fill=X)

    # the download function
    def download_image():
        global formatname
        if num.get() == 1:
            name = random.randrange(1, 100000)
        else:
            name = str(name_entry.get())
        formatname = str(format_entry.get())
        '''if var.get() == 1:
            operator = str(url_entry.get())
            formatname = '.' + operator[-3] + operator[-2] + operator[-1]
        else:
            pass'''
        fullname = str(name) + formatname
        url = str(url_entry.get())
        fw = open('file-size.txt', 'w')
        file_size = int(requests.head(url, headers={'accept-encoding': ''}).headers['Content-Length'])
        fw.write(str(file_size))
        fw.close()
        path = str(output_entry.get()) + "\\"
        urllib.request.urlretrieve(url, path.replace("\\", "\\\\") + fullname)

    # the status bar
    status_bar = Label(root, text="Downloading...", bd=1, relief=SUNKEN, anchor=W)
    status_bar.pack(side=BOTTOM, fill=X)

    # the download frame
    body_frame = Frame(root, bg="light blue")
    download_button = Button(body_frame, text="Download! ", command=download_image, border=3, width=20, height=5)
    download_design = tkFont.Font(size=12, slant='italic')
    download_button['font'] = download_design
    download_button.pack(side=LEFT, pady=5, padx=5)
    body_frame.pack(side=LEFT, fill=Y)
    # the main interaction menu
    inter_frame = Frame(root)
    url_entry = Entry(inter_frame)
    label = Label(inter_frame, text="Enter the image URL: ")
    file_format = Label(inter_frame, text="Choose your file format: ")
    format_entry = Entry(inter_frame)
    file_name = Label(inter_frame, text="File's name: ")
    name_entry = Entry(inter_frame)
    check_name = Checkbutton(inter_frame, text="Give a random name", variable=num)
    # check_format = Checkbutton(inter_frame, text="Download with default format", variable=var)
    output_path = Label(inter_frame, text="Choose output path: ")
    output_entry = Entry(inter_frame)
    file_name.pack(anchor=CENTER, expand=1)
    name_entry.pack(anchor=CENTER, expand=1)
    check_name.pack(anchor=CENTER, expand=1)
    label.pack(anchor=CENTER, expand=1)
    url_entry.pack(anchor=CENTER, expand=1)
    file_format.pack(anchor=CENTER, expand=1)
    format_entry.pack(anchor=CENTER, expand=1)
    # check_format.pack(anchor=CENTER)
    output_path.pack(anchor=CENTER, expand=1)
    output_entry.pack(anchor=CENTER, expand=1)
    inter_frame.pack(expand=1)
    root.mainloop()

    # the end!


main_menu()
Omid Ki
  • 111
  • 1
  • 10
  • you could've calculated speed youself if you were using sockets. I don't think you can really accomplish the said task while using synchronous requests lib, your program will block until your file is downloaded. Alternativly - if it's possible to control chunk-size with requests lib - you can estimate time that it would take to download 1mb image with X bytes chunk-size and dynamicaly decrease the speed in your download bar if the download time is greater than your estimate (very innacurate solution tho) Updates of progress bar are done in separate thread – Javed Apr 14 '20 at 07:07
  • 2
    Since you are using `urllib.request.urlretrieve()`, you can associate a callback via `reporthook` option and show the progress in the callback. – acw1668 Apr 14 '20 at 07:12

1 Answers1

0

This is code snippet from my tool for status bar

progress = ttk.Progressbar(self, orient=HORIZONTAL, length=400,  mode='determinate')
progress.grid(row=3, column=0, pady=2, padx=2, columnspan=4, sticky=SW+SE)
progress.pack(side=BOTTOM, anchor=S, expand=YES)
progress["maximum"] = 100
progerss_part = 0

you can update progress by using

progress["value"] = x

Hope this will help you.

  • Hello, Phani Kumar. A question: Is 'X' supposed to be an Int? Because if it is I get an error like this one: TypeError: 'module' object does not support item assignment. So what is the problem? – Omid Ki Apr 16 '20 at 16:42