root = tkinter.Tk() or root = Tk()? - python

I have two scripts that both work:
import tkinter
root = tkinter.Tk()
root.configure(bg='blue')
root.mainloop()
and
from tkinter import *
root = Tk()
text = Text(root)
text.insert(INSERT, "Hello world!")
text.pack()
root.mainloop()
I want to combine the two scripts to print the text on a blue background, but moving anything from one script to another seems to break it.
I can't figure out if it's about root = tkinter.Tk() vs root = Tk(), or import tkinter vs from tkinter import *, or something entirely different. I can't find a successful combination.
I'm using Ubuntu and Python 3.6.9.

Because you use two different styles when importing tkinter, you will need to modify the code from one file when moving to the other. The code in your first example is the preferred way to do it because PEP8 discourages wildcard imports.
When when you copy the code from the second example, you'll need to add tkinter. to every tkinter command (tkinter.Tk(), tkinter.Text(root), tk.INSERT, etc.
Personally I find import tkinter as tk to be a slight improvement. I find tk.Tk() to be a little easier to type and read than tkinter.Tk().

You should know that:
from tkinter import *
will import all the attribute in the tkinter.But if you also define some variable in your script.It will be covered by your new variable.So we don't recommend you to use that.(If you used both from tkinter.ttk import * and from tkinter import *.Some default widgets of tkinter will be covered by ttk widgets.)
Just like Mr.Bryan said,I'd like to use import tkinter as tk,too.

Related

Can ttk safely be used with mttkinter?

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?

Why packing widgets into frames instead of directly packing them into the root window?

