I am programming a GUI using Tkinter. In one of the classes I have defined a variable (entry_filename) and would like to use it in another class. A part of the code is as follows:
class Loginpage(tk.Frame,Search):
def __init__(self,parent,controller):
tk.Frame.__init__(self,parent)
self.controller=controller
self.label_user=tk.Label(self, text="Username")
self.label_user.grid(row=0, column=0)
self.label_pass=tk.Label(self, text="Password")
self.label_pass.grid(row=1, column=0)
self.entry_user=tk.Entry(self)
self.entry_user.focus_set()
self.entry_user.grid(row=0, column=1)
self.entry_pass=tk.Entry(self,show="*")
self.entry_pass.grid(row=1, column=1)
self.button=ttk.Button(self, text="Login",command= self.Logincheck)
self.button.grid(columnspan=2)
def Logincheck(self):
global username
global password
try:
username=self.entry_user.get()
password=self.entry_pass.get()
self.ssh = paramiko.SSHClient()
self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.ssh.connect(server, username=username, password=password)#input your username&password
button1 = ttk.Button(self, text="Click to Continue",command= lambda: self.controller.show_frame(Inputpage))
button1.grid(columnspan=2)
except:
tm.showerror("Login error", "Incorrect username/password")
class Inputpage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller=controller
self.filein_label=tk.Label(self,text="Input file name")
self.filein_label.grid(row=0,column=0)
self.entry_filename=tk.Entry(self)
self.entry_filename.focus_set()
self.entry_filename.grid(row=0,column=1)
self.button1 = ttk.Button(self, text="Click to Continue",command= lambda: self.controller.show_frame(Graphpage))
self.button1.grid(columnspan=2)
class Graphpage(tk.Frame,Inputpage):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller=controller
self.label = tk.Label(self, text="Graph Page!", font=LARGE_FONT)
self.label.pack(pady=10,padx=10)
button1 = ttk.Button(self, text="Back to Input Page",command=lambda: self.controller.show_frame(Inputpage))
button1.pack()
filename=Inputpage.entry_filename.get()
The Graphpage calls the variable filename which is later used to create the graph (that part of the code is omitted here). When the code is run the following error is returned:
TypeError: Cannot create a consistent method resolution
order (MRO) for bases Frame, Inputpage
It seems that I have hit another roadblock in attempting to solve the earlier issue, however, if I can understand the resolution to this, I hope that I can attempt to solve further issues. Thanks for your help
ssh
is a local variable inside functionLoginCheck
so you are not able to retrieve it from another class. One thing possible to do is to definessh
asself.ssh
so it will be accessible throughinstance_of_Loginpage.ssh
. It will work only when you will pass an instance ofLoginpage
into an instance ofGraphpage
. If you need access to an ssh connection from many places I suggest to create another class just to handle ssh (you can use Borg patter to achieve it).The culprit is that you should not share class member variables that way.
If different classes share some common data, that data is probably another class and they can inherit from it.
In above case every instance of A and every instance of B share all the CommonData class variables, like client.
You can use multiple inheritance too. define all common data as CommonData attributes and use CommonData as a class to hold data, like in above example, don't create instances from it:
A simpler option would be to just define a variable CommonData in the outer scope and use it from anywhere:
But global variables are generally seen as a bad thing in a program as their use can become a problem for several reasons.
Yet another way is to pass the variable to the object initializer. That makes the instance to keep its own value copied from the creation value:
If you run all the code above it will print
Edit:
See my comment to your answer and a simple example here. Here I opt for two global references to tkinter StringVars. The stringvars exist themselves in the Tk() namespace, like the widgets; besides they are global Python names.
Now in the next example see how I turn the stringvars into variables of Page1 and Page2 instances (not classes), making them local instead of global. Then I am forced to pass a reference for the widget page1 object into the widget page2 object.
This looks more close to what you are asking.
About MRO trouble, if you avoid multiple inheritance it won't happen.
Or you deal with it usually by using
super()
In your case the error is because you store the widget in the object/instance (in
self.somename
), and then you try to invoke a widget method qualifying with the class name. There is no widget there in the class for you to use a method.So the search using the method resolution order fails, because there is no corresponding name there.
Note that I have not used multiple inheritance, so I could have just written
tk.Frame.
instead of callingsuper
. I like super because it makes clear in the text that I am invoking the parent class but super is really needed only when there are multiple parents and various levels of subclassing (usually forming a diamond shape).Now the example: