I am trying to have two dropdown lists bellow two labels stating what they are. The problem is whenever i run it the second list is offset to the left. This takes place in the setupPage section and looks like so:
image of the issue
I have tried lots of combinations of sticky to no avail. Any help would be appreciated.
Code:
from tkinter import *
from tkinter import ttk
root = Tk()
def startPage(root):
content = ttk.Frame(root) #frame for plaing everything into
#frame = ttk.Frame(content, borderwidth=5, relief="sunken", width=200, height=100) #fram for plaxing images
lbl1 = ttk.Label(content, text="Is this a new or existing site?",font=("arial",12)) #setup of label for screen 1
yesvar = BooleanVar() #variables for check boxes later on
novar = BooleanVar()
yesvar.set(False)
novar.set(False)
one = ttk.Checkbutton(content, text="Yes", variable=yesvar, onvalue=True) #check buttons setup
two = ttk.Checkbutton(content, text="No", variable=novar, onvalue=True)
ok = ttk.Button(content, text="New", command = nextPage) #setup for buttons screen 1
cancel = ttk.Button(content, text="Existing")
content.grid(column=0, row=0) #intilises content
#frame.grid(column=0, row=0, columnspan=3, rowspan=2)
lbl1.grid(column=0, row=0, columnspan=3,pady=10,padx=10) #places the label asking the question with a gap either side for the window bindings
#name.grid(column=3, row=1, columnspan=2)
#one.grid(column=0, row=3)
#two.grid(column=1, row=3)
ok.grid(column=0, row=1,pady=10,padx=10) #places yes button 10 away from each edge
cancel.grid(column=1, row=1,pady=10,padx=10) #as above
def setupPage(root):
content = ttk.Frame(root) #frame for plaing everything into
#frame = ttk.Frame(content, borderwidth=5, relief="sunken", width=200, height=100) #fram for plaxing images
lbl1 = ttk.Label(content, text="Select meterial 1",font=("arial",12)) #setup of label for screen 1
lbl2 = ttk.Label(content, text = "Select meterial 2" ,font = ("arial",12))
content.grid(column=0, row=0)
lbl1.grid(column=0, row=0,columnspan=1, pady=10,padx=10)
lbl2.grid(column=1,row=0,columnspan=1,pady=10,padx=10)
clicked = StringVar()
clicked.set("lo2")
clicked2 = StringVar()
clicked2.set("lo2")
drop2 = OptionMenu(root, clicked2, "lo2", "mo3", "Lo2+mo3")
drop = OptionMenu(root, clicked, "lo2", "mo3", "Lo2+mo3")
drop.grid(column=0, row=1,pady=10,padx=10,sticky=NW)
drop2.grid(column=1, row=1,pady=10,padx=10,sticky=NW)
def nextPage():
global pagenum, root
for widget in root.winfo_children():
widget.destroy()
if pagenum == 1:
setupPage(root)
pagenum = 2
else :
startPage(root)
pagenum = 1
startPage(root)
pagenum = 1
root.mainloop()
The parent of the labels and the OptionMenus are different.
Changing the parents to root instead of content seems to work
from tkinter import *
from tkinter import ttk
root = Tk()
def startPage(root):
print("oi")
content = ttk.Frame(root) #frame for plaing everything into
#frame = ttk.Frame(content, borderwidth=5, relief="sunken", width=200, height=100) #fram for plaxing images
lbl1 = ttk.Label(content, text="Is this a new or existing site?",font=("arial",12)) #setup of label for screen 1
yesvar = BooleanVar() #variables for check boxes later on
novar = BooleanVar()
yesvar.set(False)
novar.set(False)
one = ttk.Checkbutton(content, text="Yes", variable=yesvar, onvalue=True) #check buttons setup
two = ttk.Checkbutton(content, text="No", variable=novar, onvalue=True)
ok = ttk.Button(content, text="New", command = nextPage) #setup for buttons screen 1
cancel = ttk.Button(content, text="Existing")
content.grid(column=0, row=0) #intilises content
#frame.grid(column=0, row=0, columnspan=3, rowspan=2)
lbl1.grid(column=0, row=0, columnspan=3,pady=10,padx=10) #places the label asking the question with a gap either side for the window bindings
#name.grid(column=3, row=1, columnspan=2)
#one.grid(column=0, row=3)
#two.grid(column=1, row=3)
ok.grid(column=0, row=1,pady=10,padx=10) #places yes button 10 away from each edge
cancel.grid(column=1, row=1,pady=10,padx=10) #as above
def setupPage(root):
#content = ttk.Frame(root) #frame for plaing everything into
#frame = ttk.Frame(content, borderwidth=5, relief="sunken", width=200, height=100) #fram for plaxing images
lbl1 = ttk.Label(root, text="Select meterial 1",font=("arial",12)) #setup of label for screen 1
lbl2 = ttk.Label(root, text = "Select meterial 2" ,font = ("arial",12))
#content.grid(column=0, row=0)
lbl1.grid(column=0, row=0,columnspan=1, pady=10,padx=10)
lbl2.grid(column=1,row=0,columnspan=1,pady=10,padx=10)
clicked = StringVar()
clicked.set("lo2")
clicked2 = StringVar()
clicked2.set("lo2")
drop2 = OptionMenu(root, clicked2, "lo2", "mo3", "Lo2+mo3")
drop = OptionMenu(root, clicked, "lo2", "mo3", "Lo2+mo3")
drop.grid(column=0, row=1,pady=10,padx=10,sticky=NW)
drop2.grid(column=1, row=1,pady=10,padx=10,sticky=NW)
def nextPage():
print("oi2")
global pagenum, root
for widget in root.winfo_children():
widget.destroy()
if pagenum == 1:
print("oi3")
setupPage(root)
pagenum = 2
else :
startPage(root)
pagenum = 1
startPage(root)
pagenum = 1
root.mainloop()
Related
I know how to add a scrollbar on a tkinter window, frame, canvas.
I also know how to do it on a listbox.
Problem is, I have a window that doesn't have any of those, and only use Label and Button:
from tkinter import *
test1 = 100
test2 = 100
test3 = 100
test4 = 100
root = Tk()
root.title("Program")
root.geometry('350x250')
# first group of labels & buttons
label = Label(root, text="test1")
label.grid(row=0, column=0, columnspan=2)
label = Label(root, text=test1)
label.grid(row=1, column=0, columnspan=2)
button = Button(root, text="Up")
button.grid(row=2, column=0)
button = Button(root, text="Down")
button.grid(row=2, column=1)
#
label = Label(root, text="test2")
label.grid(row=3, column=0, columnspan=2)
label = Label(root, text=test2)
label.grid(row=4, column=0, columnspan=2)
button = Button(root, text="Up")
button.grid(row=5, column=0)
button = Button(root, text="Down")
button.grid(row=5, column=1)
#
label = Label(root, text="test3")
label.grid(row=6, column=0, columnspan=2)
label = Label(root, text=test3)
label.grid(row=7, column=0, columnspan=2)
button = Button(root, text="Up")
button.grid(row=8, column=0)
button = Button(root, text="Down")
button.grid(row=8, column=1)
#
label = Label(root, text="test4")
label.grid(row=9, column=0, columnspan=2)
label = Label(root, text=test4)
label.grid(row=10, column=0, columnspan=2)
button = Button(root, text="Up")
button.grid(row=11, column=0)
button = Button(root, text="Down")
button.grid(row=11, column=1)
root.mainloop()
The above has a small window resolution on purpose, because, while it may work in maximizing the window, once there are too many Label's text or Button, then a Scrollbar will be needed. This is intended to test that.
How can I add a scrollbar to the above code?
You need a scrollable frame. See example here: https://gist.github.com/mp035/9f2027c3ef9172264532fcd6262f3b01
And for buttons and labels, instead of using root as parent, use the scrollable frame as parent. For example:
from tkinter import *
c1 = "#999999"
c2 = "#000000"
class ScrollFrame(Frame):
"""
A simple scrollable frame class for tkinter
Source: https://gist.github.com/mp035/9f2027c3ef9172264532fcd6262f3b01
"""
def __init__(self, parent):
# create a frame (self)
super().__init__(parent, background=c1)
# place canvas on self
self.canvas = Canvas(
self, bd=0, bg=c1, relief="flat", highlightthickness=0
)
# place a frame on the canvas, this frame will hold the child widgets
self.viewPort = Frame(self.canvas, background=c1)
self.viewPort.grid_columnconfigure(0, weight=1)
# place a scrollbar on self
self.vsb = Scrollbar(self, orient="vertical", command=self.canvas.yview)
# attach scrollbar action to scroll of canvas
self.canvas.configure(yscrollcommand=self.vsb.set)
# pack scrollbar to right of self
self.vsb.pack(side="right", fill="y")
# pack canvas to left of self and expand to fil
self.canvas.pack(side="left", fill="both", expand=True)
self.canvas_frame = self.canvas.create_window(
(0, 0),
window=self.viewPort,
anchor="nw", # add view port frame to canvas
tags="self.viewPort",
)
# bind an event whenever the size of the viewPort frame changes.
self.viewPort.bind("<Configure>", self.onFrameConfigure)
self.canvas.bind("<Configure>", self.FrameWidth)
self.canvas.bind_all("<MouseWheel>", self._on_mousewheel)
def _on_mousewheel(self, event):
self.canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")
def FrameWidth(self, event):
canvas_width = event.width
self.canvas.itemconfig(self.canvas_frame, width=canvas_width)
def onFrameConfigure(self, event):
"""Reset the scroll region to encompass the inner frame"""
# whenever the size of the frame changes, alter the scroll region respectively.
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
tests = [100, 99, 98, 101]
root = Tk()
root.title("Program")
root.geometry('350x250')
scroll_frame = ScrollFrame(root)
for i, testi in enumerate(tests):
# grouping labels and buttons together in a subframe
# so that the row numbers of the labels and buttons
# are always 0 to 2 within the sub-frame
f1 = Frame(scroll_frame.viewPort)
# first group of labels & buttons
label = Label(f1, text=f"test{i}")
label.grid(row=0, column=0, columnspan=2)
label = Label(f1, text=testi)
label.grid(row=1, column=0, columnspan=2)
button = Button(f1, text="Up")
button.grid(row=2, column=0)
button = Button(f1, text="Down")
button.grid(row=2, column=1)
# defining this group to have 2 columns with equal weight
f1.grid_columnconfigure(0, weight=1)
f1.grid_columnconfigure(1, weight=1)
# expand this sub-frame horizontally to it's parent, sticking to West and East of parent frame
f1.grid(sticky="we", ipadx=2)
# adding a separator
Frame(f1, height=1, background=c2).grid(
sticky="we", pady=5, padx=5, columnspan=2
)
# expand the scroll_frame in all 4 directions to fill the parent frame, sticking to West, East, North and South of parent frame
scroll_frame.grid(sticky="wens", row=0, column=0)
# set root frame only has 1 column (filled by scroll_frame)
root.grid_columnconfigure(0, weight=1)
root.mainloop()
I recently stumbled on an easier way to do that (also use less code to do so):
import tkinter as tk
root = tk.Tk()
text = tk.Text(wrap="none")
vsb = tk.Scrollbar(orient="vertical", command=text.yview)
text.configure(yscrollcommand=vsb.set)
vsb.pack(side="right", fill="y")
text.pack(fill="both", expand=True)
for i in range(30):
test1 = "test" + str(i)
test2 = "Button" + str(i)
c = tk.Label(text=test1)
k = tk.Label(text=i)
b = tk.Button(text=test2)
d = tk.Button(text=test2)
text.window_create("end", window=c)
text.insert("end", "\n")
text.window_create("end", window=k)
text.insert("end", "\n")
text.window_create("end", window=b)
text.window_create("end", window=d)
text.insert("end", "\n")
text.configure(state="disabled")
root.mainloop()
This is based on this answer. It doesn't use a canvas.
There is also another similar answer to the one I accepted on this post, here.
First off, I'm new to coding. And I'm following a course on it. But in the meantime I want to test myself and figure things out for myself and "learn on the job" a bit with more hands on coding that I can use right away.
I've written below code to try and figure out to make a main window with 2 buttons. If I press a button, it should change the screen into the second/third screen. But instead if I fire up my exe.
It opens all 3 windows right away in separate windows. And once I press a button it opens another window. But what I would want is that the main window get's "updated" to show only the labels/pictures/buttons etc (which I did not include in the .py yet).
from tkinter import *
def second_window1():
second_window1 = Toplevel(main)
second_window1.title("Second window")
second_window1.geometry("414x896")
Label(second_window1, text ="This is the second window")#.pack()
def third_window1():
third_window1 = Toplevel(main)
third_window1.title("Third window")
third_window1.geometry("414x896")
Label(third_window1, text ="This is the third window")#.pack()
main = Tk()
main.title("Main Screen")
main.geometry('414x896')
main.configure(background = "azure2")
main.resizable(False, False)
Label(main, text = "Label_1", fg = "chartreuse2", bg = "ghostwhite", font = "Helvetica 16 bold").grid(row=1, column=1)
second_window = Tk()
second_window.title("Second Screen")
second_window.geometry('414x896')
second_window.configure(background = "azure2")
second_window.resizable(False, False)
Label(main, text = "Label_2", fg = "chartreuse2", bg = "ghostwhite", font = "Helvetica 16 bold").grid(row=1, column=1)
third_window = Tk()
third_window.title("Third Screen")
third_window.geometry('414x896')
third_window.configure(background = "azure2")
third_window.resizable(False, False)
Label(main, text = "Label_3", fg = "chartreuse2", bg = "ghostwhite", font = "Helvetica 16 bold").grid(row=1, column=1)
btn = Button(main, text ="Second Screen", command = second_window1).grid(row=1, column=1)
btn = Button(main, text ="Third Screen", command = third_window1).grid(row=2, column=1)
mainloop()
enter image description here
You would want to use a ttk.Notebook for that.
See e.g. at TkDocs.
An example that creates a UI using a Notebook is below.
def create_widgets(root, db):
"""Create the UI.
Arguments:
root: root window.
db: a connection to an sqlite3 database or None.
Returns:
A SimpleNamespace of widgets.
"""
# Set the font size.
default_font = nametofont("TkDefaultFont")
default_font.configure(size=12)
root.option_add("*Font", default_font)
# Common bindings
root.bind_all('q', do_q)
# SimpleNamespace to store widgets we need in the callbacks.
w = SimpleNamespace()
# Menu
menubar = tk.Menu(root)
root.config(menu=menubar)
filemenu = tk.Menu(menubar, tearoff=0)
filemenu.add_command(label="Open", command=do_open)
filemenu.add_separator()
filemenu.add_command(label="Close", command=root.quit)
menubar.add_cascade(label="File", menu=filemenu)
# Notebook
n = ttk.Notebook(root)
w.n = n
n.pack(expand=1, fill='both')
f1 = ttk.Frame(n) # Pagina 1
f1.columnconfigure(1, weight=1)
f1.rowconfigure(1, weight=1)
w.f1 = f1
f2 = ttk.Frame(n) # Pagina 2
w.f2 = f2
f2.columnconfigure(0, weight=1)
f2.rowconfigure(0, weight=1)
f3 = ttk.Frame(n) # Pagina 3
w.f3 = f3
f3.columnconfigure(0, weight=1)
f3.rowconfigure(0, weight=1)
f4 = ttk.Frame(n)
f4.columnconfigure(0, weight=1)
f4.rowconfigure(0, weight=1)
w.f4 = f4
n.add(f2, text='Orders')
n.add(f3, text='Keywords')
n.add(f4, text="Bew. 800")
n.add(f1, text='Find')
# First row of page one
ttk.Label(f1, text='Look for:').grid(row=0, column=0, sticky='w')
ze = ttk.Entry(f1)
ze.grid(row=0, column=1, sticky='ew')
ze.bind('<Return>', do_seek)
w.ze = ze
zb = ttk.Button(
f1,
text='Execute',
command=do_seek
)
if db is None:
ze['state'] = 'disabled'
zb['state'] = 'disabled'
zb.grid(row=0, column=3, sticky='e')
w.zb = zb
# Second row of page 1
cols = ['hours']
tv = ttk.Treeview(f1, columns=cols, selectmode=None)
tv.column("#0", anchor=tk.CENTER)
tv.heading("#0", text="Datum")
tv.column("hours", anchor=tk.CENTER)
tv.heading("hours", text="Hours")
tv.grid(row=1, column=0, columnspan=4, sticky='nesw')
w.tv = tv
vsb = ttk.Scrollbar(f1, orient="vertical", command=tv.yview)
vsb.grid(row=1, column=4, sticky='ns')
tv.configure(yscrollcommand=vsb.set)
# First row of page 2
cols2 = ['order', 'hours']
tv2 = ttk.Treeview(f2, columns=cols2, selectmode=None, show='headings')
for c in cols2:
tv2.heading(c, text=c.capitalize())
tv2.column(c, anchor=tk.CENTER)
tv2.grid(row=0, column=0, sticky='nesw')
w.tv2 = tv2
vsb = ttk.Scrollbar(f2, orient="vertical", command=tv2.yview)
vsb.grid(row=0, column=1, sticky='ns')
tv2.configure(yscrollcommand=vsb.set)
# First row of page 3
cols3 = ['keyword', 'hours']
tv3 = ttk.Treeview(f3, columns=cols3, selectmode=None, show='headings')
for c in cols3:
tv3.heading(c, text=c.capitalize())
tv3.column(c, anchor=tk.CENTER)
tv3.grid(row=0, column=0, sticky='nesw')
w.tv3 = tv3
vsb = ttk.Scrollbar(f3, orient="vertical", command=tv3.yview)
vsb.grid(row=0, column=1, sticky='ns')
tv3.configure(yscrollcommand=vsb.set)
# First for of page 4
cols4 = ['order', 'hours']
tv4 = ttk.Treeview(f4, columns=cols4, selectmode=None, show='headings')
for c in cols4:
tv4.heading(c, text=c.capitalize())
tv4.column(c, anchor=tk.CENTER)
tv4.grid(row=0, column=0, sticky='nesw')
w.tv4 = tv4
vsb = ttk.Scrollbar(f4, orient="vertical", command=tv4.yview)
vsb.grid(row=0, column=1, sticky='ns')
tv4.configure(yscrollcommand=vsb.set)
return w
I have 2 different python GUI menus in 2 different scripts.
A dropdown list to select
A menu where numbers can be input and output at the same GUI
I want to merge these 2 together so that both appear in the same GUI menu.
I am having trouble doing it because the structure in both python scripts is different.
Please advice.
Sharing both scripts below:
1st one
from tkinter import *
class Custombox:
def __init__(self, title, text):
self.title = title
self.text = text
def store():
self.new = self.entry.get() # storing data from entry box onto variable
if self.new == '50': # checking
a.change('ACCEPTED') # changing text
elif self.new == '40':
a.change('Increase frequency') # else, changing text
else:
a.change('Decrease frequency') # else, changing text
self.win = Toplevel()
self.win.title(self.title)
# self.win.geometry('400x150')
self.win.wm_attributes('-topmost', True)
self.label = Label(self.win, text=self.text)
self.label.grid(row=0, column=0, pady=(20, 10), columnspan=3, sticky='w', padx=10)
self.l = Label(self.win)
self.entry = Entry(self.win, width=50)
self.entry.grid(row=1, column=1, columnspan=2, padx=10)
self.b1 = Button(self.win, text='Attack', width=10, command=store)
self.b1.grid(row=3, column=1, pady=10)
# self.b2 = Button(self.win, text='Cancel', width=10, command=self.win.destroy)
# self.b2.grid(row=3, column=2, pady=10)
def __str__(self):
return str(self.new)
def change(self, ran_text):
self.l.config(text=ran_text, font=(0, 12))
self.l.grid(row=2, column=1, columnspan=3, sticky='nsew', pady=5)
root = Tk()
root.withdraw()
a = Custombox('User learning platform', 'Select the frequency of the victim sensor.')
root.mainloop()
2nd one
from tkinter import *
root = Tk()
root.title("GUI platform")
# Add a grid
mainframe = Frame(root)
mainframe.grid(column=0,row=0, sticky=(N,W,E,S) )
mainframe.columnconfigure(0, weight = 1)
mainframe.rowconfigure(0, weight = 1)
mainframe.pack(pady = 100, padx = 100)
# Create a Tkinter variable
tkvar = StringVar(root)
# Dictionary with options
choices = { 'URM37','HC-SR04','SRF05','Parallax PING'}
tkvar.set('') # set the default option
popupMenu = OptionMenu(mainframe, tkvar, *choices)
Label(mainframe, text="Please select the type of Sensor for attack").grid(row = 1, column = 1)
popupMenu.grid(row = 2, column =1)
# on change dropdown value
def change_dropdown(*args):
if tkvar.get() == 'HC-SR04':
print( "Correct" )
else:
print("WRONG")
# link function to change dropdown
tkvar.trace('w', change_dropdown)
root.mainloop()
I'm trying to place a frame with a bunch of widgets inside a toplevel window for which I have created menus. When I run the program I get two separate windows (see screen grab).
What I want is to see the labels, entry boxes, buttons, etc. inside the larger "main" window.
Screenshot of actual result
Here is the code:
# Basic menubar with a few sub-menus
from tkinter import *
from tkinter import ttk
root = Tk()
root.option_add("tearOff", FALSE)
# *************** SETUP THE CONTAINERS ***********
root.title("Menu Example")
root.geometry("600x300")
#frame = ttk.Frame(root, borderwidth = 5, relief = "sunken")
#frame.grid(row=0, column=0, sticky = (N,W,E,S))
# ***************************************************
# **** Create the Menubar
win = Toplevel(root)
menubar = Menu(win)
appmenu = Menu(menubar, name='apple')
menubar.add_cascade(menu=appmenu)
appmenu.add_command(label='About My Application')
appmenu.add_separator()
win["menu"]=menubar
# Add some menus to the menubar
menu_file = Menu(menubar)
menu_edit = Menu(menubar)
menu_transform = Menu(menubar)
menubar.add_cascade(menu=menu_file, label="File") # cascade menu items add a menu to a menubar
menubar.add_cascade(menu=menu_edit, label="Edit")
# Add items to the menus
menu_file.add_command(label = "New") # command menu items add commands to a menu.
menu_file.add_command(label = "Open...")
menu_file.add_command(label = "Close")
menu_file.add_separator()
menu_file.add_command(label = "Export as ...")
menu_edit.add_command(label = "Copy")
menu_edit.add_command(label = "Paste")
menu_edit.add_cascade(menu=menu_transform, label="Transform")
menu_transform.add_command(label="group")
menu_transform.add_command(label="ungroup")
menu_transform.add_command(label="align")
#menu_edit.add_command(label = "Transform")
# *****************************************
frame = ttk.Frame(win, borderwidth = 5, relief = "sunken")
frame.grid(row=0, column=0, sticky = (N,W,E,S))
# ***************************************************
ipaddr = StringVar()
username = StringVar()
password = StringVar()
ipAddrLbl = ttk.Label(frame, text="Switch IP Address:")
ipAddrLbl.grid(column=0, row=1, sticky = W)
usernameLbl = ttk.Label(frame, text="User Name:")
usernameLbl.grid(column=0, row=2, sticky = W)
passwordLbl = ttk.Label(frame, text="Password:")
passwordLbl.grid(column=0, row=3, sticky = W)
ipaddrEntry = ttk.Entry(frame, textvariable="ipaddr")
ipaddrEntry.grid(column=1, row=1, sticky = W)
usernameEntry = ttk.Entry(frame, textvariable="username")
usernameEntry.grid(column=1, row=2, sticky = W)
passwordEntry = ttk.Entry(frame, textvariable="password", show = "*")
passwordEntry.grid(column=1, row=3, sticky = W)
loginButton = ttk.Button(frame, text = "Login")
loginButton.grid(column=0, row=4, sticky=W)
root.mainloop()
I think the best answer for this question is to iconify the root window, then you can tinker with the Toplevel to your hearts content. That way, the root main window is hidden while the mainloop is still going without dual tkinter instances. Heres the edited code with a little tweaking so that the mainloop stops when the Toplevel is closed.
# Basic menubar with a few sub-menus
from tkinter import *
from tkinter import ttk
def _delete_window():
print ("delete_window")
try:
root.destroy()
except:
pass
root = Tk()
root.option_add("tearOff", FALSE)
# *************** SETUP THE CONTAINERS ***********
root.title("Menu Example")
root.geometry("600x300")
root.iconify()
#frame = ttk.Frame(root, borderwidth = 5, relief = "sunken")
#frame.grid(row=0, column=0, sticky = (N,W,E,S))
# ***************************************************
# **** Create the Menubar
win = Toplevel(root)
win.geometry('400x150')
menubar = Menu(win)
appmenu = Menu(menubar, name='apple')
menubar.add_cascade(menu=appmenu)
appmenu.add_command(label='About My Application')
appmenu.add_separator()
win["menu"]=menubar
# Add some menus to the menubar
menu_file = Menu(menubar)
menu_edit = Menu(menubar)
menu_transform = Menu(menubar)
menubar.add_cascade(menu=menu_file, label="File") # cascade menu items add a menu to
a menubar
menubar.add_cascade(menu=menu_edit, label="Edit")
# Add items to the menus
menu_file.add_command(label = "New") # command menu items add commands to a menu.
menu_file.add_command(label = "Open...")
menu_file.add_command(label = "Close")
menu_file.add_separator()
menu_file.add_command(label = "Export as ...")
menu_edit.add_command(label = "Copy")
menu_edit.add_command(label = "Paste")
menu_edit.add_cascade(menu=menu_transform, label="Transform")
menu_transform.add_command(label="group")
menu_transform.add_command(label="ungroup")
menu_transform.add_command(label="align")
#menu_edit.add_command(label = "Transform")
# *****************************************
frame = Frame(win, borderwidth = 5, relief = "sunken")
frame.pack()
frame.place(relx=0.5, rely=0.5, anchor=CENTER)
# ***************************************************
ipaddr = StringVar()
username = StringVar()
password = StringVar()
ipAddrLbl = ttk.Label(frame, text="Switch IP Address:")
ipAddrLbl.grid(column=0, row=1, sticky = W)
usernameLbl = ttk.Label(frame, text="User Name:")
usernameLbl.grid(column=0, row=2, sticky = W)
passwordLbl = ttk.Label(frame, text="Password:")
passwordLbl.grid(column=0, row=3, sticky = W)
ipaddrEntry = ttk.Entry(frame, textvariable="ipaddr")
ipaddrEntry.grid(column=1, row=1, sticky = W)
usernameEntry = ttk.Entry(frame, textvariable="username")
usernameEntry.grid(column=1, row=2, sticky = W)
passwordEntry = ttk.Entry(frame, textvariable="password", show = "*")
passwordEntry.grid(column=1, row=3, sticky = W)
loginButton = ttk.Button(frame, text = "Login")
loginButton.grid(column=0, row=4, sticky=W)
win.protocol("WM_DELETE_WINDOW", _delete_window)
root.mainloop()
Corrected code to use Toplevel widget instead of new Tk instance:
import tkinter as tk
class Gui1:
def __init__(self, root):
self.root = root
self.frame = tk.Frame(root)
self.button = tk.Button(text="Openwindow2",
command=self.create_gui2)
self.button.grid(row=0, column=0)
self.frame.grid(row=1, column=1)
def create_gui2(self):
class Gui2:
def __init__(self, root2):
self.root2 = root2
self.frame2 = tk.Frame(root2)
self.label=tk.Label(text="Window 2")
self.label.grid(row=0,column=0)
self.frame2.grid(row=3,column=3)
root2 = tk.Toplevel()
app2 = Gui2(root2)
root = tk.Tk()
app = Gui1(root)
root.mainloop()
I'm using rows to layout my Tkinter program.
I usually use pack so my buttons would automatically place itself and not over lap, using rows, my buttons are overlapping, and I have to align them by changing their padx value. I was wondering if there was an easier way to do this.
from sys import argv
from Tkinter import *
from PIL import Image, ImageTk, ImageFilter
import random
script, infile = argv
class MyApp(object):
def __init__(self):
self.root = Tk()
self.root.wm_title("ImagePro")
# Original
original = Image.open(infile)
(w, h) = (original.size[0], original.size[1])
tkpi = ImageTk.PhotoImage(original)
label = Label(self.root, image=tkpi)
label.grid(row =0, column=0, padx=5,pady=5)
img = original.copy().convert("L")
tkpi2 = ImageTk.PhotoImage(img)
label = Label(self.root, image=tkpi2)
label.grid(row =0, column=1, padx=5,pady=5)
Label(self.root, text = "Original").grid(row=1, column=0)
Label(self.root, text = "Modified").grid(row=1, column=1)
Button(self.root, text = "Brighten").grid(row=2, column=0, sticky=W)
Button(self.root, text = "Darken").grid(row=2, column=0, sticky=W, padx=60)
Button(self.root, text = "Warm").grid(row=2, column=0, sticky=W, padx=112)
Button(self.root, text = "Cool").grid(row=2, column=0, sticky=W, padx=158)
self.root.mainloop()
MyApp()
To do this you need to start using frames. A frame acts as a container for widgets. Add all the buttons to a frame, then add that frame to the root container.
class MyApp(object):
def __init__(self):
self.root = Tk()
self.root.wm_title("ImagePro")
#Original
original = Image.open(infile)
(w, h) = (original.size[0], original.size[1])
tkpi = ImageTk.PhotoImage(original)
label = Label(self.root, image=tkpi)
label.grid(row =0, column=0, padx=5,pady=5)
img = original.copy().convert("L")
tkpi2 = ImageTk.PhotoImage(img)
label = Label(self.root, image=tkpi2)
label.grid(row =0, column=1, padx=5,pady=5)
Label(self.root, text = "Original").grid(row=1, column=0)
Label(self.root, text = "Modified").grid(row=1, column=1)
self.buttonframe = Frame(self.root)
self.buttonframe.grid(row=2, column=0, columnspan=2)
Button(self.buttonframe, text = "Brighten").grid(row=0, column=0)
Button(self.buttonframe, text = "Darken").grid(row=0, column=1)
Button(self.buttonframe, text = "Warm").grid(row=0, column=2)
Button(self.buttonframe, text = "Cool").grid(row=0, column=3)
self.root.mainloop()
Each button goes in its own column within the frame, and the frame goes at the bottom of the main container.
If you use the same row,column couple for several widgets, they will appear in the same cell of the grid. Thus something like this should do the trick.
Button(self.root, text = "Brighten").grid(row=2, column=0)
Button(self.root, text = "Darken").grid(row=2, column=1)
Button(self.root, text = "Warm").grid(row=2, column=2)
Button(self.root, text = "Cool").grid(row=2, column=3)
You will find detailed information on this documentation of grid geometry manager http://effbot.org/tkinterbook/grid.htm