I'm using Tkinter for the GUI, and I have one problem:
I try to make a message widget, and when I write:
body = Message(top, bd = 2)
body.pack(side=RIGHT)
I get this error:
body.pack(side=RIGHT)
AttributeError: Message instance has no attribute 'pack'
I dont understand this becaue I checked in some guides and Its allowed to use 'message' this way, as seen here in the example: http://www.tutorialspoint.com/python/tk_message.htm
Is there another way to write this?
There are at least two Message classes in Tkinter. One of them comes from tkMessageBox.Message, and the other one is from Tkinter.Message. The former is a subclass of the Dialog from tkCommonDialog, and since packing a dialog is meaningless, there is no pack method for this case. The later is a Tk widget called message, which is the one you want; being a widget, it makes sense to pack it.
Your complete code mostly like have something in the form (Python 2):
from Tkinter import *
from tkMessageBox import *
The second import shadows the Message class from the first import. To use the Message class you are after, simply change the above code to:
from Tkinter import *
import tkMessageBox
Then adapt your code accordingly.
Related
I am practicing on my personal project to create oop from tkinter module. I have written a code block where I try to create Label widget by imperative code line, then within a class.
from tkinter import *
app=Tk()
app.geometry('500x300')
Button(app,width=13,height=1,text='scrape').pack()
var_str=StringVar()
var_str='result 001 ...'
Label(app,width=33,height=1,text='res',textvariable=var_str).pack()
class label():
def __init__(self,master,var_text):
self.label=Label(master,width=33,height=1,textvariable=var_text).pack()
lbl_one=label(app,var_str)
app.mainloop()
The strangeness is if I comment out Label(app,width=33,height=1,text='res',textvariable=var_str).pack() then my object instantiation does not work out.
I would like to have a clear answer why lbl_one object gives same text result as with Label(app...) line?
because you probably forgot that u put StringVar at top then changed it to string which not work.
var_str=StringVar(master=app, value="res")
replace that line to this and comment the first label's line then the object would work fine.
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 have the button's image cycle through all possible pizza images, but instead it throws the following error when I click on it:
self.config(image=next(self.images))
AttributeError: 'buttonInitialize' object has no attribute 'config'
Here's the code. I know it's ugly, sorry. I barely understand python classes, so I couldn't figure out how to factor the repetitive parts out
from tkinter import *
from itertools import cycle
class buttonInitialize:
def __init__ (self,enabler):
frame=Frame(enabler)
frame.pack()
pizzaList=[]
pizzaList.append(PhotoImage(file="Cheese.png").zoom(10))
pizzaList.append(PhotoImage(file="AvocadoWSauce.png").zoom(10))
pizzaList.append(PhotoImage(file="AvocadoWCheese.png").zoom(10))
self.images=cycle(pizzaList)
self.printButton=Button(frame,image=pizzaList[0] ,command=self.nextPizza)
self.printButton.pack(side=LEFT)
def nextPizza(self):
self.config(image=next(self.images))
root=Tk()
c=buttonInitialize(root)
root.mainloop()
Instead of self.config(), use self.printButton.config()
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
I've been following a tutorial for the tkinter interface in python and it uses the following piece of code to declare a root widget for the program which then has children widgets:
root = Tk()
I'm getting the following error when trying to interpret this piece of code:
Global name Tk() is not defined
I'm fairly sure this is because tkinter has changed since the tutorial; I cannot find any other tutorials that do not use snippets of code like this so they wouldn't work either.
The question I have is in context simple, but searching, I cannot find the answer;
How can I bypass this: what has changed to the syntax of tkinter and what is the new method of sorts to declare a root widget? additionally it would be brilliant if anybody has the knowledge of tkinter to warn me whether the way in which you can add children widgets to the root has changed as well.
Thank you for any and all replies ~ Michael
You probably forgot from Tkinter import * at the top.
Alternatively, there's
import Tkinter
or
import Tkinter as tk
Edit: Generally, you want to use the idiom from <library> import <module>, so for your specific example from Tkinter import Tk would work.
which just allows you type tk.Button, for example, rather than Tkinter.Button throughout your code. And if you're using Python 3.x, the library is lowercase.
import tkinter
For general importing questions, I've seen the Importing Python Modules link referenced a lot on SO.
You seem to have named the file tkinter.py. You cannot name a file with the module you are importing. Python will try to import from your existing file instead of tkinter module. There will be module name collison. Try to rename your file name.
from Tkinter import *
root = Tk()