I made a button inside a class and that calls a define function which creates a new window, but whenever I try to put something inside the window like a Label, nothing appears. What is it am I doing wrong? What am I supposed to call when creating the Label because it seems like I'm not calling the right thing
from tkinter import *
class mainTitle(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
myTitle = Label(self, text="Arithmetic & Geometric Sequence", font=("bold", 15))
myTitle.grid(row=1, column=1, pady=50)
opLabel = Label(self, text="Chooose either Arithmetic & Geometric series to calculate")
opLabel.grid(row=2, column=1, pady=10)
self.ariButton = Button(self, text="Arithmetic Sequence", command=self.ariClick)
self.ariButton.grid(row=3, column=1)
self.geoButton = Button(self, text="Geometric Sequence", command=self.geoClick)
self.geoButton.grid(row=4, column=1, pady=10)
self.grid_rowconfigure(0, weight=1)
self.grid_rowconfigure(5, weight=1)
self.grid_columnconfigure(0, weight=1)
self.grid_columnconfigure(2, weight=1)
def ariClick(Frame):
ariWindow = Toplevel()
ariWindow.geometry("300x300")
ariWindow.title("Arithmetic Sequence")
aLbl = Label(Frame, text="a")
aLbl.place(anchor=CENTER) #This is not appearing in the new window
def geoClick(Frame):
geoWindow = Toplevel()
geoWindow.geometry("300x300")
geoWindow.title("Geometric Sequence")
def qProgram(Frame):
root.destroy()
if __name__ == "__main__":
root = Tk()
root.geometry("450x350")
mainTitle(root).grid(sticky="nsew")
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
root.mainloop()
this should work
class mainTitle(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
myTitle = Label(self, text="Arithmetic & Geometric Sequence", font=("bold", 15))
myTitle.grid(row=1, column=1, pady=50)
opLabel = Label(self, text="Chooose either Arithmetic & Geometric series to calculate")
opLabel.grid(row=2, column=1, pady=10)
self.ariButton = Button(self, text="Arithmetic Sequence", command=self.ariClick)
self.ariButton.grid(row=3, column=1)
self.geoButton = Button(self, text="Geometric Sequence", command=self.geoClick)
self.geoButton.grid(row=4, column=1, pady=10)
self.grid_rowconfigure(0, weight=1)
self.grid_rowconfigure(5, weight=1)
self.grid_columnconfigure(0, weight=1)
self.grid_columnconfigure(2, weight=1)
def ariClick(Frame):
ariWindow = Toplevel()
ariWindow.geometry("300x300")
ariWindow.title("Arithmetic Sequence")
#i called as parent the toplevel() instance ariwindow
aLbl = Label(ariWindow, text="aqwertyui")
aLbl.place(anchor=CENTER) # This is not appearing in the new window
def geoClick(Frame):
geoWindow = Toplevel()
geoWindow.geometry("300x300")
geoWindow.title("Geometric Sequence")
def qProgram(Frame):
root.destroy()
if __name__ == "__main__":
root = Tk()
root.geometry("450x350")
mainTitle(root).grid(sticky="nsew")
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
root.mainloop()
vote the answer if it runs.
Related
I am using this code to navigate between frames in my Tkinter text editor app. And when I want to organize the pageone with multiple frames in order to collect all the buttons in the same frame and other widgets in some other possible frames I got an error: _tkinter.TclError: cannot use geometry manager grid inside . which already has slaves managed by pack. if you could help me, ty.
here is the code I used
import tkinter as tk
from tkinter import ttk
LARGE_FONT=("Verdana",12)
def popupmsg(msg):
popup=tk.Tk()
popup.wm_title("!")
label=ttk.Label(popup,text=msg,font=LARGE_FONT)
label.pack()
b1=ttk.Button(popup,text="OKAY",command=popup.destroy)
b1.pack()
popup.mainloop()
class MainWindow(tk.Tk):
def __init__(self,*arg,**kwargs):
tk.Tk.__init__(self,*arg,**kwargs)
container=tk.Frame(self)
container.pack(side="top",fill="both",expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
menubar=tk.Menu(container)
filemenu=tk.Menu(menubar,tearoff=0)
filemenu.add_command(label="Save settings", command=lambda:popupmsg("Not supported yet!"))
filemenu.add_command(label="Exit",command=quit)
menubar.add_cascade(label="File", menu=filemenu)
tk.Tk.config(self,menu=menubar)
self.frames={}
for F in(StartPage,PageOne):
frame=F(container,self)
self.frames[F]=frame
frame.grid(row=0,column=0,sticky="nsew")
self.show_frame(StartPage)
def show_frame(self,cont):
frame=self.frames[cont]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self,parent,controller):
tk.Frame.__init__(self,parent)
label_startpage=ttk.Label(self,text="Start Page",font=LARGE_FONT)
label_startpage.pack(padx=10,pady=10)
button_to_pageONE=ttk.Button(self,text="Go to Page ONE",command= lambda:
controller.show_frame(PageOne)).pack()
class PageOne(tk.Frame):
def __init__(self,parent,controller):
tk.Frame.__init__(self,parent)
self.rowconfigure(0, minsize=200, weight=1)
self.columnconfigure(1, minsize=200, weight=1)
txt_edit = tk.Text(self).grid(row=0, column=1, sticky="nsew")
button_frame = tk.Frame(self,bg="lightblue").grid(row=0, column=0, sticky="ns")
btn_open = ttk.Button(button_frame, text="Open").grid(row=0, column=0, sticky="ew", padx=5, pady=5)
btn_save = ttk.Button(button_frame, text="Save As...").grid(row=1, column=0, sticky="ew", padx=5)
button_to_startpage = ttk.Button(button_frame, text="Back to Start Page",
command=lambda:
controller.show_frame(StartPage)).grid(row=2, column=0,
sticky="ew", padx=5,
pady=5)
app=MainWindow()
app.geometry("1280x720")
app.mainloop()
You cannot use pack as well as grid on container
container=tk.Frame(self)
container.pack(side="top",fill="both",expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
pack and grid just don't work well together.
See this entry for more info
You're making a very common mistake on this line:
button_frame = tk.Frame(self,bg="lightblue").grid(row=0, column=0, sticky="ns")
Because you are doing tk.Frame(...).grid(...), button_frame is being set to the result of .grid(...). That makes button_frame None. When you do btn_open = ttk.Button(button_frame, ...), that places the button as a child of the root window rather than a child of button_frame. You're using pack in the root window, so you can't use grid for any other widgets in the root window.
The solution is to properly create button_frame by separating widget creation from widget layout:
button_frame = tk.Frame(...)
button_frame.grid(...)
I was trying to program a kind of calculator in Python using the Tkinter library. My problem is that I watch some pages that says that the way to set de heidth and weidth of a button is using rowconfigure and columnconfigure. The problem is that when I run the script it doesn't work. I don't know what I'm doing bad so pls help me
Here is the code
import tkinter as tk
def insert_number(variable, entry):
result = variable + entry
return result
conjunt = ""
class MainWindow(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.parent = parent
self.grid()
self.config(bg="blue")
self.button1 = tk.Button(text="1", command=insert_number(conjunt, "1")).grid(
column=0, row=0)
self.button1 = tk.Button(text="2", command=insert_number(conjunt, "2")).grid(
column=1, row=0)
self.button1 = tk.Button(text="3", command=insert_number(conjunt, "3")).grid(
column=2, row=0)
self.button1 = tk.Button(text="4", command=insert_number(conjunt, "1")).grid(
column=0, row=1)
self.button1 = tk.Button(text="5", command=insert_number(conjunt, "1")).grid(
column=1, row=1)
self.button1 = tk.Button(text="6", command=insert_number(conjunt, "1")).grid(
column=2, row=1)
self.button1 = tk.Button(text="7", command=insert_number(conjunt, "1")).grid(
column=0, row=2)
self.button1 = tk.Button(text="8", command=insert_number(conjunt, "1")).grid(
column=1, row=2)
self.button1 = tk.Button(text="9", command=insert_number(conjunt, "1")).grid(
column=2, row=2)
self.button1 = tk.Button(text="0", command=insert_number(conjunt, "1")).grid(
column=1, row=3)
self.columnconfigure(0, weight=1)
self.columnconfigure(1, weight=1)
self.rowconfigure(0, weight=1)
self.rowconfigure(1, weight=1)
def give_result(self):
pass
def main():
root = tk.Tk()
root.title("Calculadora")
buttons_frame = MainWindow(root)
buttons_frame.grid()
root.mainloop()
if __name__ == "__main__":
main()
I'm trying to create a canvas widget with a number of widgets embedded within it. Since there will frequently be too many widgets to fit in the vertical space I have for the canvas, it'll need to be scrollable.
import tkinter as tk # for general gui
import tkinter.ttk as ttk # for notebook (tabs)
class instructionGeneratorApp():
def __init__(self, master):
# create a frame for the canvas and scrollbar
domainFrame = tk.LabelFrame(master)
domainFrame.pack(fill=tk.BOTH, expand=1)
# make the canvas expand before the scrollbar
domainFrame.rowconfigure(0,weight=1)
domainFrame.columnconfigure(0,weight=1)
vertBar = ttk.Scrollbar(domainFrame)
vertBar.grid(row=0, column=1, sticky=tk.N + tk.S)
configGridCanvas = tk.Canvas(domainFrame,
bd=0,
yscrollcommand=vertBar.set)
configGridCanvas.grid(row=0, column=0, sticky=tk.N + tk.S + tk.E + tk.W)
vertBar.config(command=configGridCanvas.yview)
# add widgets to canvas
l = tk.Label(configGridCanvas, text='Products')
l.grid(row=1, column=0)
r = 2
for product in ['Product1','Product2','Product3','Product4','Product5','Product6','Product7','Product8','Product9','Product10','Product11','Product12','Product13','Product14','Product15','Product16','Product17','Product18','Product19','Product20']:
l = tk.Label(configGridCanvas, text=product)
l.grid(row=r, column=0)
c = tk.Checkbutton(configGridCanvas)
c.grid(row=r, column=1)
r += 1
ButtonFrame = tk.Frame(domainFrame)
ButtonFrame.grid(row=r, column=0)
removeServerButton = tk.Button(ButtonFrame, text='Remove server')
removeServerButton.grid(row=0, column=0)
# set scroll region to bounding box?
configGridCanvas.config(scrollregion=configGridCanvas.bbox(tk.ALL))
root = tk.Tk()
mainApp = instructionGeneratorApp(root)
root.mainloop()
As best as I can tell, I'm following the effbot pattern for canvas scrollbars, but I end up with either a scrollbar that isn't bound to the canvas, or a canvas that is extending beyond the edges of its master frame:
I've attempted the solutions on these questions, but there's still something I'm missing:
resizeable scrollable canvas with tkinter
Tkinter, canvas unable to scroll
Any idea what I'm doing wrong?
I have added some comments to #The Pinapple 's solution for future reference.
from tkinter import *
class ProductItem(Frame):
def __init__(self, master, message, **kwds):
Frame.__init__(self, master, **kwds)
self.grid_rowconfigure(1, weight=1)
self.grid_columnconfigure(0, weight=1)
self.text = Label(self, text=message, anchor='w')
self.text.grid(row=0, column=0, sticky='nsew')
self.check = Checkbutton(self, anchor='w')
self.check.grid(row=0, column=1)
class ScrollableContainer(Frame):
def __init__(self, master, **kwargs):
#our scrollable container is a frame, this frame holds the canvas we draw our widgets on
Frame.__init__(self, master, **kwargs)
#grid and rowconfigure with weight 1 are used for the scrollablecontainer to utilize the full size it can get from its parent
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
#canvas and scrollbars are positioned inside the scrollablecontainer frame
#the scrollbars take a command parameter which is used to position our view on the canvas
self.canvas = Canvas(self, bd=0, highlightthickness=0)
self.hScroll = Scrollbar(self, orient='horizontal',
command=self.canvas.xview)
self.hScroll.grid(row=1, column=0, sticky='we')
self.vScroll = Scrollbar(self, orient='vertical',
command=self.canvas.yview)
self.vScroll.grid(row=0, column=1, sticky='ns')
self.canvas.grid(row=0, column=0, sticky='nsew')
#We do not only need a command to position but also one to scroll
self.canvas.configure(xscrollcommand=self.hScroll.set,
yscrollcommand=self.vScroll.set)
#This is the frame where the magic happens, all of our widgets that are needed to be scrollable will be positioned here
self.frame = Frame(self.canvas, bd=2)
self.frame.grid_columnconfigure(0, weight=1)
#A canvas itself is blank, we must tell the canvas to create a window with self.frame as content, anchor=nw means it will be positioned on the upper left corner
self.canvas.create_window(0, 0, window=self.frame, anchor='nw', tags='inner')
self.product_label = Label(self.frame, text='Products')
self.product_label.grid(row=0, column=0, sticky='nsew', padx=2, pady=2)
self.products = []
for i in range(1, 21):
item = ProductItem(self.frame, ('Product' + str(i)), bd=2)
item.grid(row=i, column=0, sticky='nsew', padx=2, pady=2)
self.products.append(item)
self.button_frame = Frame(self.frame)
self.button_frame.grid(row=21, column=0)
self.remove_server_button = Button(self.button_frame, text='Remove server')
self.remove_server_button.grid(row=0, column=0)
self.update_layout()
#If the widgets inside the canvas / the canvas itself change size,
#the <Configure> event is fired which passes its new width and height to the corresponding callback
self.canvas.bind('<Configure>', self.on_configure)
def update_layout(self):
#All pending events, callbacks, etc. are processed in a non-blocking manner
self.frame.update_idletasks()
#We reconfigure the canvas' scrollregion to fit all of its widgets
self.canvas.configure(scrollregion=self.canvas.bbox('all'))
#reset the scroll
self.canvas.yview('moveto', '1.0')
#fit the frame to the size of its inner widgets (grid_size)
self.size = self.frame.grid_size()
def on_configure(self, event):
w, h = event.width, event.height
natural = self.frame.winfo_reqwidth() #natural width of the inner frame
#If the canvas changes size, we fit the inner frame to its size
self.canvas.itemconfigure('inner', width=w if w > natural else natural)
#dont forget to fit the scrollregion, otherwise the scrollbar might behave strange
self.canvas.configure(scrollregion=self.canvas.bbox('all'))
if __name__ == "__main__":
root = Tk()
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
sc = ScrollableContainer(root, bd=2)
sc.grid(row=0, column=0, sticky='nsew')
root.mainloop()
From what I can tell you are looking for something like this..
from tkinter import *
class ProductItem(Frame):
def __init__(self, master, message, **kwds):
Frame.__init__(self, master, **kwds)
self.grid_rowconfigure(1, weight=1)
self.grid_columnconfigure(0, weight=1)
self.text = Label(self, text=message, anchor='w')
self.text.grid(row=0, column=0, sticky='nsew')
self.check = Checkbutton(self, anchor='w')
self.check.grid(row=0, column=1)
class ScrollableContainer(Frame):
def __init__(self, master, **kwargs):
Frame.__init__(self, master, **kwargs) # holds canvas & scrollbars
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
self.canvas = Canvas(self, bd=0, highlightthickness=0)
self.hScroll = Scrollbar(self, orient='horizontal',
command=self.canvas.xview)
self.hScroll.grid(row=1, column=0, sticky='we')
self.vScroll = Scrollbar(self, orient='vertical',
command=self.canvas.yview)
self.vScroll.grid(row=0, column=1, sticky='ns')
self.canvas.grid(row=0, column=0, sticky='nsew')
self.canvas.configure(xscrollcommand=self.hScroll.set,
yscrollcommand=self.vScroll.set)
self.frame = Frame(self.canvas, bd=2)
self.frame.grid_columnconfigure(0, weight=1)
self.canvas.create_window(0, 0, window=self.frame, anchor='nw', tags='inner')
self.product_label = Label(self.frame, text='Products')
self.product_label.grid(row=0, column=0, sticky='nsew', padx=2, pady=2)
self.products = []
for i in range(1, 21):
item = ProductItem(self.frame, ('Product' + str(i)), bd=2)
item.grid(row=i, column=0, sticky='nsew', padx=2, pady=2)
self.products.append(item)
self.button_frame = Frame(self.frame)
self.button_frame.grid(row=21, column=0)
self.remove_server_button = Button(self.button_frame, text='Remove server')
self.remove_server_button.grid(row=0, column=0)
self.update_layout()
self.canvas.bind('<Configure>', self.on_configure)
def update_layout(self):
self.frame.update_idletasks()
self.canvas.configure(scrollregion=self.canvas.bbox('all'))
self.canvas.yview('moveto', '1.0')
self.size = self.frame.grid_size()
def on_configure(self, event):
w, h = event.width, event.height
natural = self.frame.winfo_reqwidth()
self.canvas.itemconfigure('inner', width=w if w > natural else natural)
self.canvas.configure(scrollregion=self.canvas.bbox('all'))
if __name__ == "__main__":
root = Tk()
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
sc = ScrollableContainer(root, bd=2)
sc.grid(row=0, column=0, sticky='nsew')
root.mainloop()
I have no bug errors and I was wondering why 'TIMER' is not showing up in the GUI when I run it. It just shows a white box. I`ve tried searching the forums for an issue similar to mine but I failed to find any.
CODE:
import tkinter
class study_timer:
def __init__(self, master):
self.master = master
self.mainframe = tkinter.Frame(self.master, bg='white')
self.mainframe.pack(fill = tkinter.BOTH, expand=True)
self.build_grid()
self.build_banner()
def build_grid(self):
self.mainframe.columnconfigure(0, weight=1)
self.mainframe.rowconfigure(0, weight=0)
self.mainframe.rowconfigure(0, weight=1)
self.mainframe.rowconfigure(0, weight=0)
def build_banner(self):
banner = tkinter.Label(
self.mainframe,
bg='black',
text='TIMER',
fg='white',
font=('Ravie Regular', 30)
)
banner.grid(
row=0, column=0,
stick='ew',
padx=10, pady=10
)
if __name__ == "__main__":
root = tkinter.Tk()
root.mainloop()
You should instantiate an object of the class if you want to run the functions that you defined. The functions are called from constructor(init) in your class structure.
Second, if statement's indentation is wrong.
Third, you should send the root object to init function as parameter.
This will work
import tkinter
class study_timer:
def __init__(self, master):
self.master = master
self.mainframe = tkinter.Frame(self.master, bg='white')
self.mainframe.pack(fill = tkinter.BOTH, expand=True)
self.build_grid()
self.build_banner()
def build_grid(self):
self.mainframe.columnconfigure(0, weight=1)
self.mainframe.rowconfigure(0, weight=0)
self.mainframe.rowconfigure(0, weight=1)
self.mainframe.rowconfigure(0, weight=0)
def build_banner(self):
banner = tkinter.Label(
self.mainframe,
bg='black',
text='TIMER',
fg='white',
font=('Ravie Regular', 30)
)
banner.grid(
row=0, column=0,
stick='ew',
padx=10, pady=10
)
if __name__ == "__main__":
root = tkinter.Tk()
ss = study_timer(root)
root.mainloop()
I'm trying to write a simple ui with Tkinter in python and I cannot get the widgets within a grid to resize. Whenever I resize the main window the entry and button widgets do not adjust at all.
Here is my code:
class Application(Frame):
def __init__(self, master=None):
Frame.__init__(self, master, padding=(3,3,12,12))
self.grid(sticky=N+W+E+S)
self.createWidgets()
def createWidgets(self):
self.dataFileName = StringVar()
self.fileEntry = Entry(self, textvariable=self.dataFileName)
self.fileEntry.grid(row=0, column=0, columnspan=3, sticky=N+S+E+W)
self.loadFileButton = Button(self, text="Load Data", command=self.loadDataClicked)
self.loadFileButton.grid(row=0, column=3, sticky=N+S+E+W)
self.columnconfigure(0, weight=1)
self.columnconfigure(1, weight=1)
self.columnconfigure(2, weight=1)
app = Application()
app.master.title("Sample Application")
app.mainloop()
Add a root window and columnconfigure it so that your Frame widget expands too. That's the problem, you've got an implicit root window if you don't specify one and the frame itself is what's not expanding properly.
root = Tk()
root.columnconfigure(0, weight=1)
app = Application(root)
I use pack for this. In most cases it is sufficient.
But do not mix both!
class Application(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.pack(fill = X, expand =True)
self.createWidgets()
def createWidgets(self):
self.dataFileName = StringVar()
self.fileEntry = Entry(self, textvariable=self.dataFileName)
self.fileEntry.pack(fill = X, expand = True)
self.loadFileButton = Button(self, text="Load Data", )
self.loadFileButton.pack(fill=X, expand = True)
A working example. Note that you have to explicitly set the configure for each column and row used, but columnspan for the button below is a number greater than the number of displayed columns.
## row and column expand
top=tk.Tk()
top.rowconfigure(0, weight=1)
for col in range(5):
top.columnconfigure(col, weight=1)
tk.Label(top, text=str(col)).grid(row=0, column=col, sticky="nsew")
## only expands the columns from columnconfigure from above
top.rowconfigure(1, weight=1)
tk.Button(top, text="button").grid(row=1, column=0, columnspan=10, sticky="nsew")
top.mainloop()