Python Calculator results are not being displayed - python

so i was trying to make a python calculator, that opens like a window, but before the calculations i was trying to make it display the numbers that i clicked, everything was normal, the append, the list, everything was normal until it had to display the actual numbers, where it displays nothing, i tried to make change the label to "hi" for example to see if the problem is with the list, but nothing is being displayed, can someone help me get numbers to be displayed in the "results" area? here is my code:
root = tk.Tk()
color = '#263D42'
numbers = []
Background = tk.Canvas(root, height=600, width=601, bg=color)
Background.pack()
resultBack = tk.Canvas(root, height=150, width=400, bg="#E4E0E0")
resultBack.place(x=50, y=1)
root.title('Calculator')
root.iconphoto(False, tk.PhotoImage(file='plus.ico'))
root.resizable(width = False, height = False)
root.geometry("500x600")
for number in numbers:
label = tk.Label(root, text="hi", bg="black")
label.pack()
frame = tk.Frame(root, bg="white")
frame.place(relwidth=0.8, relheight=0.8, relx=0.1, rely=0.1) #frame
def addOne():
for widget in frame.winfo_children():
widget.destroy()
numbers.append('1')
for number in numbers:
print(number)
label = tk.Label(root, text=number, bg="black")
label.pack()
print(numbers)
one = tk.Button(root, text="1", padx=10, pady=5, fg="#000000", bg="#ffffff", command=addOne)
one.place(x=30, y=30)
root.mainloop()

You should not be creating and deleting your labels like that; you can just change them.
Maybe try something like this:
import tkinter as tk
root = tk.Tk()
numbers = []
root.title('Calculator')
root.resizable(width = False, height = False)
root.geometry("500x600")
label_text = tk.StringVar()
label_text.set('hi')
label = tk.Label(root, textvariable=label_text)
label.pack()
frame = tk.Frame(root, bg="white")
frame.place(relwidth=0.8, relheight=0.8, relx=0.1, rely=0.1) #frame
def addOne():
numbers.append(1)
work = ""
for i in numbers:
work+=str(i)
label_text.set(work)
one = tk.Button(root,
text="1",
padx=10,
pady=5,
fg="#000000",
bg="#ffffff",
command=addOne)
one.place(x=30, y=30)
root.mainloop()
That should get the numbers showing up. StringVars are your friend for these sorts of things. As you update them, tk automatically updates the widget they are attached to.
From here, you will probably want to move things around to look better etc. and you probably don't want to have to add a method for each button (addTwo, addThree, addFour etc.) Let us know if you need more help.

Related

Tkinter window geometry

I'm working on Tkinter window, and I want to set up the height and width of the screen without the geometry function, so I made 2 scales vertical and horizontal, then I use a button with a command that set up the window size in the following code:
root = Tk()
root.title("Root window")
label = Label(root, text="The height").pack()
slay = Scale(root, from_=0, to=200)
slay.pack()
my_label = Label(root, text="The width").pack()
hor = Scale(root, from_=0, to=250, orient=HORIZONTAL)
hor.pack()
def btns():
root.geometry(str(f"{slay.get} x {hor.get}"))
btn = Button(root, text="Setup the window size", command=btns).pack()
And the error is:
line 20, in btns
root.geometry(str(f"{slay.get} x {hor.get}"))
You are just referencing the .get() function, never actually calling them. So you will receive an error.
Call the function using (). Also, there is no space between str(f"{slay.get()} x {hor.get()}").
So it would look something like this:
root.geometry(str(f"{slay.get()}x{hor.get()}"))
This works.
The problem was root.geometry(str(f"{vert.get} x {hori.get}"))
I changed it to this root.geometry(str(f"{vert.get()}x{hori.get()}"))
Simply removed the spaces around 'x' and added () to the get
Also added orient = VERTICAL to slay
root = Tk()
root.title("Root window")
label = Label(root, text="The height").pack()
slay = Scale(root, from_=0, to=200, orient=VERTICAL)
slay.pack()
my_label = Label(root, text="The width").pack()
hor = Scale(root, from_=0, to=250, orient=HORIZONTAL)
hor.pack()
def btns():
print( slay.get(), hor.get() )
root.geometry(str(f"{slay.get()}x{hor.get()}"))
btn = Button(root, text="Setup the window size", command=btns).pack()
root.mainloop()

How do you make a child label smaller than its parent frame?

