3

My python application consists of various separate processing algorithms/modules combined within a single (Py)Qt GUI for ease of access.

Every processing algorithm sits within its own module and all the communication with GUI elements is implemented within a single class in the main module. In particular, this GUI class has a progressbar (QProgressBar) object designed to represent the current processing progress of a chosen algorithm. This object has .setValue() method (self.dlg.progressBar.setValue(int)).

The problem is that since self.dlg.progressBar.setValue() is a class method I cannot use it inside my imported processing modules to report their progress state within their own code.

The only workaround I found is to add progressbar variable to definition of each processing module, pass there self.dlg.progressBar inside the main module and then blindly call progressbar.setValue(%some_processing_var%) inside the processing module.

Is this the only way to use outer class methods inside imported modules or are there better ways?

Vasily
  • 2,192
  • 4
  • 22
  • 33

1 Answers1

5

No. I think this approach somewhat breaks software engineering principles (e.g. single responsibility). In single responsibility principle, each module is only in charge of its assigned task and nothing else. If we consider UI a separate layer, so your processing modules shouldn't have anything to do with the UI layer.

In this case, your modules should have a method called publish_progress(callback) which callback is a function to be called for each progress step (more info). Then, in your UI layer define a function which is given an integer (between 0 to 100) and updates the progress bar. Once you've defined it, you should register it with publish_progress method of your modules.

def progress_callback(prg):
    self.dlg.progressBar.setValue(prg)

Registering it:

my_module.publish_progress(progress_callback)

Calling the callback in your module:

progress_callback(0)
...
# do something
...
progress_callback(20)
...
# do something
...
progress_callback(100)
frogatto
  • 28,539
  • 11
  • 83
  • 129
  • @hi-im-frogatto I think I'm getting the idea, but still there are a few things I don't understand. **1. Main (GUI) module:** a) If I have to define the `progress_callback` inside my GUI class, why there is no `self` in the definition? b) where in the main code I have to put registering statement? **2. Processing module(s):** a) should I define `publish_progress` inside a processing function or as a separate method? b) Based on your kind reply, all the real work is done by `progress_callback`, which I import from the main module. Then what should this `publish_progress` method do? – Vasily Oct 18 '16 at 12:26
  • 1
    @Vasily **1.a:** No. `progress_callback` isn't supposed to be a _method_ of `Main` class. It's instead a local function that can be defined inside one of the main's methods. **1.b:** Registering statement could be right after the UI initialization (or somewhere else). **2.a:** It could be a method of the processing class. (or a function of the module). **2.b:** `publish_progress` is just a register function/method and does nothing else. If something is still unclear, feel free to ask. – frogatto Oct 19 '16 at 05:07
  • 1
    @Vasily This approach is kind of Callback pattern. [Check it out at Wikipedia](https://en.wikipedia.org/wiki/Callback_(computer_programming)). – frogatto Oct 19 '16 at 05:10
  • @hi-im-frogatto yes, I've read [wiki](https://en.wikipedia.org/wiki/Callback_(computer_programming)), [this](http://code-maven.com/function-or-callback-in-python) and [this](http://curiosityhealsthecat.blogspot.ru/2013/07/using-python-decorators-for-registering_8614.html) but I still cannot understand `the_caller` - `the_callback` relation in my case. I see that you've already explained it all in a great detail, but since this is a very first time I'm using this it's still hard to implement. But I see that it is a very important thing to learn so I won't give up no matter how dumb I am ;) – Vasily Oct 19 '16 at 20:22
  • [Here](http://stackoverflow.com/questions/40140531/report-progress-to-qprogressbar-using-variable-from-an-imported-module#40140793) I opened another question with a simple but detailed version of the code. I believe it could be a bit easier if I can display a whole picture. Thank you for you help, I'm sure I'll be laughing at myself when I finally understand it completely. – Vasily Oct 19 '16 at 20:36