How to call this tkinter gui function? - python

How do i access windows function in Mygui class?
I want to create colored content in my tkinter box#
but i can't pass value to it.
from tkinter import *
class Mygui:
def window(self, colour):
self.main_window=Tk()
self.main_window.geometry('300x100')
self.main_window.title('Login')
self.top_frame=Frame(self.main_window)
self.top_frame.pack()
self.label=Label(self.top_frame, fg=colour, text="Sample Text", width=45)
self.label.pack(side="top")
self.label1=Label(self.top_frame,text=" ", width=45)
self.label1.pack(side="top")
self.my_button = Button(self.main_window, text="Retry", command=self.do_something, height=2, width=18)
self.my_button.pack()
mainloop()
def do_something(self):
print('ok')
class login:
def example(self):
print("Start")
Mygui.window('blue')
a = login.example(' ')
The error i get is:
Start
Traceback (most recent call last):
File "B:/data/loginMech/test.py", line 25, in <module>
a = login.example(' ')
File "B:/data/loginMech/test.py", line 23, in example
Mygui.window('blue')
TypeError: window() missing 1 required positional argument: 'colour'

Mygui is a class, not a function. So, you have to construct an instance of it, like this:
gui = Mygui()
And then you can call methods on that instance:
gui.window('blue')
When you write Mygui.window, that's an unbound method, which you can call by explicitly passing it a self argument along with its other arguments. But you'd still need to have something to pass as that self:
gui = Mygui()
Mygui.window(gui, 'blue')
In general, you don't want to do this. There are cases where unbound methods are useful, but if you have one, you probably know you have one.
And you need to do the same thing with login:
log = login()
log.example()
By calling login.example, you're using an unbound method again. And then you're passing ' ' as the self argument. This doesn't make any sense, because ' ' is not a login instance, but CPython 3.x happens to not check for that error, so you get away with it.

Abarnet pointed out one fix however in Tkinter it might be better to inherit from the Tkinter class Tk to start you GUI.
Take this example. A much smaller amount of code and produces the same results desired.
import tkinter as tk
class MyGUI(tk.Tk):
def __init__(self, colour):
tk.Tk.__init__(self)
self.geometry('300x100')
self.title('Login')
tk.Label(self, fg=colour, text="Sample Text", width=45, pady=10).grid(row=0, column=0)
tk.Button(self, text="Retry", command=self.do_something, height=2, width=18).grid(row=1, column=0)
def do_something(self):
print('ok')
MyGUI("Blue").mainloop()
Results:

Related

Python Tkinter: What syntax in main() will get the return value of a method bound to button in a class instance?

New to tkinter, I want a short program to:
create a window to take user input, by means of an entry widget and a submit button
capture the input and return it to main, so that I can do something else with it.
The following code creates the window and captures input, but breaks at the next-to-last line.
from tkinter import *
from tkinter import ttk
class TxtEntryWindow:
def __init__(self):
self.root = Tk()
self.frame = ttk.Frame(self.root).pack()
self.box = ttk.Entry(self.frame)
self.box.pack()
self.but = ttk.Button(self.frame, text='Submit', command=self.capture_txt)
self.but.pack()
self.root.mainloop()
def capture_txt(self):
txt = self.box.get()
return txt
win = TxtEntryWindow()
user_input = win.capture_txt()
print(user_input)
Here's a copy of the error message:
Traceback (most recent call last):
File "C:...\wclass.py", line 22, in
user_input = win.capture_txt()
File "C:...\wclass.py", line 17, in capture_txt
txt = self.box.get()
File "C:...\Python\Python310\lib\tkinter_init_.py", line 3072, in get
return self.tk.call(self._w, 'get')
_tkinter.TclError: invalid command name ".!entry"
I have no idea what this means. I suspect that dependence of "txt" on the button event in the class prevents "win.capture_txt()" in main() at the bottom from fetching the user input.
Can anyone shed light?
Consulted Python's official documentation (unintelligible), Tkinter's official tutorial and command reference. Searched numerous analogies on StackOverflow and on youtube. Googled the error message itself. I've tried to strike out on my own and rewrite the critical command about twenty times. Blind intuition leads nowhere. Stabbing in the dark.
The error means that the entry widget (self.box) has been destroyed when the line user_input = win.capture_txt() is executed.
You can use an instance variable to store the input text instead and access this instance variable after the window is destroyed:
from tkinter import *
from tkinter import ttk
class TxtEntryWindow:
def __init__(self):
self.text = "" # initialize the instance variable
self.root = Tk()
self.frame = ttk.Frame(self.root).pack()
self.box = ttk.Entry(self.frame)
self.box.pack()
self.but = ttk.Button(self.frame, text='Submit', command=self.capture_txt)
self.but.pack()
self.root.mainloop()
def capture_txt(self):
# save the user input into the instance variable
self.text = self.box.get()
self.root.destroy()
win = TxtEntryWindow()
print(win.text) # show the content of the instance variable