There is only one frame in my GUI, and it resizes itself to the size of the window. The frame has a child label, and I want the label to always be 1/3 the height of the frame and 1/1.5 the width of the frame. The code below tries to do that but the label always resizes itself to the size of the frame.
import tkinter
tk = tkinter.Tk()
tk.geometry("400x400")
f = tkinter.Frame(tk, bd=5, bg="white")
f.pack(padx=10, pady=10)
def callback(event):
f.config(height=tk.winfo_height(), width=tk.winfo_width())
l.config(width=int(f.winfo_width()/1.5), height=int(f.winfo_height()/3))
l = tkinter.Label(f, text="lead me lord", bg="yellow", relief=tkinter.RAISED, bd=5)
l.pack(side="bottom")
tk.bind("<Configure>", callback)
tk.mainloop()
The width and height of the label are in characters. In order to use pixels, you need to add an empty image to the label:
img = tkinter.PhotoImage() # an image of size 0
l = tkinter.Label(f, text="lead me lord", bg="yellow", relief=tkinter.RAISED, bd=5,
image=img, compound='center')
Actually you don't need to resize the frame in the callback if you add fill="both", expand=1 into f.pack(...):
import tkinter
tk = tkinter.Tk()
tk.geometry("400x400")
f = tkinter.Frame(tk, bd=5, bg="white")
f.pack(padx=10, pady=10, fill="both", expand=1)
def callback(event):
l.config(width=int(f.winfo_width()/1.5), height=int(f.winfo_height()/3))
#l.config(width=event.width*2//3, height=event.height//3) # same as above line if bind on frame
img = tkinter.PhotoImage()
l = tkinter.Label(f, text="lead me lord", bg="yellow", relief=tkinter.RAISED, bd=5,
image=img, compound='center')
l.pack(side="bottom")
f.bind("<Configure>", callback) # bind on frame instead of root window
tk.mainloop()
Given your precise specifications, the best solution is to use place since it lets you use relative widths and heights. However, if you plan to have other widgets in the window, place is rarely the right choice.
This example will do exactly what you asked: place the label at the bottom with 1/3 the height and 1/1.5 the width. There is no need to have a callback for when the window changes size.
Note: I had to change the call to pack for the frame. The text of your question said it would expand to fill the window but the code you had wasn't doing that. I added the fill and expand options.
import tkinter
tk = tkinter.Tk()
tk.geometry("400x400")
f = tkinter.Frame(tk, bd=5, bg="white")
f.pack(padx=10, pady=10, fill="both", expand=True)
l = tkinter.Label(f, text="lead me lord", bg="yellow", relief=tkinter.RAISED, bd=5)
l.place(relx=.5, rely=1.0, anchor="s", relheight=1/3., relwidth=1/1.5)
tkinter.mainloop()

i want to align my code in a perfect order of widgets, so that ui look neat and clean

