How to arrange buttons in a row? - python

I have defined separate functions, and have a main() function.
In the main() function, I have several buttons, which call to other functions when clicked.
eg.
def main():
global root
global tkinter
global canvas
root = Tk()
root.title("Shapes Quiz - Flow Computing")
Button(root, text ="1", bg="Grey", width=10, command=pentagon).pack()
Button(root, text ="2", bg="Grey", width=10, command=circle).pack()
Button(root, text ="3", bg="Grey", width=10, command=diamond).pack()
Button(root, text ="4", bg="Grey", width=10, command=hexagon).pack()
Button(root, text ="5", bg="Grey", width=10, command=triangle).pack()
Button(root, text ="6", bg="Grey", width=10, command=square).pack()
Button(root, text ="7", bg="Grey", width=10, command=rectangle).pack()
Button(root, text ="8", bg="Grey", width=10, command=heptagon).pack()
Button(root, text ="9", bg="Grey", width=10, command=octagon).pack()
Button(root, text ="10", bg="Grey", width=10, command=oval).pack()
Button(root, text ="Help", bg="Grey", width=10, command=help).pack()
Button(root, text ="Clear", bg="Red", width=10, command=clearshapes).pack()
Button(root, text ="QUIT", bg="Red", width=10, command=quit).pack()
I'm sure there must be an easier way to organize these buttons. I have heard of the use of frames and grids, and even co-ordinates; but I am still unsure of how to do this.
I would like to organize the buttons so they are horizontal, not vertical as they are appearing currently.

Change pack() to pack(side='left').

Definitely, there is an easier way to do this with the grid geometry manager (the link is already in the comments):
# ...
root.title("Shapes Quiz - Flow Computing")
BUTTONS = [{"text":"1", "bg":"Grey", "width":10, "command":pentagon},
{"text":"2", "bg":"Grey", "width":10, "command":circle},
# Rest of the buttons
{"text":"QUIT", "bg":"Red", "width":10, "command":quit}]
for i, options in enumerate(BUTTONS):
Button(root, **options).grid(row=0, column=i)
Note that you always use almost the same code, so it may look cleaner if you use a for loop and declare the options of the widgets in advance.

Related

How do I get image under the text In Tkinter?