I'm learning Python by building an airplane ticket app. I'm currently working on learning TkInter for the GUI, and I want to know why I have to create a container (frame) instead of just putting everything in root = Tk() which seems to work.
Also, isn't ttk part of tkinter, therefore I shouldn't have to have the 2nd line (from tkinter import ttk)?
Here's my code:
from tkinter import *
from tkinter import ttk
root = Tk()
frame = Frame(root)
root.title("AirTix")
flight_title = Label(frame, text = "Flights").grid()
root.mainloop()
Thanks!
I want to know why I have to create a container (frame) instead of just putting everything in root = Tk() which seems to work.
You do not have to create a container. Whatever tutorial or book is telling you that you must is wrong. There's nothing wrong with creating everything in the root window.
That being said, for anything but the most trivial of apps, it helps tremendously to organize your widgets in logical groups, with each logical group being a frame (or, perhaps, a Canvas or PanedWindow). This gives you the flexibility to use the best geometry manager (pack, place, or grid) for each section.
For example, it makes sense to have a toolbar that is a frame with a bunch of buttons packed left-to-right. The same might be true for a bottom status bar. The main body might be a frame with widgets arranged in a grid.
grid can be a bit more complicated to use, and pack excels at placing widgets either in a single horizontal row (toolbar or status bar), or column (toolbar on top, status bar on bottom, main area in the middle.
Also, isn't ttk part of tkinter, therefore I shouldn't have to have the 2nd line (from tkinter import ttk)?
Even though ttk is part of tkinter, it does not get imported when you import everything from tkinter. Many python packages are this way, with sub-modules that must be explicitly imported.
Further, it's bad practice to use a wildcard import. Instead of doing this:
from tkinter import *
root = Tk()
... it's arguably better to do it like this:
import tkinter as tk
root = tk.Tk()
With the former, you end up polluting the global namespace with a bunch of things you may or may not use. With the latter, you import exactly one thing. Plus, it makes your code more self-documenting because it makes it crystal clear when you are expecting to use an object or class from the tk package.

Python turtle get tkinter root

Python turtle works with tkinter. How to get the root you know from tkinter?
Like this:
import tkinter
root = tkinter.Tk()
but for turtle.
The top-level widget is available through the winfo_toplevel method of the turtle canvas:
import turtle
canvas = turtle.getcanvas()
root = canvas.winfo_toplevel()
It is of a subtype of Tk:
import tkinter
assert type(root) is turtle._Root
assert isinstance(root, tkinter.Tk)
As pointed out by #das-g
root = turtle.getcanvas().winfo_toplevel()
gives you an object representing the turtle root window.
However, if your use case is to integrate turtle graphics with a full-blown Tkinter application, the explicit approach should be preferred at all times:
from tkinter import *
import turtle
root = Tk()
turtle_canvas = turtle.Canvas(root)
turtle_canvas.pack(fill=BOTH, expand=True) # fill the entire window
protagonist = turtle.RawTurtle(turtle_canvas)
protagonist.fd(100) # etc.
This adds the extra benefit of being able to control position and size of the turtle canvas. Plus, having explicit code helps others understanding it.
turtle.getcanvas()
returns the object you are (I am) looking for.

ttk OptionMenu does not fit into its bounding box

I am facing a problem creating a Tkinter-application under Windows, using python 2.7. Basically, when I create an OptionMenu, its right corner (where a down button indicates that something happens when you click there) is truncated in the middle.
The following code reproduces the issue:
from Tkinter import Tk, StringVar
from ttk import OptionMenu
root = Tk()
options = list('ABC')
var = StringVar(value='A')
om = OptionMenu(root, var, var.get(), *options)
om.config(width=25)
om.pack()
root.mainloop()
The result looks on my computer like this:
I have played around with the padx and ipadx keywords of the packing layout manager and also tried a grid layout instead. None of them lets me see the down-arrow completely.
I appreciate your helpful comments on this issue.
The same happens to me on Windows 7 but not on XP, both using Python 2.7. I have found a bug report which states is should be fixed in Tk 8.5.8. Updating Tcl/Tk in Python seems to be very complicated though
The fix in question is for one of the script files shipped in the tk library. You could modify your local copy of vistaTheme.tcl to match this. In later versions I think it does actually request the size from the system properly but this should work if you are forced to use an older version of Tk.
You can find the path using:
from Tkinter import Tk
tk = Tk()
tk.eval("set tk_library")
and then edit the /ttk/vistaTheme.tcl file. I've got python3 here and it seems to have come with Tk 8.6.1 so has this fixed already.

ttk: how to make a frame look like a labelframe?

Python ttk gui creating is easy and has mostly native look and feel (win7). I am having a slight problem, though:
I would like to have a frame that looks like ttk.LabelFrame but without label. Just omitting the text option will leave an ugly gap.
Also I can not get the ttk.Frame border to look like LabelFrame. Is there an elegant way of doing this? Bonus karma if this works on all/most windows versions above xp.
Maybe it works with styles but the style LabelFrame properties seem mostly empty (style.element_options("border.relief")). Maybe I am looking in the wrong place.
edit:
try: # python 3
from tkinter import * # from ... import * is bad
from tkinter.ttk import *
except:
from Tkinter import *
from ttk import *
t = Tcl().eval
print("tcl version: " + str(t("info patchlevel")))
print("TkVersion: " + str(TkVersion))
root = Tk()
lF = LabelFrame(root, text=None)
lF.grid()
b = Button(lF, text='gonzo')
b.grid()
f = Frame(root, relief="groove") #GROOVE)
f.grid()
b2 = Button(f, text='gonzo')
b2.grid()
f2 = Frame(root, relief=GROOVE, borderwidth=2)
f2.grid()
b3 = Button(f2, text='gonzo')
b3.grid()
mainloop()
output on win7 with freshly downloaded python 3.2.3:
tcl version: 8.5.9
TkVersion: 8.5
There is python 2.6.6 installed on this machine, too (same problem). Each installation seems to be using the correct tk/tcl, though.
OK, seems like one solution to getting the LabelFrame without the gap is to use an empty widget in place of the text. So, modifying the first part of your example slightly:
# don't do the 'from tkinter import *' thing to avoid namespace clashes
import tkinter # assuming Python 3 for simplicity's sake
import tkinter.ttk as ttk
root = tkinter.Tk()
f = tkinter.Frame(relief='flat')
lF = ttk.LabelFrame(root, labelwidget=f, borderwidth=4)
lF.grid()
b = ttk.Button(lF, text='gonzo')
b.grid()
root.mainloop()
Seems to work for me with the regular Win7 theme.

Categories