I want a neat and clean UI for my program it's working well but UI is terribly bad. Can anyone help me to fix this?
I am trying to use grid and place, but due to lack of knowledge of python. I am unable to do it.
#wap to demonstrate use of check button
import tkinter
from tkinter import messagebox
def pd():
if (var1.get())==1:
l1.config(text="You Have Selected Pendrive")
elif (var1.get())==0:
l1.config(text="")
def mcard():
if (var2.get())==1:
l2.config(text="You Have Selected Memory card")
elif (var2.get())==0:
l2.config(text="")
def hdd():
if (var3.get())==1:
l3.config(text="You Have Selected HDD")
elif (var3.get())==0:
l3.config(text="")
def per():
print("Successfully compiled")
msgbox=tkinter.messagebox.askquestion("Closing program","Are you sure?",)
if msgbox=="yes":
win.destroy()
else:
tkinter.messagebox.showinfo('Return','You will now return to the application screen')
win=tkinter.Tk()
var1=tkinter.IntVar()
var2=tkinter.IntVar()
var3=tkinter.IntVar()
win.geometry("500x500+0+0")
cb1=tkinter.Checkbutton(text="Pendrive",height=2,width=15,variable=var1,font=5,cursor="dot",bg="grey",anchor="w",command=pd)
cb2=tkinter.Checkbutton(text="Memory Card",height=2,width=15,variable=var2,font=5,cursor="dot",bg="grey",anchor="w",command=mcard)
cb3=tkinter.Checkbutton(text="HDD",height=2,width=15,variable=var3,font=5,cursor="dot",bg="grey",anchor="w",command=hdd)
b1=tkinter.Button(text="Submit",height=2,width=15,command=per)
# from this line problem begins with UI.
l1=tkinter.Label(height=2,width=30)
l2=tkinter.Label(height=2,width=30)
l3=tkinter.Label(height=2,width=30)
cb1.grid(column=0,row=1)
cb2.grid(column=0,row=2)
cb3.grid(column=0,row=3)
l1.place(x=40,y=300)
l2.place(x=40,y=350)
l3.place(x=40,y=400)
b1.place(x=125,y=450)
win.mainloop()
Actual results are different than I expected it to be. the widgets are not aligned well(I want them to centered)and there isn't enough padding between them( there should be enough space so that it won't look messy ).
If you want better aligned then rather don't use width, height, place() but pack() and grid() and its options. If you use wrong option in pack(), grid() then you will see error message with all available options for pack or grid. pack and grid use different options.
More in documentation: place(), pack(), grid()
import tkinter as tk
from tkinter import messagebox
def pd():
if var1.get():
l1.config(text="You Have Selected Pendrive")
else:
l1.config(text="")
def mcard():
if var2.get():
l2.config(text="You Have Selected Memory card")
else:
l2.config(text="")
def hdd():
if var3.get():
l3.config(text="You Have Selected HDD")
else:
l3.config(text="")
def per():
print("Successfully compiled")
msgbox = messagebox.askquestion("Closing program","Are you sure?",)
if msgbox == "yes":
win.destroy()
else:
messagebox.showinfo('Return', 'You will now return to the application screen')
win = tk.Tk()
win.geometry("500x500+0+0")
var1 = tk.IntVar()
var2 = tk.IntVar()
var3 = tk.IntVar()
cb1 = tk.Checkbutton(win, text="Pendrive", variable=var1, font=5, cursor="dot", bg="grey", anchor="w", command=pd)
cb2 = tk.Checkbutton(win, text="Memory Card", variable=var2, font=5, cursor="dot",bg="grey", anchor="w", command=mcard)
cb3 = tk.Checkbutton(win, text="HDD", variable=var3, font=5, cursor="dot", bg="grey", anchor="w", command=hdd)
cb1.pack(ipadx=10, ipady=10, fill='both', expand=True)
cb2.pack(ipadx=10, ipady=10, fill='both', expand=True)
cb3.pack(ipadx=10, ipady=10, fill='both', expand=True)
l1 = tk.Label(win, background='#bbbbbb')
l2 = tk.Label(win, background='#cccccc')
l3 = tk.Label(win, background='#bbbbbb')
l1.pack(ipadx=10, ipady=10, fill='both', expand=True)
l2.pack(ipadx=10, ipady=10, fill='both', expand=True)
l3.pack(ipadx=10, ipady=10, fill='both', expand=True)
b1 = tk.Button(win, text="Submit", command=per)
b1.pack(side='bottom', ipadx=10, ipady=10, fill='both', expand=True)
win.mainloop()

Frame loosing height when filled tkinter

Hello everyone i am learning to make a gui with tkinter but i run into something and can't find the answer to it i have 3 frames a header a shadow for the header and a main content frame and that works fine
code :
root = Tk()
root.geometry("1080x600")
root.minsize(width=1080, height=600)
root.maxsize(width=1080, height=600)
root.title("learning ui")
headerFrame = Frame(root, height=50, bg="#17181b")
headerShadow = Frame(root, height=3, bg="#08090a")
contentFrame = Frame(root, bg="#17181b")
headerFrame.pack(side=TOP, fill=X)
headerShadow.pack(fill=X)
contentFrame.pack(fill=BOTH, expand=True)
root.mainloop()
Screen shot :
But when i pack something to the header it looses its height.
code:
root = Tk()
root.geometry("1080x600")
root.minsize(width=1080, height=600)
root.maxsize(width=1080, height=600)
root.title("learning ui")
headerFrame = Frame(root, height=50, bg="#17181b")
headerShadow = Frame(root, height=3, bg="#08090a")
contentFrame = Frame(root, bg="#17181b")
headerFrame.pack(side=TOP, fill=X)
headerShadow.pack(fill=X)
contentFrame.pack(fill=BOTH, expand=True)
main.e = Entry(headerFrame)
main.e.pack(side=RIGHT)
main.e.focus_set()
searchBtn = Button(headerFrame, text="Search", command=lambda: callback(retrieve_input()))
searchBtn.pack(side=RIGHT)
def callback(q):
print q
root.mainloop()
Screen shot:
All widgets are designed to "shrink to fit" their children. While this may seem counter-intuitive at first, it's the best way to do widget layout. Don't try to force a frame or window to be a specific size, just put the widgets in that you want and it will end up being the right size.
If you want to turn this feature off you can, but I strongly recommend against it. If you want to know more, search for "overrideredirect".

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