Python 3.5: Adding a margin to a tkinter window - python

Code:
from data import *
from tkinter import *
root = Tk()
root.title("python")
root.geometry("400x400")
label1 = Label(root, text="Type a thing:")
entry1 = Entry(root)
button_1 = Button(root, text="Sign In", command=execute1)
label1.grid(row=1, column=0, padx=(0,15))
entry1.grid(row=1, column=1)
button_1.grid(row=2, sticky=W)
root.mainloop()
I want to add margin to the window. Like adding margin in CSS.
I tried this:
root.grid(padx=20, pady=20)
But i'm getting this error:
TypeError: wm_grid() got an unexpected keyword argument 'padx'
I'm using Python 3.5, how can i do that?

You can not run this code:
root.grid(padx=20, pady=20)
Because both padx and pady options are used to add a padding to place around the widget in a cell. This means, you can use these two options for widgets positioned within the tkinter.TK() main window using the grid() method.
But for the main widget root itself you can not add any padding because a padding is added respectively to a tkinter.TK() cell.

Related

How to make text show up in a specific location on a Tkinter window

please see the code below. Working on a 100 days of code project. How to I make text appear in a specific position (x=400, y=150) for example on a window.
Please see my code below.
from tkinter import *
from tkinter import messagebox
BACKGROUND_COLOR = "#B1DDC6"
window = Tk()
window.title('Flashy')
window.config(padx=50, pady=50, bg=BACKGROUND_COLOR)
# Todo. Center the front of the card.
canvas = Canvas(width=800, height=526, bg=BACKGROUND_COLOR, highlightthickness=0)
card_front = PhotoImage(file='images/card_front.png')
canvas.create_image(400, 263, image=card_front)
canvas.grid(row=0, column=1, columnspan=2)
# Placing text on the card.
text_1 = Label(text="French", bg='white', font=("Ariel", 40, "italic"), fg='black')
text_1.goto(x=400, y=150)
text_1.grid(row=0, column=0, columnspan=2)
# Buttons
check_mark = PhotoImage(file='images/right.png')
check_mark_button = Button(image=check_mark, highlightthickness=0)
check_mark_button.grid(row=1, column=2)
wrong_mark = PhotoImage(file='images/wrong.png')
wrong_mark_button = Button(image=wrong_mark, highlightthickness=0)
wrong_mark_button.grid(row=1, column=1)
window.mainloop()
I tried using .config to specify the location for the text but that doesn't work.
Use the place() geometry manager to place widgets at specific coordinates.
Instead of:
text_1.goto(x=400, y=150)
Try...
text_1.place(x=400, y=150)
And remove:
text_1.grid(row=0, column=0, columnspan=2)
since you should only use one geometry manager method (pack, grid, or place) on a given widget.

tkinter pack() method not working for one label