AttributeError: type object 'gui' has no attribute 'label'

I want to change a labeltext from outside of the class through a setter method in the class. Im just getting
AttributeError: type object 'gui' has no attribute 'label'. I tried changing the text through label['text']; label.config(text = 'X')
from tkinter import *
class gui:
def __init__(self):
self.root = Tk()
self.label = Label(self.root, text='Y')
self.label.pack()
self.button = Button(self.root, text='Click', command=self.__btnClick)
self.button.pack()
mainloop()
def __btnClick(self):
changeText()
def setLabelText(self):
self.label['text']= 'X'
def changeText():
gui.setLabelText(gui)
if __name__ == '__main__':
window = gui()
I dont know if it helps but heres my full code
https://pastebin.com/bT43NgpH
Thank you for your help!
You have to call setLabelText on an instance of gui not on the class itself. When you call setLabelText in __btnClick you have to give the instance of gui as a parameter to this function. You've got the instance in the parameter self.
So __btnClick should be altered to:
def __btnClick(self):
changeText(self)
And changeText should be altered to:
def changeText(the_window):
the_window.setLabelText()
I'd like to add a link to the Style Guide for Python Code. Your code is hard to read for an experienced programmer (OK, not that hard, but harder than necessary) because you don't follow the naming conventions.

tkinter python function takes 1 argument, given 2

I'm getting this error when I try to run my code:
File "./countdown.py", line 36, in <module>
app = Application(root)
File "./countdown.py", line 16, in __init__
self.create_buttons(self)
TypeError: create_buttons() takes exactly 1 argument (2 given)
Here's my code:
import Tkinter as tk
class Application(tk.Frame):
"""Countdown app - simple timer"""
def __init__(self, master):
"""initialize frame"""
tk.Frame.__init__(self, master)
#super(Application, self).__init__(master)
self.grid()
self.create_buttons(self)
def create_buttons(self):
self.startBttn = Button(app, text = "Start")
self.startBttn.grid()
self.stopBttn = Button(app, text = "Stop")
self.stopBttn.grid()
self.resetBttn = Button(app, text = "Reset")
self.resetBttn.grid()
### Main Code ###
# create the root window using Tk - an object of tkinter class
root = tk.Tk()
# modify the prog. window (set size, title, etc.)
root.title("Countdown")
root.geometry("200x100")
#instantiate Application
app = Application(root)
I've been looking for an answer to this for a while but haven't been able to apply other people's solutions to my code- any ideas? If I remove the tk. before Frame in the class Application declaration I get an error that says Frame not found. If I use super(Application, self).__init__(master) instead of the line above it, I get a type error must be class not class object.
Don't explicitly pass self when calling a bound method. Call it like this:
self.create_buttons()
By calling the method with self.create_buttons(self) the function receives two arguments: the implicit self that is passed when calling a bound method (Python does this automatically), and the explicit self that you pass in the method call.
There are also some other problems with create_buttons() which you can fix with this code:
def create_buttons(self):
self.startBttn = tk.Button(self, text = "Start")
self.startBttn.grid()
self.stopBttn = tk.Button(self, text = "Stop")
self.stopBttn.grid()
self.resetBttn = tk.Button(self, text = "Reset")
self.resetBttn.grid()
The changes are that you need to use tk.Button to reference the Button class, and to pass self to tk.Button which is a reference to the parent frame. Here self is the Application instance which is a subclass of tk.Frame - hence self is a frame.
Finally you need to add a call to mainloop():
#instantiate Application
app = Application(root)
root.mainloop()
Regarding the problem with super, the tkinter classes are of the "old-style" type and do not support super(). Therefore you must call the base class with tk.Frame.__init__(self, master).
There is a workaround by using multiple inheritance and including object as a base class. If you declare Application as :
class Application(tk.Frame, object):
def __init__(self, master):
"""initialize frame"""
super(Application, self).__init__(master)
then you can use super(), but it's hardly worth the effort.

