Converting Python 2.7 to Python 3 with tkinter - python-3.x

I have a working application using Python 2.7 and Tkinter that uses these constructs:
from Tkinter import *
import Tkinter
import tkFileDialog
class Window(Frame):
#...
# other functional code
#...
def ChangeCWD(self): #CWD is current working directory
root = Tkinter.Tk()
root.withdraw()
directory = tkFileDialog.askdirectory( ... )
root = Tk()
root.mainloop()
It has labels, buttons, canvas, multiple frames and file dialogue boxes and it all works nicely.
I have begun updating the code to work on Python 3.5 and, so far all functions seem to work except for the file dialog. This is where I have got to so far:
from tkinter import *
import tkinter
import tkinter.filedialog
class Window(Frame):
#...
# other functional code
#...
def ChangeCWD(self): #CWD is current working directory
root = tkinter.Tk()
root.withdraw()
directory = filedialog.askdirectory( ... )
root = Tk()
root.mainloop()
However this code produces the error
"NameError: name 'filedialog' is not defined"
when the filedialog.askdirectory() statement is reached. Could anyone provide any help to understand what I should do to correct the situation please?
As an aside, please be gentle with me! I've always been rather mystified by the various ways of invoking import statements and how to use "tk." or "root." before some function calls. There are simply too many conflicting explanations out on the web that I can't get a clear picture.

You use import tkinter.filedialog, which imports tkinter.filedialog with the namespace tkinter.filedialog, then you try to use filedialog in your code.
Pick one of these two:
change your call to tkinter.filedialog.askdirectory( ... )
change your import to import filedialog from tkinter, which will import tkinter.filedialog with the namespace filedialog.
Note: from tkinter import * might seem like it should import filedialog, but that * does not import submodules unless the package has explicitly specified that they should.

Related

Am trying to run this code ,but its saying tkinter has no attribute "Tk()",am using pycharm,both the Tk() and mainloop(). Thank you

Am trying to run this code ,but its saying tkinter has no attribute “Tk()”,am using pycharm,both the Tk() and mainloop(). Thank you
import tkinter
def main():
main_window=tkinter.Tk() #here
tkinter.mainloop() #and here
main()

Import an Error class from a package in python

How can I import the Error class (and only the error class, not a namespace) in python to be used in an exception handling?
What's not intended to be used:
from tkinter import _tkinter as tk
try:
...
except tk.TclError:
print('Oops. Bad window path.')
I've tried the above, which works but doing so also imports a bunch of other things into my namespace that I don't need and I also need to use tk.TclError to reference it instead of simply TclError.
What I try to avoid, since it imports the whole package that I do not need, I solely need to handle the exception:
import tkinter as tk
try:
...
except tk.TclError:
print('Oops. Bad window path.')
So how do I import the Error class alone from the package, without getting the whole tkinter namespace, if that's even possible or recommandable?
I have two seperate Programs, I'll call them A and B here to shorten it.
What I would like to achieve
A.py
## Communicator ##
import B
#... Some irrelevant code ...
GUI = B.start()
try:
#Tell the GUI to modify something, for example:
GUI.entry.insert(0, 'Input')
except TclError:
#Modification failed due to Bad Window Path
B.py
## GUI ##
import tkinter as tk
#Little Function to give the Communicator the required object to start/handle the GUI
def start():
root = tk.Tk()
run = Alarmviewer(root)
return run
#... GUI initialization, creating/destroying of windows, modifications, etc
The TclError class can be imported from tkinter. To make it available as tk.TclError just import tkinter with the name tk:
import tkinter as tk
try:
...
except tk.TclError:
...
You can, of course, import just the TclError exception if you wish, though it really doesn't have any actual advantage over importing the entire module in this particular example:
from tkinter import TclError
try:
...
except TclError:
...
Your question claims you must reference it as tk.TclError, but that is a false statement. You reference it by the name you import it as. The name is irrelevant, what is important is the actual exception object itself.
For example, create a file named gui.py, and in that file put this:
# gui.py
import tkinter as tk
def do_something():
raise tk.TclError("something bad happened")
Next, in another file add the following code:
from tkinter import TclError
import gui
try:
gui.do_something()
except TclError:
print("I caught the TclError")
When you run the code, you should see "I caught the TclError" printed.

Why do i need to import messagebox in python?