import tkinter as tk
win = tk.Tk()
win.title('使用者登入')
win.geometry('300x200')
lb1 = tk.Label(win,text='使用者帳號資料',font=('微軟正黑體',16),fg='yellow',bg='black')
lb1.pack(fill='x')
lb2 = tk.Label(win,text='帳號 : ABCDEF',height=4,width=26,font=('標楷體',14),bg='lightblue')
lb2.pack(side='left',anchor='nw',fill='x')
lb3 = tk.Label(win,text='注意',height=50,width=3,font=('微軟正黑體',12),bg='pink')
lb3.pack(anchor='se',fill='y',expand=True)
lb4 = tk.Label(win,text='密碼 : 123456',height=4,width=15,font=('標楷體',14),bg='lightgreen')
lb4.pack(anchor='sw',side='left')
win.mainloop()
The variable lb4 could not be shown on the tkinter window even though I have used pack() method. I would like to put the lb4 widget below lb2 and I had tried using anchor='sw' still not showing so any possible methods to have that widget be shown properly?
The pack method works properly, check that:
import tkinter as tk
win = tk.Tk()
win.title('使用者登入')
win.geometry('300x200')
# lb1 = tk.Label(win,text='使用者帳號資料',font=('微軟正黑體',16),fg='yellow',bg='black')
# lb1.pack(fill='x')
#
# lb2 = tk.Label(win,text='帳號 : ABCDEF',height=4,width=26,font=('標楷體',14),bg='lightblue')
# lb2.pack(side='left',anchor='nw',fill='x')
#
# lb3 = tk.Label(win,text='注意',height=50,width=3,font=('微軟正黑體',12),bg='pink')
# lb3.pack(anchor='se',fill='y',expand=True)
lb4 = tk.Label(win,text='密碼 : 123456',height=4,width=15,font=('標楷體',14),bg='lightgreen')
lb4.pack(anchor='sw',side='left')
win.mainloop()
If it does show anything is because the pack method add widget to the right of the previous on if it's anchored to "S"(outh), even if the new widget it's anchored to 'w' and sided to 'left'.
Since lb3 is anchor at 'se', any other widget is displayed outside the windows.
You shoud use .grid to properly design your window:
import tkinter as tk
win = tk.Tk()
win.title('使用者登入')
lb1 = tk.Label(win, text='使用者帳號資料', font=('微軟正黑體', 16), fg='yellow',
bg='black')
lb1.grid(row=0, column=0, columnspan=3, sticky='WE')
lb2 = tk.Label(win, text='帳號 : ABCDEF', height=4, width=26, font=('標楷體', 14),
bg='lightblue')
lb2.grid(row=1, column=0, sticky='WE')
lb3 = tk.Label(win, text='注意', width=3, font=('微軟正黑體', 12), bg='pink')
lb3.grid(row=1, column=2, rowspan=2, sticky='NS')
#
lb4 = tk.Label(win, text='密碼 : 123456', height=4, width=15, font=('標楷體', 14),
bg='lightgreen')
lb4.grid(row=2, column=0, sticky='w')
win.mainloop()
It looks like this:
Here, I removed the height of lb3 since it's not required (sticky 'NS' allow us to extend the widget to top and down of the rowspan).
You can change column, row, columnspan, rowspan as you want to create the layout you desire.
Each time you use pack, it allocates an entire side for the widget. Thus, the order in which you call pack matters. For example, once you put widget along the top, you can no longer put something to the right.
This is usually much easier to visualize when you group all of your pack statements together for all children in the same parent widget. I also recommend always explicitly defining the side parameter so that your intentions are crystal clear.
This is the proper order to use pack to get lb4 below lb2, with lb1 along the top and lb3 along the right side:
lb1.pack(side="top", fill='x')
lb3.pack(side="right", fill='y')
lb2.pack(side="top", fill='x')
lb4.pack(side="top", fill='x')
I tried running your code and using lb4 before lb3 fixes the problem, but it won't display below lb2 as you have already used side='left' in lb2 so it acquires the whole left side, to pack it below lb2 remove the side='left' in lb2 and put it in lb4.
It doesn't display lb4 at first because it packs it outside of the TKinter window .
Instead of using .pack() use .grid() to better place the labels in the window.
This works:
import tkinter as tk
win = tk.Tk()
win.title('使用者登入')
win.geometry('300x200')
lb1 = tk.Label(win,text='使用者帳號資料',font=('微軟正黑體',16),fg='yellow',bg='black')
lb1.pack(fill='x')
lb2 = tk.Label(win,text='帳號 : ABCDEF',height=4,width=26,font=('標楷體',14),bg='lightblue')
lb2.pack(anchor='nw',fill='x')
lb4 = tk.Label(win,text='密碼 : 123456',height=4,width=15,font=('標楷體',14),bg='lightgreen')
lb4.pack(side='left',anchor='sw')
lb3 = tk.Label(win,text='注意',height=50,width=3,font=('微軟正黑體',12),bg='pink')
lb3.pack(anchor='se',fill='y',expand=True)
win.mainloop()

Making text appear in Gui instead of python shell

