0

I'm trying to make a file downloader program and want to show a panel that shows all the processing details in that panel and not in the shell I already have a progress bar, but want to put the processing panel below the wxpython mainframe. I tried to do it but didn't find any solution, I want to ask does wxpython supports this feature and if yes, then can you help me to do so

I'm not an expert just started working with python... will be very thankful for your replies.

  • What are the processing details that you want to display? – Mike Driscoll Nov 16 '17 at 15:59
  • its like I'm downloading files (all types like mp3,mp4, pdf and all )and want to show the processing details – monika razdan Nov 16 '17 at 16:30
  • Yes, but what exactly is that? The progress bar already gives the user indication that they are x% through the download. Are you wanting to add a label with the file name that is being downloaded? Do you want to display metadata about the file that is being downloaded? Or something else? – Mike Driscoll Nov 16 '17 at 19:42
  • the progress bar I added simply fills up first even before the downloading it doesn't work as the file that is being downloaded what I want it should work according to the file processing and show the amount left like normally we download any file from the browser it shows the percentage file downloaded and left. (somewhat in same manner) – monika razdan Nov 17 '17 at 05:13
  • Ah. Then you want to run the download in a thread and update your progress bar that way. – Mike Driscoll Nov 17 '17 at 18:29

1 Answers1

0

You will want to use a thread to do the downloading part as doing file I/O tends to be blocking. I wrote about this a few years ago here:

More recently, I actually put together a simple application that demonstrates how to download a file using wxPython and a progress bar:

Here's the code example:

import requests
import os
import wx
import wx.lib.scrolledpanel as scrolled

from threading import Thread
from wx.lib.pubsub import pub

########################################################################
class DownloadThread(Thread):
    """Downloading thread"""

    #----------------------------------------------------------------------
    def __init__(self, gnum, url, fsize):
        """Constructor"""
        Thread.__init__(self)
        self.fsize = fsize
        self.gnum = gnum
        self.url = url
        self.start()

    #----------------------------------------------------------------------
    def run(self):
        """
        Run the worker thread
        """
        local_fname = os.path.basename(self.url)
        count = 1
        while True:
            if os.path.exists(local_fname):
                tmp, ext = os.path.splitext(local_fname)
                cnt = "(%s)" % count
                local_fname = tmp + cnt + ext
                count += 1
            else:
                break
        req = requests.get(self.url, stream=True)
        total_size = 0
        print local_fname
        with open(local_fname, "wb") as fh:
            for byte in req.iter_content(chunk_size=1024):
                if byte:
                    fh.write(byte)
                    fh.flush()
                total_size += len(byte)
                if total_size < self.fsize:
                    wx.CallAfter(pub.sendMessage, 
                                 "update_%s" % self.gnum,
                                 msg=total_size)
        print "DONE!"
        wx.CallAfter(pub.sendMessage,
                     "update_%s" % self.gnum,
                     msg=self.fsize)


########################################################################
class MyGauge(wx.Gauge):
    """"""

    #----------------------------------------------------------------------
    def __init__(self, parent, range, num):
        """Constructor"""
        wx.Gauge.__init__(self, parent, range=range)

        pub.subscribe(self.updateProgress, "update_%s" % num)

    #----------------------------------------------------------------------
    def updateProgress(self, msg):
        """"""
        self.SetValue(msg)

########################################################################
class MyPanel(scrolled.ScrolledPanel):
    """"""

    #----------------------------------------------------------------------
    def __init__(self, parent):
        """Constructor"""
        scrolled.ScrolledPanel.__init__(self, parent)

        self.data = []
        self.download_number = 1

        # create the sizers
        self.main_sizer = wx.BoxSizer(wx.VERTICAL)
        dl_sizer = wx.BoxSizer(wx.HORIZONTAL)

        # create the widgets
        lbl = wx.StaticText(self, label="Download URL:")
        self.dl_txt = wx.TextCtrl(self)
        btn = wx.Button(self, label="Download")
        btn.Bind(wx.EVT_BUTTON, self.onDownload)

        # layout the widgets
        dl_sizer.Add(lbl, 0, wx.ALL|wx.CENTER, 5)
        dl_sizer.Add(self.dl_txt, 1, wx.EXPAND|wx.ALL, 5)
        dl_sizer.Add(btn, 0, wx.ALL, 5)
        self.main_sizer.Add(dl_sizer, 0, wx.EXPAND)

        self.SetSizer(self.main_sizer)
        self.SetAutoLayout(1)
        self.SetupScrolling()

    #----------------------------------------------------------------------
    def onDownload(self, event):
        """
        Update display with downloading gauges
        """
        url = self.dl_txt.GetValue()
        try:
            header = requests.head(url)
            fsize = int(header.headers["content-length"]) / 1024

            sizer = wx.BoxSizer(wx.HORIZONTAL)
            fname = os.path.basename(url)
            lbl = wx.StaticText(self, label="Downloading %s" % fname)
            gauge = MyGauge(self, fsize, self.download_number)

            sizer.Add(lbl, 0, wx.ALL|wx.CENTER, 5)
            sizer.Add(gauge, 0, wx.ALL|wx.EXPAND, 5)
            self.main_sizer.Add(sizer, 0, wx.EXPAND)

            self.Layout()

            # start thread
            DownloadThread(self.download_number, url, fsize)
            self.dl_txt.SetValue("")
            self.download_number += 1
        except Exception, e:
            print "Error: ", e

########################################################################
class DownloaderFrame(wx.Frame):
    """"""

    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, None, title="Downloader", size=(800, 400))
        panel = MyPanel(self)
        self.Show()

#----------------------------------------------------------------------
if __name__ == "__main__":
    app = wx.App(False)
    frame = DownloaderFrame()
    app.MainLoop()

Note that I am using requests instead of Python's urllib for the actual downloading, so you will want to get that as well or update this code to use urllib.

Mike Driscoll
  • 32,629
  • 8
  • 45
  • 88
  • this code is exactly the problem I need the solution for. the gauge processing should depend on the amount of downloading speed, but here the gauge is simply filling up and the processing is working at back. I want that processing to be shown simply on panel and with detailed download processing – monika razdan Nov 25 '17 at 09:55
  • You could try to request what the full file size is from the server and then display the amount downloaded with the gauge. If you want download speed, then you will need to check out this answer: https://stackoverflow.com/questions/20801034/how-to-measure-download-speed-and-progress-using-requests – Mike Driscoll Dec 06 '17 at 17:09