I recently started learning Python and Tkinter. I started about a month ago. But let's get to the point.
I have been making a random software (so don't mock) for 1 day now, and the code is ready, but I still need to make the app itself, so I have been doing it, but face a problem when making background changing buttons. I made buttons which change the background to either a colour or a picture.
The normal colours work really well, but the image seems to be acting weird. I got the image appearing from the button, but the problem is, when I click the button, the image displays OVER the texts, entry etc.
"Code Fix" that works for a non-changing picture:
Tkinter.Label(window, i=bgimg, compound=Tkinter.CENTER).pack()
I haven't seen many people have this problem. I saw one, and that worked (if I would have a non-changeable background), but because I have the buttons, the code just doesn't care about it. (The code that would have helped for a non-changing picture.)
Here is the code:
from tkinter import *
import tkinter as tk
import tkinter
window=Tk()
bgimg= tk.PhotoImage(file = "C:\\Users\\Hoze\\Downloads\\Hoze (1).png")
btn=Button(window, text="Convert", fg='blue', padx=50)
btn.place(x=220, y=380)
def myClick():
myLabel = Label(window, window.configure(bg='red'))
myLabel.pack()
btn=Button(window, text="Red", fg='red', padx=20, command=myClick)
btn.place(x=520, y=150)
def myClick():
myLabel = Label(window, window.configure(bg='blue'))
myLabel.pack()
btn=Button(window, text="Blue", fg='blue', padx=19, command=myClick)
btn.place(x=520, y=200)
def myClick():
myLabel = Label(window, window.configure(bg='green'))
myLabel.pack()
btn=Button(window, text="Green", fg='green', padx=15, command=myClick)
btn.place(x=520, y=300)
def myClick():
myLabel = Label(window, window.configure(bg='orchid'))
myLabel.pack()
btn=Button(window, text="Default", fg='orchid', padx=11, command=myClick)
btn.place(x=520, y=250)
# Here is the problem, and here is the code that
# put the picture like it should UNDER the text
# (if i put the code to the start)
# (But then it does't change to the other colours)
def myClick():
myLabel= Label(window, i=bgimg, )
myLabel.pack()
btn=Button(window, text="Cool", fg='aqua', padx=11, command=myClick)
btn.place(x=520, y=250)
# If i now run this code, the picture will come
# on top of the text.
lbl=Label(window, text=" Extract a word here, \n that you want make secret!", fg='blue', font=("Helvetica", 16))
lbl.place(x=166 , y=50)
lbl=Label(window, text="Your Secret Word is: ", fg='blue', font=("Helvetica", 10))
lbl.place(x=120, y=300)
txtfld=Entry(window, text="This is Entry Widget", bd=5)
txtfld.place(x=234, y=150)
window.title('Hoze Secret Lenguage Converter')
window.geometry("600x500+10+10")
window.minsize(600, 500)
window.maxsize(600, 500)
window.iconbitmap("C:\\Users\\Hoze\\Music\\Coding\\Project Secret\\favicon.ico")
window.configure(bg='green')
window.mainloop()
This should make your stuff
#import tkinter as tk
from email.mime import image
from tkinter import *
window=Tk()
bgimg= PhotoImage(file = "C:\\Users\\Hoze\\Downloads\\Hoze (1).png")
myLabel= Label(window, i=bgimg )
myLabel.pack()
myLabel.pack_forget()
btn=Button(window, text="Convert", fg='blue', padx=50)
btn.place(x=220, y=380)
def myClick():
myLabel.pack_forget()
window.configure(bg='red')
btn=Button(window, text="Red", fg='red', padx=20, command=myClick)
btn.place(x=520, y=150)
def myClick():
myLabel.pack_forget()
window.configure(bg='blue')
btn=Button(window, text="Blue", fg='blue', padx=19, command=myClick)
btn.place(x=520, y=200)
def myClick():
myLabel.pack_forget()
window.configure(bg='green')
btn=Button(window, text="Green", fg='green', padx=15, command=myClick)
btn.place(x=520, y=300)
def myClick():
myLabel.pack_forget()
window.configure(bg='orchid')
btn=Button(window, text="Default", fg='orchid', padx=11, command=myClick)
btn.place(x=520, y=250)
#Here is the problem, and here is the code that put the picture like it should UNDER the text (if i put the code to the start)(But then it does't change to the other colours)
def myClick():
myLabel.pack()
btn=Button(window, text="Cool", fg='aqua', padx=11, command=myClick)
btn.place(x=520, y=250)
#If i now run this code, the picture will come on top of the text. I hope yall get it, im kinda new
#
lbl=Label(window, text=" Extract a word here, \n that you want make secret!", fg='blue', font=("Helvetica", 16))
lbl.place(x=166 , y=50)
lbl=Label(window, text="Your Secret Word is: ", fg='blue', font=("Helvetica", 10))
lbl.place(x=120, y=300)
txtfld=Entry(window, text="This is Entry Widget", bd=5)
txtfld.place(x=234, y=150)
window.title('Hoze Secret Lenguage Converter')
window.geometry("600x500+10+10")
window.minsize(600, 500)
window.maxsize(600, 500)
window.iconbitmap("C:\\Users\\Hoze\\Music\\Coding\\Project Secret\\favicon.ico")
window.configure(bg='green')
window.mainloop()

How do I use grid_forget more than once in tkinter?

I'm trying to give myself Excercises using imports and keeping programs and modules separate from each other. In this particular excercise I've given myself, I have a basic feet-to-inches and inches-to-feet converter.
Everything works except for one problem. Where the answer is displayed on the GUI, a new answer covers the old answer, rather than replace.
import tkinter as tk
from tkinter import E, W
import Converter
window = tk.Tk()
window.title("Converter")
answer_label = tk.Label(window, text="No Answer")
answer_label.grid(row=5)
def feet_to_inches_function(old_label):
old_label.grid_forget()
answer_label = tk.Label(window, text=Converter.feet_to_inches(int(entry_bar.get())))
answer_label.grid(row=5)
def inches_to_feet_function(old_label):
old_label.grid_forget()
answer = tk.Label(window, text=Converter.inches_to_feet(int(entry_bar.get())))
answer.grid(row=5)
title_label = tk.Label(window, text="Convert")
entry_bar = tk.Entry(window, font=('HELVETICA', 10))
fti_button = tk.Button(window, text="Feet to Inches", command=lambda: feet_to_inches_function(answer_label))
itf_button = tk.Button(window, text="Inches to Feet", command=lambda: inches_to_feet_function(answer_label))
quit_button = tk.Button(window, text="Quit", command=window.destroy)
title_label.grid(row=0, column=0, sticky=W)
entry_bar.grid(row=1, columnspan=2, sticky=(E, W))
fti_button.grid(row=3, column=0)
itf_button.grid(row=3, column=1)
quit_button.grid(row=4, columnspan=2, sticky=(E, W))
window.mainloop()
Also as a separate question,I'm having a hard time understanding mainloop.I know that it makes the program go in an infinate loop, but from where? I don't see any logical evidence that shows that my code is on an endless loop.
Thanks so much
Here's a solution for you:
import tkinter as tk
from tkinter import E, W
window = tk.Tk()
window.title("Converter")
answer_label = tk.Label(window, text="No Answer")
answer_label.grid(row=5)
def feet_to_inches_function():
answer_label.configure(text='As you want (INCHES)')
def inches_to_feet_function():
answer_label.configure(text='As you want (FEET)')
title_label = tk.Label(window, text="Convert")
entry_bar = tk.Entry(window, font=('HELVETICA', 10))
fti_button = tk.Button(window, text="Feet to Inches", command=feet_to_inches_function)
itf_button = tk.Button(window, text="Inches to Feet", command=inches_to_feet_function)
quit_button = tk.Button(window, text="Quit", command=window.destroy)
title_label.grid(row=0, column=0, sticky=W)
entry_bar.grid(row=1, columnspan=2, sticky=(E, W))
fti_button.grid(row=3, column=0)
itf_button.grid(row=3, column=1)
quit_button.grid(row=4, columnspan=2, sticky=(E, W))
window.mainloop()
All you need is to configure the text of the Label in both functions.

How to hide a part of the frame through button pressing

I have a window with two parts. One part is to do some settings. I want to hide it until the user press a setting button. is it possible to hide a part of the frame that contains many widgets?
I have seen many examples to hide a widget in tkinter (eg. pack_forget and grid_forget). In my case, I am trying to hide a part of the frame through a button press (that contains more than one widgets). Any suggestions please
I can't use more than one frames because of some issues.
import tkinter as tk
def startFn():
pass
#fn body
def stopFn():
pass
#fn body
def FnToShow():
pass
#fn body ???
def FnToHide():
pass
#fn body ???
root = tk.Tk()
root.geometry('600x400')
#two containers like this.
#trying to hide container_2 untill the user press settingBtn
container_1 = tk.Frame(root, borderwidth=2, relief="solid")
container_2 = tk.Frame(root, borderwidth=2, relief="solid")
startBtn = tk.Button(container_1, text = "Start", command =startFn)
startBtn.grid(row=4, column=4)
stopBtn = tk.Button(container_1, text = "Stop", command= stopFn)
stopBtn.grid(row=5, column=4)
settingBtn = tk.Button(container_1, text = "Settings", command= FnToShow)
settingBtn.grid(row=6, column=4)
setting_1 = tk.Label(container_2, text = "Setting-1", fg='#000000')
setting_1.grid(row=3, column=10)
setting_2 = tk.Label(container_2, text = "Setting-2", fg='#000000')
setting_2.grid(row=4, column=10)
closeSettingBtn = tk.Button(container_2, text = "close Settings", command= FnToHide)
closeSettingBtn.grid(row=5, column=10)
container_1.pack(side="left", expand=True, fill="x", padx=1, pady=1)
container_2.pack(side="right",expand=True, fill="x", padx=1, pady=1)
root.mainloop()
You could show/hide the entire container_2 using the functions FnToShow and FnToHide:
something like this:
import tkinter as tk
def startFn():
pass
def stopFn():
pass
def FnToShow():
container_2.pack(side="right",expand=True, fill="x", padx=1, pady=1)
def FnToHide():
container_2.pack_forget()
root = tk.Tk()
root.geometry('600x400')
container_1 = tk.Frame(root, borderwidth=2, relief="solid")
container_2 = tk.Frame(root, borderwidth=2, relief="solid")
startBtn = tk.Button(container_1, text="Start", command =startFn)
startBtn.grid(row=4, column=4)
stopBtn = tk.Button(container_1, text="Stop", command= stopFn)
stopBtn.grid(row=5, column=4)
settingBtn = tk.Button(container_1, text="Settings", command= FnToShow)
settingBtn.grid(row=6, column=4)
setting_1 = tk.Label(container_2, text="Setting-1", fg='#000000')
setting_1.grid(row=3, column=10)
setting_2 = tk.Label(container_2, text="Setting-2", fg='#000000')
setting_2.grid(row=4, column=10)
closeSettingBtn = tk.Button(container_2, text="close Settings", command= FnToHide)
closeSettingBtn.grid(row=5, column=10)
container_1.pack(side="left", expand=True, fill="x", padx=1, pady=1)
root.mainloop()

How to get a variable to actually show in tkinter?

So basically I am practising using Tkinter and I was going to make a little clicker game based on anime. I have researched loads, however, no matter what I try the text saying how many RC cells I have won't show anything at all. please keep it simple as I'm still new to coding.
from tkinter import *
rcc=1
x=1
#click function
def click():
global rcc
rcc=rcc+1
return rcc
while x==1:
rccc=str(rcc)
window=Tk()
window.title("my click game boi")
rc=StringVar()
rc.set=(rccc)
window.configure(background="black")
##### my photo
photo1=PhotoImage(file="kanekipic.gif")
Label (window, image=photo1, bg='black') .grid(row=0, column=0, sticky=E)
Button(window, text="eat", width=3, command=click) .grid(row=3, column=0,
sticky=W)
Label1=Label(window, textvariable=rc, bg="red", fg="white") .grid(row=1, column=0, sticky=S)
print (rcc)
window.mainloop()
The best solution (in the sense that it preserves the desired goal and is "kept simple"), I came up with is:
#!/usr/bin/env python3
from tkinter import *
rcc = 1
def click():
global rcc
rcc += 1
rc.set(rcc)
print('rcc was increased to {}'.format(rcc))
if __name__ == '__main__':
window = Tk()
window.title("my click game boi")
window.configure(background='black')
rc = IntVar()
photo1 = PhotoImage(file="kanekipic.gif")
Label(window, image=photo1, bg='black').grid(row=0, column=0, sticky=E)
Button(window, text="eat", width=3, command=click).grid(row=3, column=0, sticky=W)
Label(window, textvariable=rc, bg="red", fg="white").grid(row=1, column=0, sticky=S)
window.mainloop()
Whenever you click on the eat button, the counter will be increased.

How would I modify/add text to a tkinter.Label?

I am in the process of learning basic Python. I am currently attempting to create a simple calculator program that only has addition and subtraction. I have one issue though. I am not sure how I would add text to my Python label upon button press. Right now, upon pressing the '1' button, my program will change the display label to the text "1". However, I want my program to add text, not set it.
For example, if I press 'button 1' 5 times, it currently will reset the label text 5 times and will result with a single 1. I want it to add the number to the label upon press, not replace.
Current Result after pressing button 5 times: 1
Requested result after pressing button 5 times: 11111
Here is my current code for the program. If anything is unclear, just ask; thanks.
from tkinter import *
window = Tk()
# Creating main label
display = Label(window, text="")
display.grid(row=0, columnspan=3)
def add_one():
display.config(text='1')
# Creating all number buttons
one = Button(window, text="1", height=10, width=10, command=add_one)
two = Button(window, text="2", height=10, width=10)
three = Button(window, text="3", height=10, width=10)
four = Button(window, text="4", height=10, width=10)
five = Button(window, text="5", height=10, width=10)
six = Button(window, text="6", height=10, width=10)
seven = Button(window, text="7", height=10, width=10)
eight = Button(window, text="8", height=10, width=10)
nine = Button(window, text="9", height=10, width=10)
zero = Button(window, text="0", height=10, width=10)
# Placing all number buttons
one.grid(row=1, column=0)
two.grid(row=1, column=1)
three.grid(row=1, column=2)
four.grid(row=2, column=0)
five.grid(row=2, column=1)
six.grid(row=2, column=2)
seven.grid(row=3, column=0)
eight.grid(row=3, column=1)
nine.grid(row=3, column=2)
# Creating all other buttons
add = Button(window, text="+", height=10, width=10)
subtract = Button(window, text="-", height=10, width=10)
equal = Button(window, text="=", height=10, width=10)
# Placing all other buttons
add.grid(row=4, column=0)
subtract.grid(row=4, column=1)
equal.grid(row=4, column=2)
window.mainloop()
You should use a StringVar for this. And your callback needs to get the current contents of the StringVar, modify it, and use the modified string to set the new value of the StringVar. Like this:
import tkinter as tk
window = tk.Tk()
# Creating main label
display_text = tk.StringVar()
display = tk.Label(window, textvariable=display_text)
display.grid(row=0, columnspan=3)
def add_one():
s = display_text.get()
s += '1'
display_text.set(s)
one = tk.Button(window, text="1", height=10, width=10, command=add_one)
one.grid(row=1, column=0)
window.mainloop()
BTW, you should try to make your program a little more compact by using for loops to create and lay out your buttons, in accordance with the DRY principle.
Also, it's not a good idea to use from tkinter import *. It imports over 130 names into your namespace, making it easy to create name collisions if you accidentally use a Tkinter name for one of your own variables or functions.
You can define add_one like the following, to first get the existing value and then append a new value to it:
def add_one():
current_value = display.cget("text")
new_value = current_value + "1"
display.config(text=new_value)
Is this what you're looking for:
from tkinter import *
root = Tk()
var = StringVar()
def f1():
var.set(" ")
var.set("1")
def f2():
var.set(" ")
var.set("2")
label = Label(root, textvariable=var)
label.pack()
button1 = Button(root, text="One", command=f1)
button1.pack()
button2 = Button(root, text="Two", command=f2)
button2.pack()
?

Categories

Resources