I'm making a GUI with python and tkinter That prompts user the Mac Address of his pc and asks for a code The Python snippet i have used for retrieving the MAc address is :
import uuid
def get_mac():
mac_num = hex(uuid.getnode()).replace('0x', '').upper()
mac = ''.join(mac_num[i : i + 2] for i in range(0, 11, 2))
return mac
x= get_mac()
print x
I have also made a gui containing the two fields as shown below
However when i execute the python snippet the mac address is displayed outside the python gui and in the python shell, how can i make the mac address appear in the space provided in the GUi itself
Here is the code for the gui:
from Tkinter import *
from ttk import *
root =Tk()
def show_form():
bottomFrame = Frame(root)
bottomFrame.pack(side=BOTTOM)
b = Button(bottomFrame,text="ACTIVATE",command=lambda: show_call_back(root))
b1 = Button(bottomFrame, text="TRIM")
b2 = Button(bottomFrame, text="OVERLAY")
b3 = Button(bottomFrame, text="MERGE")
b.pack(side=RIGHT,padx=8,pady=26)
b1.pack(side=LEFT, padx=8, pady=26)
b1.config(state='disabled')
b2.pack(side=LEFT, padx=8, pady=26)
b2.config(state='disabled')
b3.pack(side=LEFT, padx=8, pady=26)
b3.config(state='disabled')
root.mainloop()
def show_call_back(parent):
top = Toplevel(parent)
top.geometry("250x200+600+250")
top.resizable(width=False, height=False)
top.title("Activation")
Label(top, text="Mac Address:",).grid(row=0, sticky=W, padx=4)
Label(top, text="Code").grid(row=1, sticky=W, padx=4)
Entry(top).grid(row=1, column=1, sticky=E, pady=4)
Button(top, text="Submit", command=top.destroy).grid(row=2, column=1)
show_form()
root.mainloop()
After your last comment, the solution is quite simple: add a new Label to display the result of get_mac().
Solution - Add a Label in row=0 and text=get_mac().
hLbl = Label(top, text=get_mac(), bg='white', relief=SUNKEN, width = 15)
hLbl.grid(row=0, column=1, sticky=E, pady=4)
I have added bg='white' and relief=SUNKEN to a the same style as
an Entry. The extra width = 15 is to enlarge the size of the label.
Warning 1 - as #abccd comments, keep only one mainloop(), and place the root = Tk() after the function declaration.
Warning 2 - Instead of using root as a global variable in bottomFrame = Frame(root) of the function show_form(), add it as input parameter.
def show_form(my_root): # use my_root instead of global root
bottomFrame = Frame(my_root)
bottomFrame.pack(side=BOTTOM)
# also for the command parameter
b = Button(bottomFrame,text="ACTIVATE",command=lambda: show_call_back(my_root))
...
And call:
root = Tk()
show_form(root)
root.mainloop()
EDIT -------
Output - here is what I get under Python 3.5.0

Using tkinter grid

I am fairly new to using .grid in tkinter and was wondering how I could get the l2 variable to be right under the l1 variable. When the code is run the 2nd label is too far down (even have to resize window). I would like to be able to place it in a specific place (below l1) but I'm not sure how to.
Thank you.
Example:
Welcome
Please log-in to continue
Gap's a little big there as well.
Current code:
from tkinter import *
from tkinter.ttk import *
root = Tk()
root.geometry("1300x720")
myImage = PhotoImage(file='ssf.png')
label = Label(image=myImage)
label.grid(row=0)
label.image = myImage
l1 = Label(root, text="Welcome", font="Arial 100 bold", anchor="e").grid(row=0, column=1)
l2 = Label(root, text="Please log-in to continue.", font="Arial 30 bold", anchor="e").grid(row=10, column=1)
Preview of how it looks
Well, you can use the Frame widget to put the text in it like this:
from tkinter import *
from tkinter.ttk import *
root = Tk()
root.geometry("1300x720")
myImage = PhotoImage(file='ssf.png')
label = Label(image=myImage)
label.grid(row=0)
label.image = myImage
labelFrame = Frame(root)
labelFrame.grid(row=0,column=1)
l1 = Label(labelFrame, text="Welcome", font="Arial 100 bold", anchor="e")
l1.grid(row=0, column=0)
l2 = Label(labelFrame, text="Please log-in to continue.", font="Arial 30 bold", anchor="e")
l2.grid(row=1, column=0)
The Frame widget is in row 0, column 1 and contains 'l1' and 'l2'.
Pls see my comments in the revised code below.
I would recommend drawing out the grid system on paper to visualise
your layout and compare it with what is created by your program.
Activating the background color of the widgets such as frame and
label will help you visualize your creation.
Recommend reading these references.
http://www.tkdocs.com/tutorial/grid.html
http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/layout-mgt.html
Happy coding. :)
#from tkinter import *
#from tkinter.ttk import *
## I suggest you abbreviate the imported modules to help you keep track of which
## module methods/functions you are using. See below. To be consistent, we will
## use ttk widgets where possible.
# Load tkinter for python 3
import tkinter as tk
import tkinter.ttk as ttk
root = tk.Tk()
root.geometry("1300x720")
# Customise style of ttk widgets
# I have added this to help you visualise the grid system.
s=ttk.Style()
s.configure('frame1.TFrame', background='pink')
s.configure('l0.TLabel', background='blue')
s.configure('l1.TLabel', background='green')
s.configure('l2.TLabel', background='brown')
# Create a frame inside root to contain all the widgets.
# The frame contains a 2x2 grid.
frame1 = ttk.Frame(root, style='frame1.TFrame', borderwidth=20, relief=tk.SUNKEN )
frame1.grid(row=0, column=0, rowspan=2, columnspan=2, sticky='nsew')
# Load Image
# Added tk in fromt of PhotoImage.
myImage = tk.PhotoImage(file='ssf.png')
# Create a ttk.label to contain image
## I added ttk in front of Label. If not, it will mean you will use tk.Label instead of ttk.Label.
## Also I added frame1 as the 1st option to the ttk.Label to mean the ttk.Label
## is inside frame1.
## The "in_=frame1" option is added to grid to mean l0 is grid inside frame1 grid system.
l0 = ttk.Label(frame1, image=myImage, width=500)
l0.grid(in_=frame1, row=0, column=0, sticky='nsew')
#label.image = myImage
# Create a ttk.Label to contain l1
l1 = ttk.Label(frame1, text="Welcome", style='l1.TLabel', font="Arial 100 bold", anchor=tk.E)
l1.grid(in_=frame1, row=0, column=1)
#l1 = Label(root, text="Welcome", font="Arial 100 bold", anchor="e").grid(row=0, column=1)
# Create a ttk.Label to contain l2
l2 = ttk.Label(frame1, text="Please log-in to continue.", style='l2.TLabel', font="Arial 30 bold")
l2.grid(in_=frame1, row=1, column=1)
#l2 = Label(root, text="Please log-in to continue.", font="Arial 30 bold", anchor="e").grid(row=10, column=1)
# These configuration settings will let the grid columns and rows scale according
# to the changing size of the Window i.e. root.
root.rowconfigure(0, weight=1)
root.columnconfigure(0, weight=1)
frame1.rowconfigure(0, weight=1)
frame1.columnconfigure(1, weight=1)

