I don't understand what the problem is with my code - it has everything i need and should execute fine.
No error is generated so I believe it is a logic error but I don't know how to fix it per say.
Help with this would be much appreciated.
from tkinter import *
from tkinter import ttk
def Payment_Computation(self):
def Getting_Payment_in_Monthly():
def __init__(self):
You are missing some vital parts of an oop program:
from tkinter import *
from tkinter import ttk
class MainApplication(): # create class
def __init__(self):
# method code
def Payment_Computation(self):
# method code
def Getting_Payment_in_Monthly(self, Amount_Loan, mon_rate_interest, no_of_yrs):
# method code
if __name__ == "__main__":
MainApplication() # Instantiate class
You need to place the code in a class. You then need to instantiate the class as exemplified above.
Read more about oop program structure in Best way to structure a tkinter application?
You didn't call the __init__() function. Please check carefully :)
Related
i am trying to make a library management system in python using oops and tkinter.
here is the code:
from tkinter import *
class library():
def __init__(self):
self.screen=Tk()
self.title='LOGIN'
self.screen.minsize(800,600)
self.screen.maxsize(800,600)
self.screen.title(self.title)
c=Canvas(self.screen,bg='black').place(x=-10,y=0,height=1000,width=1000)
def screen_work(self):
self.screen_login().screen.destroy()
screen=Tk()
screen.title('LIBRARY MANAGEMENT')
#screen.attributes('-fullscreen',True)
def button(self):
Button(self.screen,text='press',bg='red').place(x=400,y=300)
lib=library()
mainloop()
now ,when i run this program a black screen of dimension '800x600; opens up without any errors but does not show any button.
As Bryan Oakley and JRiggles rightly stated, the button function is never called, so it wouldn't display
updated code
from tkinter import *
class library():
def __init__(self):
self.screen=Tk()
self.title='LOGIN'
self.screen.minsize(800,600)
self.screen.maxsize(800,600)
self.screen.title(self.title)
c=Canvas(self.screen,bg='black').place(x=-10,y=0,height=1000,width=1000)
def screen_work(self):
self.screen_login().screen.destroy()
screen=Tk()
screen.title('LIBRARY MANAGEMENT')
#screen.attributes('-fullscreen',True)
def button(self):
Button(self.screen,text='press',bg='red').place(x=400,y=300)
lib=library()
lib.button()
mainloop()
here's a great resource to learn tkinter in case you're interested!
https://realpython.com/python-gui-tkinter/
You don’t really need to use a function to add a button, you may just leave the button code near the end after the other functions. If you want to keep the function, I think you forgot to declare the function in order for the button to appear.
it doesn't work
i want it to get a number then click those button bellow and then get the result in the message box what should i do?!
from tkinter import *
from tkinter import messagebox
from tkinter import ttk
win=Tk()
#here is my problem
def household():
global s
global math
math="multiply"
x=int(E.get())
s=(x/100)*500
b="your bill is:"+str(s)
messagebox.showinfo("result",b)
def commercial():
global s
x=int(E.get())
if x<=4000000:
s=(x/100)*750
household()
commercial()
E=Entry(win,bg="#87CEFA")
b1=Button(win,text="Household",bg="#4169E1",command=household)
b3=Button(win,text="commercial",bg="#4169E1",command=commercial)
E.place(x=100,y=85,width=100,height=20)
b1.place(x=100,y=165,width=100,height=30)
b3.place(x=150,y=165,width=100,height=30)
You're calling household() and commercial() before you define E. Because you are doing a wildcard import (from tkinter import *) you're importing the constant E from tkinter, which is defined as the string "e".
The solution is:
don't do wildcard imports import tkinter with import tkinter as tk and then use tk. as a prefix for all tkinter objects (tk.Entry(...), tk.Button(...), etc)
Make sure your code runs in the correct order. If you have functions that depend on a variable, make sure those functions aren't called before the variable is defined.
I want to run the tkinter mainloop in the background because I´m following the MVC Pattern, so the Controller gets a Interfaceobject to handle all cares. So I tried to thread it. RuntimeError: Calling Tcl from different apartment occures. Saw no further answers on this topic.
Does anyone have a clue what to do?
Thanks, Max
I don´t have the solution you want for this problem. Maybe this question is can show you what happens.
Anyway you can try by defining all tkinter objects inside the function like this:
from tkinter import Tk
import threading
def mainloop():
root = Tk()
#Your tkinter objects goes here
root.mainloop()
t = threading.Thread(target=mainloop)
t.start()
or you can run the mainloop without threading and thread the Controller:
from tkinter import Tk
import threading
root = Tk()
root.mainloop()
def controler():
while True:
pass
t = threading.Thread(target=controler)
t.start()
thanks #Tomás Gomez Pizarro for one solution. I myself came up with a solution. My Controller etc are set up with a reference(Object) to my Gui. the Gui itself, so the mainloop function is not called until everything is ready. So in Runtime every GuiEvent is passed to the Controller via a thread so that the main loop is not interferred with.
Regards, Max
Trying my hand at Tkinter and just want to add a simple Text field. I've been able to add Entry, Button and Label but Text causes an issue. Here is what I have for Text:
import Tkinter
class myapp_tk(Tkinter.Tk):
def __init__(self,parent):
Tkinter.Tk.__init__(self,parent)
self.parent = parent
self.initialize()
def initialize(self):
self.grid()
self.about = Tkinter.Text(self)
self.about.insert(INSERT, "Hello World!")
self.about.grid(row=0, column=0)
if __name__ == '__main__':
myapp = myapp_tk(None)
myapp.title("My First App!")
myapp.mainloop()
Error received:
NameError: global name 'INSERT' is not defined
I've altered the script heading to include from Tkinter import * which will force it, but I am curious as to why it doesn't work without that change.
INSERT is a constant defined in Tkinter, so you also need to precede it with Tkinter. (given your code), that is you need to do:
self.about.insert(Tkinter.INSERT, "Hello World!")
In general, if you import a module A as import A, then to call a function or variable x from A you always need to do A.x.
INSERT is a Tkinter name, so you'd need Tkinter.INSERT.
It's good practice to avoid "star" imports - doing a star import with Tkinter loads over a hundred names into the global namspace, which is messy and a recipe for name collisions.
You can make things less verbose by doing the import like this:
import Tkinter as tk
Then you can do things like tk.INSERT and tk.Button, etc.
Another benefit of the as tk form is that it makes it easier to migrate your code to Python 3, or to write code that runs on both 2 and 3; the module name in Python 3 is all lowercase: tkinter.
If I want to create a Tkinter GUI simply with statements, I can do this:
from Tkinter import *
root = Tk()
root.title("Test Window")
tkFrame = Frame(root)
tkButton = Button(tkFrame)
[...]
The documentation, however, advises that Tkinter be used with a class definition, subclassing a Frame widget:
class App(Frame):
[...]
I would like to understand why that is so. Why can't we subclass the Frame's container, the window? It appears that is what is done with statements in the first example, so why not in a class definition?
EDIT (following Bryan Oakley's answer):
I would like to instantiate at the highest level of Tkinter, which I assume to be Tk() (though I have come across references stating Frame is the top level, but never mind). Indeed, the following will create a window:
from Tkinter import *
class Application(Tk):
pass
app = Application()
app.mainloop()
...but as soon as I try to add widgets I either get errors or two windows, with the widgets in a new window, depending on how I structure the code. Here's a basic example that will produce a second window with the button:
from Tkinter import *
class Application(Tk):
tkBtn = Button()
tkBtn.pack()
app = Application()
app.mainloop()
Anything more, using self, __init__, etc., produces errors. Could someone point me to working code that instantiates Tkinter at the highest level? Just like all the Frame subclasses I'm seeing, but at the highest level?
There is nothing that says a tkinter class must inherit from a frame. You can inherit from any of the tkinter widgets, or any other classs. If you have found documentation that states otherwise, that documentation is wrong. Using Frame is a logical choice since it is designed to be a container of other widgets, but it is not the only choice.
Personally I inherit from a frame because I find it convenient. Some of my GUIs need the ability to open more than one identical window. By having my main code in a Frame I am able to create multiple windows simply by creating multiple instances of the frame, and packing them in Toplevel widgets.
When you inherit from Tk, you can only have a single instance. In the real world that's usually enough, and there's absolutely nothing wrong with doing it that way. Since I personally write a fair number of tkinter programs, having them all start out exactly the same is convenient for me.
Another good choice is a Canvas since you can easily add a background image, which is not something you can do with a Frame.
Bottom line: you are absolutely not required to inherit from Frame. Inherit from whatever you want.
(the following was written in response to an edit of the original question)
In reference to this code:
from Tkinter import *
class Application(Tk):
tkBtn = Button()
tkBtn.pack()
app = Application()
app.mainloop()
The reason you see two windows is that you're not creating the class properly. You need to call the __init__ method of the superclass before creating widgets, because that's what actually creates the root window. Because you don't, you end up with two windows. You get one that is created implicitly when you add a button to a not-yet-constructed root window, and you get another when your subclass finishes initializing.
The solution is to not take shortcuts, and instead initialize the class properly:
from Tkinter import *
class Application(Tk):
def __init__(self):
Tk.__init__(self)
tkBtn = Button()
tkBtn.pack()
app = Application()
app.mainloop()
Note that this isn't a tkinter-specific problem. When subclassing, unless you have explicit reasons to do otherwise, you always should call the __init__ method of the superclass.
You asked for working examples, here are a couple:
https://stackoverflow.com/a/22424245/7432
https://stackoverflow.com/a/11405393/7432
You might also want to read the responses in the question Inheriting from Frame or not in a Tkinter application