When you have this code already:
from tkinter import *
Assuming that this code means that it imports everything from the tkinter module,
why doesn't it import tkinter messagebox. I'd have to use this seperate code for it to work:
from tkinter import messagebox
That's simply the way the package was designed to work. The author of tkinter decided that importing "*" wouldn't import messagebox, or some of the other packages (ttk is another example)
Generally speaking, you should never do import * anyway.

How to play sounds on python with tkinter

I have been working on a sort of 'Piano' on python. I have used tkinter as the ui,
and this is how it goes:
from tkinter import*
tk =Tk()
btn = Button(tk, text="c note", command = play)
How do I define the function play to play a sound when I press it?
Please Help.
Add these two pieces of code:
from winsound import *
&
command = lambda: Playsound("click_one.wav", SND_FILENAME)
If you don't like lambda then you can define a function before the creation of the button:
def play():
return PlaySound("click_one.wav", SND_FILENAME)
You can also define a lambda function:
play = lambda: PlaySound("click_one.wav", SND_FILENAME)
You can use pygame! It will not create a different window.
Check out Pygame's official site for more amazing functions like getting length.
There are two types of sound you can play sound or even music. Each supports pros and cons.
Tkinter doesn't support audio. You can even use pyglet or other modules.
Example code:
import pygame
from tkinter import *
root = Tk()
pygame.init()
def play():
pygame.mixer.music.load("Musics/example.mp3") #Loading File Into Mixer
pygame.mixer.music.play() #Playing It In The Whole Device
Button(root,text="Play",command=play).pack()
root.mainloop()

Why import * and then ttk?

My understanding is that the standard set-up for a tkinter program starts off like this:
from tkinter import *
from tkinter import ttk
I understand that tkinter is a package, but if I've already imported all with the *, why do I still need to import ttk? Why do I get an error if I take out the second line and try to reference ttk?
When you do from some_package import *, python will import whatever that package chooses to export. What it chooses to export may be a subset of what is actually stored in the package folder. Why is that? There's no particular reason, it's just how the package author decided to do things.
This information about what to export is defined in the __init__.py file that is inside the package (in this case, tkinter/init.py). If you look at that file you'll notice that it doesn't import ttk itself, thus ttk won't be exported and therefore can't be imported with a wildcard import.
Again, there's no particular reason other than that's how the authors of tkinter and ttk chose to do things.
For more information on the mechanics of packaging, see the packaging portion of the python tutorial (https://docs.python.org/3/tutorial/modules.html#packages)
The better way to import tkinter
You may think it's standard because many tutorials do it that way, but it's generally a bad practice. The better way, IMO, is to give the tkinter library an explicit name:
# python 3.x
import tkinter as tk
from tkinter import ttk
# python 2.x
import Tkinter as tk
import ttk
This will make your code considerably easier to read, because you have to explicitly state which toolkit you are using:
b1 = tk.Button(...) # uses a standard tk button
b2 = ttk.Button(...) # uses a ttk button
I can think of no good reason to do it any other way. Doing a global import saves you a couple of bytes each time you call a tkinter function, but at the expense of clarity. Plus, it reinforces a bad practice that might bleed into how you use other libraries.
The real authority, IMO, is PEP8, which has this to say on the matter:
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. There is one defensible use case for a wildcard import, which is to republish an internal interface as part of a public API (for example, overwriting a pure Python implementation of an interface with the definitions from an optional accelerator module and exactly which definitions will be overwritten isn't known in advance).
Because tkinter/__init__.py doesn't import ttk, so ttk isn't included in from tkinter import *.
Briefly: from tkinter import * imports from file/packet tkinter but it doesn't mean that it will import from file/packet tkinter.ttk
what the other two answers here failed to state is that ttk is not imported because it is a submodule within the tkinter module, effectively a module in itself.
so when you import tkinter you get all of the parts that directly belong to tkinter
but ttk does not directly belong and so must be imported explicitly.
however Bryan Oakley makes a good point that importing everything from a module into local namespace (as many newbies do) can lead to big problems later on when you start to use more modules. this is because some of these modules may share function names even though the functions themselves may do completely different things.
it is always best for large modules to do:
import module as mod
or
import module
and then reference the functions as belonging to the modules namespace:
module.function()
this gives you more control over what you are doing and makes it clearer later on what the function actually belonged to.

Resources