How to get the value from one class function in tkinter - python

This attempt is try to get the value from a function in class One which is retrieve when the function is call. Then the value [string1] would be passed as a parameter for class Two's method call which's within tkinter, any idea on how can it be attain
from tkinter import Tk, Label, Button
from tkinter import *
from tkinter.ttk import *
class One:
def __init__(self, master):
self.master = master
master.title("Test")
self.greet_button = Button(master, text="Test", command=self.do)
self.greet_button.pack()
def do(self):
...some action...
string1='test'
return string1
class Two:
def write(self, str):
...some action...
#object instantiate within tkinter
root = Tk()
p0 = One(root)
p0.do()
p1 = Two()
p1.write(string1)
root.mainloop()

##from tkinter import Tk, Label, Button
##
##from tkinter import *
##from tkinter.ttk import *
####why are you importing some and then everything?
import tkinter as tk
class Reader_Class(tk.Frame):
def __init__(self, master, writer_class):
tk.Frame.__init__(self,master)
self.master = master
master.title("Test")
self.writer = writer_class
self.greet_button = tk.Button(self, text="Test", command=self.do)
self.greet_button.pack()
def do(self):
string1='test'
self.writer.write(string1)
class Writer_Class(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self,master)
def write(self, test):
print(test)
root = tk.Tk()
writer = Writer_Class(root)
writer.pack()
reader = Reader_Class(root, writer)
reader.pack()
root.mainloop()
Explaination:
So first of all, it isnt necessary to import stuff twice.
Second you need to pass through the interface a reference, therefor you need to have reference. Thats why it makes sense to use the construktor first on the writer_class.
Next you give the reference as a parameter to the reader_class.
reader = Reader_Class(root, writer)
In the reader_class you keep a reference in the local_scope by using the syntax self..
self.writer = writer_class
Finally you use the reference of that class and calling a method of this class, where you can pass through a parameter of your choice.
self.writer.write(string1)

Related

simple window with an enter field

i'm a new programmer and there are certainly several errors but this shouldn't be difficult to spot. I need to create a simple window with a field named "Concorrente 1:" and an entry field displayed by function named lacopertina(). I don't understand where is the error:
import tkinter as tk
from tkinter import *
from tkinter.ttk import *
from tkinter import ttk
class schermoiniziale(tk.Frame):
def lacopertina():
print(gio1)
#return (tot1)
def __init__(self):
global gio1
#tot1=0
#schermo1=Tk()
self.gio1=tk.StringVar()
lab1=ttk.Label(self, text="Concorrente 1:")
lab1.pack()
ent1=ttk.Entry(self, textvariable=self.gio1)
ent1.pack()
pulsante = ttk.Button(self, text="Inizio", textvariable=self.gio1, command=self.lacopertina)
pulsante.pack()
def main():
schermoiniziale().mainloop()
if __name__== "__main__":
main()
I would suggest you to go through some tutorials on Python OOP.
I have modified your code as below with some comment:
# avoid using wildcard import
import tkinter as tk
from tkinter import ttk
class schermoiniziale(tk.Frame):
def __init__(self, master, **kw):
# need to call __init__() of inherited class
super().__init__(master, **kw)
self.gio1 = tk.StringVar()
lab1 = ttk.Label(self, text="Concorrente 1:")
lab1.pack()
ent1 = ttk.Entry(self, textvariable=self.gio1)
ent1.pack()
# removed textvariable=self.gio1 as I think you actually don't need it
pulsante = ttk.Button(self, text="Inizio", command=self.lacopertina)
pulsante.pack()
def lacopertina(self):
# use .get() to get the content of a StringVar
print(self.gio1.get())
def main():
# need to create the root window before creating other widget
root = tk.Tk()
# pass root window as the parent of the widget
frame = schermoiniziale(root)
frame.pack()
# start the tkinter mainloop
root.mainloop()
if __name__== "__main__":
main()

Tkinter - Give name of variable option of a Scale through a class