How to hide a button by using a class function in python

from tkinter import*
root = Tk()
shape = Canvas(root)
class GUI():
def __init__(self):
pass
def create_button(self, info, boom, posit):
self.Button(root)
self.config(text=info)
self.bind("<Button-1>",boom)
self.grid(column=posit[0],row=posit[1])
def create_label(self, info, posit):
self.Label(root)
self.config(text=info)
self.grid(column=posit[0],row=posit[1])
def go_away(self):
print("GO AWAY before")
self.button.grid_forget()
print("GO AWAY")
def make_GUI():
root.title("Hexahexaflexagon")
hexahexa = GUI()
quit_butt = GUI()
quit_butt.create_button("Exit","root.destroy()",[0,1])
quit_butt.go_away()
make_GUI()
root.mainloop()
Okay so I am trying to write a class function to just hide (and if not that then delete) a button created by tkinter, I'm new to classes and the error message I keep getting is that the GUI class does not have that function or that object does not have that attribute, I've tried code such as frm.forget(), .lower(), .grid_forget() but there not working for me.
The traceback is:
Traceback (most recent call last):
File "N:\HW\Hexahexaflexagon generator.py", line 94, in <module>
make_GUI()
File "N:\HW\Hexahexaflexagon generator.py", line 63, in make_GUI
quit_butt.go_away()
File "N:\HW\Hexahexaflexagon generator.py", line 51, in go_away
self.button.grid_forget()
AttributeError: 'function' object has no attribute 'grid_forget'
The problem is this line:
self = Button(root)
You are redefining self from referring to the current object, to now refer to a different object. You have the same problem further down with a label. This is simply not how python works.
You must store the widgets as attributes on self, not as self itself.
self.button = Button(root)
...
self.label = Label(root)
Once you do that, you can hide the button or label with grid_forget since you're using grid to make it visible:
self.button.grid_forget()
You have another problem in that you're passing in a command as a string. This will not work the way you think it does. If you want to be able to pass in a function, it needs to be a reference to an actual function:
quit_butt.button("Exit",root.destroy,[0,1])

Python 3.2, Tkinter class declarations, class undefined when subclassing

I'm learning python and encountering issues with what appears to be class decorators from tkinter. I can get tkinter to work as long as I never try to decorate with Frame. The code below gives me no errors, and no window. For whatever reason, the class I define, never gets defined. Below is my code. Below that is testing i've done based on similar questions regarding tkinter.
>>> from tkinter import *
import tkinter
class Apples:
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.button = Button(frame, text="Quit", fg="blue", command=frame.quit)
self.button.pack(side=LEFT)
self.hellos = Button(frame, text="Hello", command=self.say_hello)
self.hellos.pack(side=LEFT)
def say_hello(self):
print("Hello World!")
root = Tk()
app = Apples(root)
root.mainloop()
No window shows up. No error. So I check on the class...
>>> test = Apples(root)
Traceback (most recent call last):
File "<pyshell#54>", line 1, in <module>
test = Apples(root)
NameError: name 'Apples' is not defined
>>>
I found a similar question Creating buttons with Python GUI and attempted the code from pythonMan. I still am encountering the same class declaration issue.
>>> from tkinter import *
class Application(Frame):
"""A GUI application with three button"""
def __init__(self,master):
self.master = master
self.create_widgets()
def create_widgets(self):
#"""Create three buttons"""
#Create first buttom
btn1 = Button(self.master, text = "I do nothing")
btn1.pack()
#Create second button
btn2 = Button(self.master, text = "T do nothing as well")
btn2.pack()
#Create third button
btn3=Button(self.master, text = "I do nothing as well as well")
btn3.pack()
root = Tk()
root.title("Lazy Button 2")
root.geometry("500x500")
app = Application(root)
root.mainloop()
>>> Application
Traceback (most recent call last):
File "<pyshell#58>", line 1, in <module>
Application
NameError: name 'Application' is not defined
>>>
I can think something is not being declared properly, but is not generating a syntax error. Any help would be greatly appreciated.
I think you don't need an ">>>" sign.
"from Tkinter import *"
Assuming your code is properly reproduced in the second part of your question, you're defining your class incorrectly. You have def __init__ at the same level of indentation as class Application(Frame). Your methods need to be indented for them to be part of the class.
The code in the first part of your question works fine for me.

Categories

Resources