The following code runs fine within IDLE, but otherwise I get "NameError: global name 'messagebox' is not defined". However, if I explicitly state from tkinter import messagebox, it runs fine from where ever.
from tkinter import *
from tkinter import ttk
root = Tk()
mainFrame = ttk.Frame(root)
messagebox.showinfo("My title", "My message", icon="warning", parent=mainFrame)
Why does IDLE not need the explicit import statement but elsewhere it is required?
the messagebox is a separate submodule of tkinter, so simply doing a complete import from tkinter:
from tkinter import *
doesn't import messagebox
it has to be explicitly imported like so:
from tkinter import messagebox
in the same way that ttk has to be imported explicitly
the reason it works in idle is because idle imports messagebox for its own purposes, and because of the way idle works, its imports are accessible while working in idle
IDLE is written in Python and uses Tkinter for the GUI, so it looks like your program is using the import statements that IDLE itself is using. However, you should explicitly include the import statement for the messagebox if you want to execute your program outside the IDLE process.
messagebox.showinfo is defined inside tkinter/showinfo.py but when you use from tkinter import * you only import tkinter/__init__.py which holds the definitions of Label, Entry, Button, ... That is how python imports work.
When you use from tkinter import messagebox it looks for messagebox inside tkinter/__init__.py but it can't find it so it tries to import tkinter/messagebox.py
As for the IDLE anomaly, it is a bug in IDLE and I believe that it was patched.
Related
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 often used Tkinter to prompt users and get the path to a file. However, I am facing a recurrent issue, when the filedialog appears it often crashes Windows.
The screen freezes, everything is blocked and when I enter the Task Manager I can see "Python is not responding", when I try to kill Python, then the Task Manager itself freezes and my only option then is to reboot my laptop.
Here is a sample code of what I usually do :
import tkinter as tk
from tkinter import filedialog
import os
window=tk.Tk()
currdir=os.getcwd()
path=filedialog.askopenfilename(parent=window, initialdir=currdir, title="Select file")
Am I doing something wrong ? Any tips ? Is it just bad performances from this library ?
Have you tried using a try/ except block so that you'll exit the loop even if you hit an exception?
import tkinter as tk
from tkinter import filedialog
import os
try:
window=tk.Tk()
currdir=os.getcwd()
path=filedialog.askopenfilename(parent=window, initialdir=currdir, title="Select file")
finally:
window.mainloop()
Include
window.mainloop()
At the end of your GUI file and see if it works that way
Thanks #User9701 and #Linden
Following your advice, I updated my code as per the below :
import tkinter as tk
from tkinter import filedialog
import os
try:
window=tk.Tk()
currdir=sos.getcwd()
path=filedalog.asopenfilename(parent=window,initialdir=currdir, title="Select file")
finally:
window.destroy()
I want to use mttkinter and unfortunately I must use Python 2.7.
Suprisingly, I cannot find any information on whether ttk widgets become thread safe when using mttkinter.
Do I just have to issue
from mttkinter import mtTkinter as tk
import ttk
root = tk.Tk()
# --- use tk and ttk as usual ---
or possibly alternatively
import Tkinter as tk
import ttk
import mttkinter
root = tk.Tk()
# --- use tk and ttk as usual --
and everything will work as expected? Is there a preferred version of doing the imports?
The wiki on github states
As the mtTkinter module modifies Tkinter in memory, there is no need to change anything else in your program. Just import it once somewhere in your program, and everything should work smoothly.
However, this says nothing about ttk. Can anybody give me confirmation that using ttk is fine?
Consider this simple code:
from tkinter import *
from tkinter.ttk import *
root= Tk()
ttk.Label(root, text='Heading Here').grid(row=1, column=1)
ttk.Separator(root,orient=HORIZONTAL).grid(row=2, columnspan=5)
root.mainloop()
when i run this code it's showing error
ttk.Label(root, text='Heading Here').grid(row=1, column=1)
NameError: name 'ttk' is not defined
When you do import X, you are importing a module named X. From this point on, X will be defined.
When you do from X import *, you are not importing X, you are only importing the things that are inside of X. X itself will be undefined.
Thus, when you do from tkinter.ttk import *, you are not importing ttk, you are only importing the things in ttk. This will import things such as Label, Button, etc, but not ttk itself.
The proper way to import ttk in python3 is with the following statement:
from tkinter import ttk
With that, you can reference the ttk label with ttk.Label, the ttk button as ttk.Button, etc.
Note: doing from tkinter.ttk import * is dangerous. Unfortunately, ttk and tkinter both export classes with the same name. If you do both from tkinter import * and from tkinter.ttk import *, you will be overriding one class with another. The order of the imports will change how your code behaves.
For this reason -- particularly in the case of tkinter and ttk which each have several classes that overlap -- wildcard imports should be avoided. PEP8, the official python style guide, officially discourages wildcard imports:
Wildcard imports ( from import * ) should be avoided, as they make it unclear which names are present in the namespace, confusing both readers and many automated tools.
Note: your question implies you're using python 3, but in case you're using python 2 you can just do import ttk rather than from tkinter import ttk. ttk moved in python 3.
To import ttk, replace the following line:
from tkinter.ttk import *
with:
from tkinter import ttk
Otherwise, attributes of tkinter.ttk module will be loaded into the current module namespace instead of ttk itself.
When you are importing the ttk module, you can do it in 2 ways -
from tkinter import ttk
When you do this, ttk is imported almost like a variable, so you can use that ttk.Label
from tkinter import *
This is called wildcard import. You can't use ttk.Label you have to directly write Label(options)
ttk.Label(root, text='HeadingHere').grid(row=1, column=1)
NameError: name 'ttk' is not defined
In this remove ttk as follows.
Label(root, text='HeadingHere').grid(row=1, column=1
Now it works fine
I ran this code and the RAM in my computer with my processor looks like it's going to explode! What is the reason?
from tkinter import *
from tkinter import messagebox
from tkinter import ttk
import os
bloque1=Tk()
bloque1.title('Bloque1')
bloque1.config(bg="#1C1C1C")
bloque1.geometry("450x410")
barramenu=Menu(bloque1)
menubar=Menu(bloque1)
menubar.add_cascade(label="Actividades", menu=menubar)
menubar.add_command(label="Instrucciones")
menubar.add_command(label="Ayuda")
menubar.add_command(label="Cerrar", command=bloque1.quit)
bloque1.config(menu=menubar)
bloque1.mainloop()
You are adding a menu to itself. No doubt this is causing an infinite loop inside of Tkinter.
menubar.add_cascade(label="Actividades", menu=menubar)
That menu= attribute needs to be given another menu that will appear when you select that cascade entry from the menubar.