Expand a listbox over 2 columns Tkinter

I have the following interface: 3 frames from which 2 are on the left-hand, frame1 and frame2 and another one which is on the right, frame3.
I want to create another frame, frame4 which will have the label Output and under it there should be a Listbox. I want that both these widgets to span over the previous frames, each being places in a cell by using the grid manager.
Also I am not sure if Listbox is the widget I should be using. I want something which will contain the output of the program I will run through my application. I also thought of Entry but I need something in which I can display more than one line.
This is the code I have so far:
from Tkinter import *
root = Tk()
frame1 = Frame(root)
frame1.grid(row=0,column=0)
frame2 = Frame(root)
frame2.grid(row=1,column=0)
frame3 = Frame(root)
frame3.grid(row=0,column=1)
frame4 = Frame(root)
frame4.grid(row=2,columnspan=2)
l5 = Label(frame4, text='Output:').grid(row=2,columnspan=2)
output = Listbox(frame4, height=5)
#output.grid(row=2,column=0,columnspan=2)
#output.pack(side=LEFT, fill=BOTH, expand=1)
root.mainloop()
I managed to make the label to span across the other frames, but when I uncommented either of the last 2 lines, the interface didn't open and the program just froze.
How can I solve this?
I slightly ammended your code:
from tkinter import * # for python 2.7 use Tkinter
root = Tk()
frame1 = Frame(root, bg='red', height=20)
frame1.grid(row=0,column=0, sticky=W+E)
frame3 = Frame(root, bg='blue', height=20)
frame3.grid(row=0,column=1, sticky=W+E)
frame2 = Frame(root, bg='green', height=20)
frame2.grid(row=1,column=0, sticky=W+E)
frame4 = Frame(root)
frame4.grid(row=2,columnspan=2, sticky=E+W)
l5 = Label(frame4, text='Output:', bg='orange').grid(row=0, column=0, sticky=E+W)
output = Listbox(frame4, height=5, width=50)
output.grid(row=1,column=0)
#output.pack(side=LEFT, fill=BOTH, expand=1)
root.mainloop()
This results in:
So basically what I did was to add bg, height and sticky parameters to frames and label to easily visual what is happening and how they frames are laid out. Also I modified grid parameters listbox and label.
Hope this is what you are after, or it will help you to get there.
If you use both .grid() and .pack() Tkinter (python 2.x) or tkinter (python 3.x) will happily spend the rest of your life trying to find a way to satisfy both, you must use one within the same window or Frame, see http://www.openbookproject.net/py4fun/gui/tkPhone.html

Categories

Resources