Home > Software design >  How do I bring the OptionMenu selection from Tkinter from one class to the other without importing t
How do I bring the OptionMenu selection from Tkinter from one class to the other without importing t

Time:09-15

Good morning,

I have a question that I am stuck on. Once I have the class View that deals with the creation of all the widgets of Tkinter: In the View I have created a drop down menu that shows all the COM ports detected on the computer

'''

class View():

controller = Controller() #create instance of controller

self.portVar = tk.StringVar() 
self.portVar.set(self.controller.paramset.port[0])

self.port_menu = ttk.OptionMenu(self, self.portVar,
                    self.controller.paramset.port[0], *self.controller.get_ports())
self.port_menu.pack(in_=self.portframe, side=tk.LEFT)

'''

class Controller: The controller performs a measurement, which requires the COM port for communication with the measuring device.

There is a line for this in the source code here in the controller: '''

self.device = device(port = "Here the selection from the DropdownMenu from View")

'''

How can I bring the DropDown menu selection from the view into the controller without importing the view in the controller class?

CodePudding user response:

This looks like the Controller is known in the View. Besides that in terms of a MVC the View shouldn't know of the Controller and the Controller shouldn't know about the View. Every communication will be done by the (data-)Model.

class View():
    ...
    controller = Controller() #create instance of controller

    self.portVar = tk.StringVar() 
    self.portVar.set(self.controller.paramset.port[0])

    self.port_menu = ttk.OptionMenu(self, self.portVar,
                        self.controller.paramset.port[0], *self.controller.get_ports())
    self.port_menu.pack(in_=self.portframe, side=tk.LEFT)

Anyway, assuming the indention is like in the above code and the this snippet is also part of the __init__method. You could achieve that in with different approaches.

You could use setattr(obj, name, self.portVar.get()), but since I do not know how your controller is working and for me it looks like it gets garbage collected if there is nothing keeping that object alive, this seems not the right approach.

You could have a function that parses the selection to the controller. In your controller you have to define something like:

def receive_selection(self, value):
    print('Yay, I can work with the selected data!')

since the OptionMenu of tkinter is not very well designed it lacks of possibilities, but what you can always do, as long as you use a tkinter.AnyVariable is add a trace. As an example:

import tkinter as tk
from itertools import cycle

def printer(*args):
    print(var.get())

def coroutine():
    val = str(next(v_cycl))
    var.set(val)
    root.after(500, coroutine)

values = [1,2,3,4,5,6,7,8,9]
v_cycl = cycle(values)

root = tk.Tk()
var = tk.StringVar(root)
var.trace_add('write', printer)
coroutine()
root.mainloop()
  • Related