i'm trying to make a simple calculator using Tkinter, but the buttons are too far apart. This is my full code:
from Tkinter import *
root = Tk()
root.title("Calculadora")
display = Entry(root, font = ("Simplified Arabian Fixed", 30), bg = "black", fg = "white", bd = 30).grid(columnspan = 4)
Button7 = Button(root, bd = 10, text= "7", padx = 16, font = ("Simplified Arabian Fixed", 20), bg = "black", fg = "white").grid(column = 0, row = 1)
Button8 = Button(root, bd = 10, text = "8", padx = 16, font = ("Simplified Arabian Fixed", 20), bg = "black", fg = "white").grid(column = 1, row = 1)
Division = Button(root, bd = 10, text = "/", padx = 16, font = ("Simplified Arabian Fixed", 20), bg = "black", fg = "white").grid(column = 2, row = 1)
root.mainloop()
This occours
Is there a way to fix this?
This effect is because the entry is wider than the three buttons. You can set a smaller width and then let the grid geometry manager expand it to cover the width of the buttons with sticky = 'ew'. Also you might want to set justify = 'right' in the entry or it will look funny.
I included some text in the example below:
from Tkinter import *
root = Tk()
root.title("Calculadora")
txt = StringVar() # StringVar to hold entry text
txt.set('123456') # Set StringVar
display = Entry(root, font = ("Simplified Arabian Fixed", 30),
bg = "black", fg = "white", bd = 30, textvariable = txt,
# Set width and justify for entry + sticky to fill available space
width = 1, justify = 'right').grid(columnspan = 4, sticky = 'ew')
Button7 = Button(root, bd = 10, text= "7", padx = 16,
font = ("Simplified Arabian Fixed", 20),
bg = "black", fg = "white").grid(column = 0, row = 1)
Button8 = Button(root, bd = 10, text = "8", padx = 16,
font = ("Simplified Arabian Fixed", 20),
bg = "black", fg = "white").grid(column = 1, row = 1)
Division = Button(root, bd = 10, text = "/", padx = 16,
font = ("Simplified Arabian Fixed", 20),
bg = "black", fg = "white").grid(column = 2, row = 1)
root.mainloop()
Use sticky="ew" and adjust padx in every grid(...) for buttons to expand the buttons to fill the grid cell. Also you assigned the result of grid(...) to all button variables which always be None. So separate the grid(...) function from the creation function, for example:
Button7 = Button(root, bd=10, text="7", padx=16, font=("Simplified Arabian Fixed", 20), bg="black", fg="white")
Button7.grid(row=1, column=0, sticky="ew", padx=2)
Related
I have tried to bring the border center on panel using pos and size but border remains constant. it was not moving to center and also tried using wx.ALIGN_CENTER
Here is my code:
import wx
class myframe(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title= "asdsad")
self.login_panel = PasswordPanel(self)
self.Layout()
self.ShowFullScreen(True)
self.Show()
class PasswordPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent=parent)
self.panel = wx.Panel(self,pos=(350,350), size=(500,250), style=wx.SUNKEN_BORDER)
if __name__ == '__main__':
app = wx.App(False)
frame = myframe()
app.MainLoop()
The above code works as expected but if I include below to the panel code the border will expand.
self.quote = wx.StaticText(self.panel, label="")
self.result = wx.StaticText(self.panel, label="")
self.result.SetForegroundColour(wx.RED)
self.ok_button = wx.Button(self.panel, label="Ok")
self.cancel_button = wx.Button(self.panel, wx.ID_OK, 'Cancel')
self.lblname = wx.StaticText(self.panel, label="Enter Password:")
self.editname = wx.TextCtrl(self.panel, size=(240, -1), style=wx.TE_PASSWORD)
self.ok_button.SetFocus()
# Set sizer for the panel content
self.sizer = wx.GridBagSizer(0, 0)
self.sizer.Add(self.quote, (15, 45), flag = wx.ALL, border = 5)
self.sizer.Add(self.result, (15, 46), flag = wx.ALL, border = 5)
self.sizer.Add(self.lblname, (16, 45), flag = wx.ALL, border = 5)
self.sizer.Add(self.editname, pos = (16,46), span = (1,3), flag = wx.EXPAND|wx.ALL, border = 5)
self.sizer.Add(self.ok_button, pos = (17, 47),flag = wx.ALL, border = 5)
self.sizer.Add(self.cancel_button, pos = (17, 48),flag = wx.ALL, border = 5)
self.windowSizer = wx.BoxSizer()
self.windowSizer.Add(self.panel, 1, wx.ALL | wx.EXPAND, 5)
# Use the sizers
self.panel.SetSizerAndFit(self.sizer)
self.SetSizerAndFit(self.windowSizer)
self.Layout()
Please advise on this.
When you put your panel in the BoxSizer and you self.SetSizerandFit it, you are expanding the panel to the size of the parent PasswordPanel (self) that fills myframe.
If you remove the code commented below, the border stays at the center of the panel:
# Set sizer for the panel content
self.sizer = wx.GridBagSizer(0, 0)
self.sizer.Add(self.quote, (15, 45), flag = wx.ALL, border = 5)
self.sizer.Add(self.result, (15, 46), flag = wx.ALL, border = 5)
self.sizer.Add(self.lblname, (16, 45), flag = wx.ALL, border = 5)
self.sizer.Add(self.editname, pos = (16,46), span = (1,3), flag = wx.EXPAND|wx.ALL, border = 5)
self.sizer.Add(self.ok_button, pos = (17, 47),flag = wx.ALL, border = 5)
self.sizer.Add(self.cancel_button, pos = (17, 48),flag = wx.ALL, border = 5)
#self.windowSizer = wx.BoxSizer()
#self.windowSizer.Add(self.panel, 0, wx.ALL, 5)
# Use the sizers
self.panel.SetSizerAndFit(self.sizer)
#self.SetSizerAndFit(self.windowSizer)
self.Layout()
I am trying to make a GUI in tkinter. So far I have reached this level.
The problem is, I am not able to centre the 4 buttons at the bottom, one of them is going out of the assigned width. This is because while making a top frame, I have assigned columnspan to be 3. If I make it 4 then the centring of the middle part goes off.
import Tkinter as tk
root = tk.Tk()
root.title('Steady State Data Processing')
root.geometry('{}x{}'.format(900, 500))
topFrame = tk.Frame(root, bg = 'lavender', width = 900, height=100, relief = 'raised') # , padx = 100, pady=100
topFrame.grid(row = 0, column = 0, columnspan = 3, sticky="w")
labelCps = tk.Label(root, text='Cps', width = 0, height = 0, padx = 10, pady = 10)
labelIgn = tk.Label(root, text='Ign', width = 0, height = 0, padx = 10, pady = 10)
labelInj = tk.Label(root, text='Inj', width = 0, height = 0, padx = 10, pady = 10)
labelCps.grid(row = 1, column = 0, sticky='we')
labelIgn.grid(row = 1, column = 1, sticky='we')
labelInj.grid(row = 1, column = 2, sticky='we')
cpsFrame = tk.Frame(root, width = 300, height = 100, relief = 'raised') # , padx = 100, pady=100
cpsFrame.grid(row = 2, column = 0, sticky="nsew")
ignFrame = tk.Frame(root, width = 300, height = 100, relief = 'raised') # , padx = 100, pady=100
ignFrame.grid(row = 2, column = 1, sticky="nsew")
injFrame = tk.Frame(root, width = 300, height = 100, relief = 'raised') # , padx = 100, pady=100
injFrame.grid(row = 2, column = 2, sticky="nsew")
labelAdv = tk.Label(cpsFrame, anchor = 'center', text='Cps adv threshold:')
labelAdv.grid(row = 0, column = 0, sticky = 'w')
entryAdv = tk.Entry(cpsFrame)
entryAdv.grid(row = 0, column = 1, sticky = 'e')
labelIgn = tk.Label(ignFrame, justify = 'left', text = 'Dwell start threshold:')
labelIgn.grid(row = 0, column = 0, sticky = 'w')
entryIgn = tk.Entry(ignFrame)
entryIgn.grid(row = 0, column = 1)
labelIgn = tk.Label(ignFrame, anchor = 'center', text = 'Dwell end threshold:')
labelIgn.grid(row = 1, column = 0)
entryIgn = tk.Entry(ignFrame)
entryIgn.grid(row = 1, column = 1)
labelInj = tk.Label(injFrame, anchor = 'center', text = 'Inj start threshold:')
labelInj.grid(row = 0, column = 0)
entryInj = tk.Entry(injFrame)
entryInj.grid(row = 0, column = 1)
labelInj = tk.Label(injFrame, anchor = 'center', text = 'Inj end threshold:')
labelInj.grid(row = 1, column = 0)
entryInj = tk.Entry(injFrame)
entryInj.grid(row = 1, column = 1)
root.grid_rowconfigure(3, pad = 50)
applyButton = tk.Button(root, text = 'Apply', padx = 30, pady = 15)
applyButton.grid(row = 3, columnspan = 3)
text = ['Plot raw data', 'Plot tooth rpm', 'Plot cycle rpm', 'Plot ign data']
count = 0
for t in text:
dataButton = tk.Button(root ,text = t, width = 5, height = 5 ,anchor = 'center', padx = 30, pady = 15)
dataButton.grid(row = 4, column = count, sticky = 'news')
# dataButton.grid_columnconfigure(count, weight = 2)
count = count + 1
root.mainloop()
To center the buttons, they need to be in a frame. Second, to make them fill the space allocated to them by grid, you have to configure the grid columns in the frame to expand. I'm not sure whether you wanted padding between the buttons, but I added some to the grid command.
import Tkinter as tk
root = tk.Tk()
root.title('Steady State Data Processing')
root.geometry('{}x{}'.format(900, 500))
topFrame = tk.Frame(root, bg = 'lavender', width = 900, height=100, relief = 'raised') # , padx = 100, pady=100
topFrame.grid(row = 0, column = 0, columnspan = 3, sticky="w")
labelCps = tk.Label(root, text='Cps', width = 0, height = 0, padx = 10, pady = 10)
labelIgn = tk.Label(root, text='Ign', width = 0, height = 0, padx = 10, pady = 10)
labelInj = tk.Label(root, text='Inj', width = 0, height = 0, padx = 10, pady = 10)
labelCps.grid(row = 1, column = 0, sticky='we')
labelIgn.grid(row = 1, column = 1, sticky='we')
labelInj.grid(row = 1, column = 2, sticky='we')
cpsFrame = tk.Frame(root, width = 300, height = 100, relief = 'raised') # , padx = 100, pady=100
cpsFrame.grid(row = 2, column = 0, sticky="nsew")
ignFrame = tk.Frame(root, width = 300, height = 100, relief = 'raised') # , padx = 100, pady=100
ignFrame.grid(row = 2, column = 1, sticky="nsew")
injFrame = tk.Frame(root, width = 300, height = 100, relief = 'raised') # , padx = 100, pady=100
injFrame.grid(row = 2, column = 2, sticky="nsew")
labelAdv = tk.Label(cpsFrame, anchor = 'center', text='Cps adv threshold:')
labelAdv.grid(row = 0, column = 0, sticky = 'w')
entryAdv = tk.Entry(cpsFrame)
entryAdv.grid(row = 0, column = 1, sticky = 'e')
labelIgn = tk.Label(ignFrame, justify = 'left', text = 'Dwell start threshold:')
labelIgn.grid(row = 0, column = 0, sticky = 'w')
entryIgn = tk.Entry(ignFrame)
entryIgn.grid(row = 0, column = 1)
labelIgn = tk.Label(ignFrame, anchor = 'center', text = 'Dwell end threshold:')
labelIgn.grid(row = 1, column = 0)
entryIgn = tk.Entry(ignFrame)
entryIgn.grid(row = 1, column = 1)
labelInj = tk.Label(injFrame, anchor = 'center', text = 'Inj start threshold:')
labelInj.grid(row = 0, column = 0)
entryInj = tk.Entry(injFrame)
entryInj.grid(row = 0, column = 1)
labelInj = tk.Label(injFrame, anchor = 'center', text = 'Inj end threshold:')
labelInj.grid(row = 1, column = 0)
entryInj = tk.Entry(injFrame)
entryInj.grid(row = 1, column = 1)
root.grid_rowconfigure(3, pad = 50)
applyButton = tk.Button(root, text = 'Apply', padx = 30, pady = 15)
applyButton.grid(row = 3, columnspan = 3)
text = ['Plot raw data', 'Plot tooth rpm', 'Plot cycle rpm', 'Plot ign data']
count = 0
# Button frame
frame = tk.Frame(root)
frame.grid(row=4, column=0, sticky='news', columnspan=4)
for t in text:
# Expand the column widths as required by the window cavity.
frame.grid_columnconfigure(count, weight=1)
dataButton = tk.Button(frame ,text = t, width = 5, height = 5 ,anchor = 'center', padx = 30, pady = 15)
dataButton.grid(row = 0, column = count, sticky = 'news', padx=30)
# dataButton.grid_columnconfigure(count, weight = 2)
count = count + 1
root.mainloop()
So I have been teaching myself Object Oriented Programming for Tkinter projects as I clearly see that they are much more organized for large amounts of coding. However I must admit that I've been coasting by simply copying various bits of coding from online, not fully understanding what its purpose is.
This has lead me to the point that my code does not work at all and I have no idea why not. The first issue is an issue with simply changing an aspect of other widgets.
I have this sample code:
import Tkinter as tk
LARGE_FONT = ("Verdana", 12)
class SeaofBTCapp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **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)
self.frames = {}
frame = StartPage(container, self)
self.frames[StartPage] = 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 = tk.Label(self, text = "Start Page", font = LARGE_FONT)
label.pack(pady = 10, padx = 10)
button = tk.Button(self, text = "Change Label", command = self.change)
button.pack(pady = 10, padx = 10)
def change(self):
label["text"] = "It has changed"
app = SeaofBTCapp()
app.mainloop()
Which SHOULD be a simple enough code that, with a button press, change the label from "Start Page" to "It has changed". But whenever I run it, it says that the global variable "label" is not defined. Additionally, if I then change it to self.label, it states that StartPage instance has no attribute 'label'. I don't know what I'm doing wrong.
Additionally, in a similar vein, I'm working on a project that has a SideBar class and a Main class tied to one MainApplication class. The Main class takes a value and displays it on a Frame in the Main class. Following this, a button in the SideBar increases that value by 1. But the Main display doesn't update and I have no idea how to tie the Main updating with the button in the SideBar.
import Tkinter as tk
something = [0, 6]
class Main():
def __init__(self, root):
mainboard = tk.Frame(root, height = 100, width = 100)
self.maincanvas = tk.Canvas(mainboard, bd = 1, bg = "white")
mainboard.grid(row = 0, column = 0)
self.maincanvas.grid(row = 0, column = 0)
self.maincanvas.create_text(45, 50, anchor = "center", text = str(something[1]))
class SideBar():
def __init__(self, root):
sidebarframe = tk.Frame(root, height = 100, width = 100)
button = tk.Button(sidebarframe, width = 20, text = "Change Value", command = self.add)
sidebarframe.grid(row = 0, column = 1)
button.grid(row = 0, column = 0)
def add(self):
something[1] += 1
print something[1]
class MainApplication():
def __init__(self, parent):
self.parent = parent
self.sidebar = SideBar(self.parent)
self.main = Main(self.parent)
if __name__ == "__main__":
root = tk.Tk()
MainApplication(root)
root.mainloop()
All help would be appreciated, but please try and not use a lot of technical terms, as I am still learning.
In the first scenario replace:
label = tk.Label(self, text = "Start Page", font = LARGE_FONT)
label.pack(pady = 10, padx = 10)
With:
self.label = tk.Label(self, text = "Start Page", font = LARGE_FONT)
self.label.pack(pady = 10, padx = 10)
And also in the function change put it like this:
self.label["text"] = "It has changed"
And in your second problem i changed the code a little bit so it works:
import Tkinter as tk
something = [0, 6]
class Main():
def __init__(self, root):
mainboard = tk.Frame(root, height = 100, width = 100)
self.maincanvas = tk.Canvas(mainboard, bd = 1, bg = "white")
mainboard.grid(row = 0, column = 0)
self.maincanvas.grid(row = 0, column = 0)
self.maincanvas.create_text(45, 50, anchor = "center", text = str(something[1]))
class SideBar():
def __init__(self, root, main):
self.main = main # Putting the main object to self.main
sidebarframe = tk.Frame(root, height = 100, width = 100)
button = tk.Button(sidebarframe, width = 20, text = "Change Value", command = self.add)
sidebarframe.grid(row = 0, column = 1)
button.grid(row = 0, column = 0)
def add(self):
something[1] += 1
self.main.maincanvas.delete("all") # Removing everything from canvas
self.main.maincanvas.create_text(45, 50, anchor = "center", text = str(something[1])) # Inserting the new value
print something[1]
class MainApplication():
def __init__(self, parent):
self.parent = parent
self.main = Main(self.parent) # The main needs to run first
self.sidebar = SideBar(self.parent, self.main) # So that SideBar can use its canvas
if __name__ == "__main__":
root = tk.Tk()
MainApplication(root)
root.mainloop()
This question already has answers here:
Tkinter: AttributeError: NoneType object has no attribute <attribute name>
(4 answers)
Closed 7 years ago.
Hello I am making a GUI for a program with Tkinter, but I keep getting an error:
Traceback (most recent call last):
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1470, in __call__
return self.func(*args)
File "C:\Users\jorge\Desktop\new 1.py", line 53, in browse_button
self.browse_entry.delete(0,END)
AttributeError: 'NoneType' object has no attribute 'delete'"
I am a noobie what it comes to classes so I don't know what I'm making wrong.
If you could help me I would appreciate it.
Thanks in advance!!
from Tkinter import *
from tkFileDialog import *
import ttk,os
class App(Tk):
def __init__(self, *args, **kwargs):
Tk.__init__(self, *args, **kwargs)
self.title("Subtitles Master")
self.iconbitmap(default = r"C:\Users\jorge\Desktop\Programas Python\notepad.ico")
mainframe = Frame(self)
mainframe.pack(side = "top")
mainframe.grid_rowconfigure(0, weight = 1)
mainframe.grid_columnconfigure(0, weight = 1)
self.frames = {}
for F in (StartPage, Timing):
frame = F(mainframe, 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(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
filler1 = Frame(self, width = 30, height = 20).grid(column = 4, row = 0, rowspan = 2)
syncsubs_button = ttk.Button(self, text = "Sync Subtitles", state = DISABLED).grid(column = 5, row = 0)
timing_button = ttk.Button(self, text = "Edit Timing", command = lambda: controller.show_frame(Timing)).grid(column = 5, row = 1)
filler2 = Frame(self, width = 20, height = 20).grid(column = 6, row = 0, rowspan = 2)
syncsubs_label= Label(self, font = ("Alien Encounters", 20), text = "Sync Subtitles", fg = "dark green").grid(row = 2, columnspan = 6)
browse_label = Label(self, font = ("Calibri",12), text = "Subtitles to sync:").grid(row = 3, column = 0, sticky = "w")
filename1 = StringVar()
self.browse_entry = Entry(self, textvariable = filename1, width = 50).grid(row = 4, column = 1, columnspan = 5)
browse_button = ttk.Button(self, text = "Browse", command = self.browse_button).grid(row = 4, column = 0)
def browse_button(self):
filename = askopenfilename(title = "Choose a file",filetypes = (("Subtitles", "*.srt"), ("Text", "*.txt")))
self.browse_entry.delete(0,END)
self.browse_entry.insert(0,filename)
return filename
class Timing(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
filler1 = Frame(self, width = 30, height = 20).grid(column = 4, row = 0, rowspan = 2)
syncsubs_button = ttk.Button(self, text = "Sync Subtitles", command = lambda: controller.show_frame(StartPage)).grid(column = 5, row = 0)
timing_button = ttk.Button(self, text = "Edit Timing", state = DISABLED).grid(column = 5, row = 1)
filler2 = Frame(self, width = 20, height = 20).grid(column = 6, row = 0, rowspan = 2)
syncsubs_label= Label(self, font = ("Alien Encounters", 20), text = "Edit Timing", fg = "dark red").grid(row = 2, columnspan = 6)
window = App()
window.mainloop()
The problem is this line:
# returns None (Entry.grid(...))
self.browse_entry = Entry(self, textvariable = filename1, width = 50).grid(row = 4, column = 1, columnspan = 5)
Change to two lines:
# returns entry
self.browse_entry = Entry(self, textvariable = filename1, width = 50)
# do stuff with entry
self.browse_entry.grid(row = 4, column = 1, columnspan = 5)
Working on a Python 2.7.10 program, for a password gui but it is giving the error that Application is not defined. I am not sure if there is something wrong with Class Application(Frame) or app = Application(root), because it ask for me to define Application but I don't why they would ask me.
from Tkinter import *
class Application(Frame):
def _init_(self, master):
Frame._init_(self,master)
self.grid()
self.create_widgets()
def create_widgets(self):
self.instruction = Label(self, text = "Enter the password")
self.instruction.grid(row = 0, column = 0, columnspan = 2, sticky = W)
self.password = Entry(self)
self.password.grid(row = 1, column = 1, sticky = W)
self.submit_button = Button(self, text = "Submit", commmand = self.reveal)
self.submit_button.grid(row = 2, column = 0, sticky = W)
self.text = Text(self, width = 35, height = 5, wrap = WORD)
self.text.grid(row = 3, column = 0, columnspan = 2, sticky = W)
def reveal(self):
content = self.password.get()
if content == "password":
message = "You have the order"
else:
message = "Access denied."
self.text.delete(0.0, END)
self.text.insert(0.0, message)
root = Tk()
root.title("Password")
root.geometry("250x150")
app= Application(root)
root.mainloop()
I've fixed your code, here it is:
from Tkinter import *
class Application(Frame):
def __init__(self, master):
Frame.__init__(self,master)
self.grid()
self.create_widgets()
def create_widgets(self):
self.instruction = Label(self, text = "Enter the password")
self.instruction.grid(row = 0, column = 0, columnspan = 2, sticky = W)
self.password = Entry(self)
self.password.grid(row = 1, column = 1, sticky = W)
self.submit_button = Button(self, text = "Submit", command = self.reveal)
self.submit_button.grid(row = 2, column = 0, sticky = W)
self.text = Text(self, width = 35, height = 5, wrap = WORD)
self.text.grid(row = 3, column = 0, columnspan = 2, sticky = W)
def reveal(self):
content = self.password.get()
if content == "password":
message = "You have the order"
else:
message = "Access denied."
self.text.delete(0.0, END)
self.text.insert(0.0, message)
root = Tk()
root.title("Password")
root.geometry("250x150")
app= Application(root)
root.mainloop()
Your problems were:
You used _init_ instead of __init__
Typo of "commmand" instead of "command"
Last two lines of procedure reveal in Application were incorrectly indented (logic error, not syntax or run-time)
It wasn't really clear what your question was to be honest and I just did this in Python 3.4.3 and made changes so that it should run in Python 2.7.10. I hope that helps.