Python – Getting Variables from Other Modules in GUI and MVC

mvcpython

I am trying to split my code into different layers:
GUI, reading the GUI, creating input, calculating the model, interpreting data, creating view, sending the view to the GUI.
Somebody told me about MVC and I would like to try to build my program that way. But I'm a little confused about how to exchange information between those modules. I'm running into problems with undefined global names and so forth.
My model is written in matlab and consists of a simulation. The GUI is supposed to present the data in plots.

My actual problem is: how to connect the different modules/classes/files to each other if they are supposed to be as independent as possible?

For example: I'm creating a GUI in one file, like this:

# userinterface.py

class Userinterface(object):
    def __init__(self, controller):
        self.controller = controller
        self.buildGUI()
        return

    def buildGUI():
        # build lots of widgets and stuff
        widget = tk.Thewidget(options=values, command=self.controller.onclick)

And call it my interface. In order to keep this file nice and clean, I would like to define all functions to handle button clicks and read fields in another file and I guess this is what you would call the controller part:

# main.py
    import userinterface as gui

    class Controls(object):
        def onclick(self):
            # read values from widgets and do stuff
            var1 = GUI.widget_entry.get()
            # Call some other function with var1 etc.

if __name__ == '__main__':
    GUI_controls = Controls()
    GUI = gui.UserInterface(GUI_controls)

But how do I do to connect these two? In my example above, I'm handing over an instance of my Controls object. But then I read about Events too or Inheritance or subclasses.

I'm rather new to programming and started all this 2 months ago, so I'm struggling sorting all these theories.

If somebody could point out to me what the way of communication between my modules/files should be and what such a meeting-point looks like. Or just give me a link that I can study (like Javier did, although I'll have to read this thing more than once)

Best Answer

You're on the right track. The controller is what binds the app together, so passing it around to the various view and model classes is fine.

However, don't think that just because you have a controller, all widgets must use that controller for everything. For instance, I wouldn't put the onclick method in the controller. The controller should be for routing business logic, but what you're doing is mostly specific to the GUI.

I think a good general rule of thumb is that GUI events and callbacks should be within the GUI module. They then call the controller when interfacing with business logic. Fetching a string from the GUI itself is not business logic.

So, instead of:

# GUI module
button = Button(..., command=controller.on_click)

# Controller module
def on_click():
    var1 = GUI.widget_entry.get()
    self.do_something(var1)

I would do this:

# GUI module
button = Button(..., command=on_click)
def on_click():
    var1 = widget_entry.get()
    controller.do_something(var1)

With the above, the controller doesn't need to know what widgets are part of the GUI. All it does is provide an interface through which the GUI can request services.

If you prefer to keep the on_click in the controller, that's possible too, and not completely unreasonable. However, instead of building in knowledge of the GUI widgets into the controller, give the GUI an interface that the controller can use.

For example, instead of doing GUI.widget_entry.get(), the controller would call an accessor such as GUI.get_entry_widget_value(). That allows you to refactor the GUI without having to change the controller. If you move the entry to the_widget_entry instead of widget_entry, the controller can be completely unaware and still function properly.

Related Topic