I am starting to learn OOP and I've been struggling with some basic stuff.
In the code below, I have created a class Scales() that I want to use to create 2 very similar scales, with only their variable option being different.
How can I pass the name of these variables as a parameter when I call Scales() and make both of them a DoubleVar type?
from tkinter import *
from tkinter import ttk
from PIL import Image, ImageTk
import numpy as np
class Scales(Frame):
def __init__(self, parent, variable_name, label_text, initial_value,
final_value):
self.parent = parent
self.bar_length = 200
self.variable_name = variable_name
self.label_text = label_text
self.initial_value = initial_value
self.final_value = final_value
# self.variable_name = DoubleVar()
self.scale_name = Scale(self.parent, variable=self.variable_name,
orient=HORIZONTAL,
from_=self.initial_value,
to=self.final_value,
length=self.bar_length, cursor="hand",
label=self.label_text)
class MainApplication(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
self.slice_number_scale = Scales(self.parent, slice_number,
"Slice Number", 1, 24)
if __name__ == '__main__':
root = Tk()
root.geometry("800x600")
MainApplication(root)
root.mainloop()
If the variables are going to live as instance variables of your Scales class, then there's absolutely no reason to give them separate names; every reference to them is going to be in the context of some particular instance. You'd probably want to define a get() method that does something like return self.variable.get(), for the convenience of the class's user.
If the variables live somewhere outside the class, then Scales should not care what their names are; pass the variable itself as a parameter to the class constructor, and pass it on as the variable= option to Scale().
Just create the variables in each Scale class instance that is created, then access them through the instance's name. Here's what I mean:
from tkinter import *
#from tkinter import ttk
#from PIL import Image, ImageTk
#import numpy as np
class Scale(Frame):
""" Dummy version of class for testing and illustration. """
def __init__(self, parent, orient=None, from_=None, to=None, length=None,
cursor=None, label=None):
Frame.__init__(self, parent) # initialize base class
self.variable = DoubleVar() # create variable and make attribute
class Scales(Frame):
def __init__(self, parent, label_text, initial_value,
final_value):
self.parent = parent
self.bar_length = 200
# self.variable_name = variable_name
self.label_text = label_text
self.initial_value = initial_value
self.final_value = final_value
# self.variable_name = DoubleVar()
self.scale1 = Scale(self.parent,
# variable=self.variable_name,
orient=HORIZONTAL,
from_=self.initial_value,
to=self.final_value,
length=self.bar_length,
cursor="hand",
label=self.label_text)
self.scale1.pack()
class MainApplication(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
slice_number = 42
self.slice_number_scale = Scales(self.parent, slice_number, 1, 24)
root = Tk()
app = MainApplication(root)
app.mainloop()
After doing this you can access the variable for each Scale instance within a Scales instance as self.scale1.variable (and self.scale2.variable after you add it). Within the MainApplication instance they can be referred to as self.slice_number_scale.scale1.variable (and self.slice_number_scale2.variable).
For the latter you might want to add methods to class MainApplication to make such references more succinct, such as:
class MainApplication(Frame):
....
def get_scale_var1(self):
return self.slice_number_scale.scale1.variable.get()

Tkinter event not trigerred in all child windows.

in my code, the main window is emitting event signals, which are to be caught by the child windows, which will show the change in a label. But only the last child window catches the event signal, and changes it's label. what's wrong?
from Tkinter import *
from threading import Timer as tt
class main(Tk):
def __init__(self):
Tk.__init__(self)
tt(.5,self.timedsig).start()
for i in range (5):
child(self,i)
def timedsig(self):
self.event_generate("<<timedsig>>")
tt(.5,self.timedsig).start()
class child(Toplevel):
def __init__(self,master,num):
Toplevel.__init__(self)
self.title(str(num))
self.num=num
self.var=IntVar()
self.var.set(0)
Label(self,textvariable=self.var).pack()
self.master=master
self.master.bind("<<timedsig>>",self.changelabel)
def changelabel(self,e):
print self.num,self.var.get()
self.var.set(self.var.get()+1)
if __name__=="__main__":
main().mainloop()
Calling bind also unbinds all previous functions. To bind an additional function, you need to use the optional 3rd argument:
self.master.bind("<<timedsig>>",self.changelabel, '+')
But that's pretty silly to do in your case when you can simply pass the variable to the instances:
import Tkinter as tk
class Main(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.var = tk.IntVar(value=0)
for i in range (5):
Popup(self, i, self.var)
self.timedsig() # start the looping
def timedsig(self):
self.var.set(self.var.get() + 1)
self.after(500, self.timedsig) # call this again in 500 ms
class Popup(tk.Toplevel):
def __init__(self, master, num, var):
tk.Toplevel.__init__(self)
self.title(str(num))
lbl = tk.Label(self,textvariable=var)
lbl.pack()
if __name__=="__main__":
root = Main()
root.mainloop()
Also, that's not what we usually call a "child". It's just a different object.

Using python class with tkinter

From what I read, it is best practice to wrap code for a GUI in a class. How do I do this? I have come up with the following code based on some examples I have looked at, but this does not work as apparently DropdownMenu isn't defined? I have used this function successfully without the class wrapping.
import Tkinter as tk
import tkFileDialog
import os
class Window(tk.Frame):
def DropdownMenu(options,status,name):
optionFrame = tk.Frame(root)
optionLabel = tk.Label(optionFrame)
optionLabel["text"] = name
optionLabel.pack(side=LEFT)
var = StringVar(root)
var.set(status)
w = tk.OptionMenu(optionFrame, var, *options)
w.pack(side=LEFT)
optionFrame.pack()
return w
def __init__(self,parent):
tk.Frame.__init__(self,parent)
ndim_options = DropdownMenu(("1","2","3"),'-',"Number of dimensions")
if __name__ == "__main__":
root = tk.Tk()
Window(root).pack()
root.mainloop()
When you call DropdownMenu (inside the class), use self ...
ndim_options = self.DropdownMenu((...

interaction of different elements of window in Tkinter

I have the app with Tkinter, for example:
from Tkinter import *
from ttk import *
class MyMenu(Menu):
....
class MyNotebook(Notebook):
....
tk=Tk()
f1=Frame(master=tk)
f2=Frame(master=tk)
menu=MyMenu(master=f1)
notebook=MyNotebook(master=f2)
I want to add command in menu, which will add new tab in notebook. How can i do this?
P.S. f1 != f2 It's important!
P.P.S. functions, that used as commands in menu may be in another file
One of the frames is not necessary for the menu, since it should be configured with the window and not placed with the geometry manager. Something similar to this can do the job:
# ...
def add_tab():
text = "Tab {}".format(len(notebook.tabs()))
frame = Frame(notebook, width=100, height=100)
notebook.add(frame, text=text)
menu=MyMenu()
menu.add_command(label="Add tab", command=add_tab)
tk.config(menu=menu)
However, I recommend you to: a) Define a class instead of using global variables; and b) Don't use import * since Tkinter an ttk uses the same name for different classes. It will be not only more organized, but also easier to read:
import Tkinter as tk
import ttk
class MyMenu(tk.Menu):
pass
class MyNotebook(ttk.Notebook):
pass
class App(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.frame = ttk.Frame(self)
self.notebook = MyNotebook(self.frame)
self.frame.pack()
self.notebook.pack()
self.add_tab()
menu = MyMenu()
menu.add_command(label="Add tab", command=self.add_tab)
self.config(menu=menu)
def add_tab(self):
text = "Tab {}".format(len(self.notebook.tabs()))
frame = ttk.Frame(self.notebook, width=100, height=100)
self.notebook.add(frame, text=text)
app = App()
app.mainloop()
The solution is simple: for an instance of class A to interact with an instance of class B, class A needs a reference to the instance of class B. That means you need to either pass it in to the constructor, or set if after creation. For example:
class MyMenu(Menu):
def __init__(self, notebook):
...
self.add_command("New page", command=notebook.add(...))
...
notebook = Notebook(...)
menu = MyMenu(notebook)
Another way -- which I think is better -- is to pass what is sometimes called a controller -- a class that knows about all the widgets, or provides an interface to the widgets. For example, you could implement your app as a class and use an instance of that as your controller:
class MyMenu(Menu)
def __init__(self, app=None):
...
self.add_command(..., command=app.add_tab)
class App(Tk):
def __init__(self):
...
self.menu = MyMenu(self, controller=self)
self.notebook = Notebook(...)
...
def add_tab(self, label):
frame = Frame(self)
self.notebook.add(frame, text=label)
app = App()
app.mainloop()

Categories

Resources