import random
from tkinter import *
root = Tk()
FirstPageFrame = Frame(root) # CREATES FIRST PAGE FRAME
FirstPageFrame.pack() # CREATES FIRST PAGE FRAME
RolltheDiceTitle = Label(FirstPageFrame, text="Roll the Dice")
RolltheDiceTitle.config(font=("Courier", 30))
RolltheDiceTitle.grid()
LoginRegisterWelcomeMessage = Label(FirstPageFrame, text="Welcome to the Roll the Dice Game.")
LoginRegisterWelcomeMessage.grid(row=1, padx=10, pady=10)
DiceImage = PhotoImage(file="dice.png")
DiceImageLabel = Label(FirstPageFrame, image=DiceImage)
DiceImageLabel.grid()
registerButton = Button(FirstPageFrame, text="Register", fg="orange") # CREATES REGISTER BUTTON
registerButton.grid(row=4, padx=10, pady=10)
loginButton = Button(FirstPageFrame, text="Login", fg="Green") # CREATES LOGIN BUTTON
loginButton.grid(row=4, column=1, padx=10, pady=10)
root.mainloop() # Continues tkinter window loop so program does not close
I'm trying to have both the register and login buttons in the middle of the window (where register button is located) but side by side, not stacked.
Apologies for any incorrect formatting with this question or any easy fixes with the code. I'm super new to Tkinter and trying to figure stuff out :)
When you put the Login button in column 1 all the other widgets are in column 0, so the Login button will be displayed on the far right.
One solution is to create a contaner frame for the buttons which can be placed in the center of column 0, and then place the buttons in culmns in that frame.
I have stated row and colun explicitly for all widgets which makes it easier to follow, and also assigned a bg color to the buttonFrame so you can see where it goes.
import random
from tkinter import *
root = Tk()
FirstPageFrame = Frame(root) # CREATES FIRST PAGE FRAME
FirstPageFrame.pack() # CREATES FIRST PAGE FRAME
RolltheDiceTitle = Label(FirstPageFrame, text="Roll the Dice")
RolltheDiceTitle.config(font=("Courier", 30))
RolltheDiceTitle.grid(row=0, column=0)
LoginRegisterWelcomeMessage = Label(FirstPageFrame, text="Welcome to the Roll the Dice Game.")
LoginRegisterWelcomeMessage.grid(row=1, column=0, padx=10, pady=10)
DiceImage = PhotoImage(file="dice.png")
DiceImageLabel = Label(FirstPageFrame, image=DiceImage)
DiceImageLabel.grid(row=2, column=0)
# Here is the container frame for the buttons.
buttonFrame = Frame(FirstPageFrame, bg='tan') # bg color to indicate
buttonFrame.grid(row=3) # position and extent of frame
registerButton = Button(buttonFrame, text="Register", fg="orange") # CREATES REGISTER BUTTON
registerButton.grid(row=0, column=0, padx=10, pady=10)
loginButton = Button(buttonFrame, text="Login", fg="Green") # CREATES LOGIN BUTTON
loginButton.grid(row=0, column=1, padx=10, pady=10)
root.mainloop() # Continues tkinter window loop so program does not close
Related
I am new to Python programming. I started learning the language a few weeks ago. I am creating a "Temperature Converter" application using "tkinter". I am trying to add a scroll bar to the application but unable to do so. Please forgive me if I have not written something correctly. Please do let me know my mistake and I will definitely rectify it. I won't repeat the mistake in the future.
Thank you very much for your time. Following is my code:
import tkinter as tk
from tkinter.messagebox import showerror
from tkinter import *
window = tk.Tk()
window.title("Temperature Converter")
window.geometry('420x400')
window.option_add('*Font', '25')
window.option_add('*Font', 'Tahoma')
window.configure(bg='#f8f8f8')
window.resizable(0, 0)
def fahrenheit_to_celsius():
fahrenheit = fahrenheit_to_celsius_entry_temperature.get()
if fahrenheit == '':
showerror(title='Empty Field Error', message="Field is empty. Please input number.")
else:
try:
celsius = (5 / 9) * (float(fahrenheit) - 32)
fahrenheit_to_celsius_label_result["text"] = f"{round(celsius, 2)} \N{DEGREE CELSIUS}"
except:
showerror(title='Input Error', message="Invalid input. Please input only number.")
fahrenheit_to_celsius_label_heading = tk.Label(text="Fahrenheit to Celsius:", bg='#f8f8f8', fg='Black')
# Create the Fahrenheit entry frame with an Entry widget and label in it
fahrenheit_to_celsius_frame_entry = tk.Frame(master=window)
fahrenheit_to_celsius_entry_temperature = tk.Entry(master=fahrenheit_to_celsius_frame_entry, width=10)
fahrenheit_to_celsius_label_temperature = tk.Label(master=fahrenheit_to_celsius_frame_entry, text="\N{DEGREE FAHRENHEIT}")
def fahrenheit_to_celsius_clear():
fahrenheit_to_celsius_entry_temperature.delete(0, tk.END)
fahrenheit_to_celsius_label_result.config(text="\N{DEGREE CELSIUS}")
fahrenheit_to_celsius_button_clear = tk.Button(window, text="Clear", command=fahrenheit_to_celsius_clear, bg='#c82333', fg='White')
fahrenheit_to_celsius_label_heading.grid(row=0, column=0, columnspan=3, sticky="w")
fahrenheit_to_celsius_entry_temperature.grid(row=1, column=0, sticky="ew")
fahrenheit_to_celsius_label_temperature.grid(row=1, column=1, sticky="ew")
fahrenheit_to_celsius_button_clear.grid(row=1, column=2, sticky="w")
fahrenheit_to_celsius_button_convert = tk.Button(master=window, text="Convert", command=fahrenheit_to_celsius, bg='#218838', fg='White')
fahrenheit_to_celsius_label_result = tk.Label(master=window, text="\N{DEGREE CELSIUS}")
fahrenheit_to_celsius_label_heading.grid(row=0, padx=10, pady=10)
fahrenheit_to_celsius_frame_entry.grid(row=1, column=0, padx=12, sticky="ew")
fahrenheit_to_celsius_button_convert.grid(row=1, column=1, padx=0, sticky="ew")
fahrenheit_to_celsius_button_clear.grid(row=1, column=2, padx=(5,0), sticky="ew")
fahrenheit_to_celsius_label_result.grid(row=1, column=3, padx=0, sticky="w")
Adding a scrollbar
Scrollbars can't be added for a tkinter frame, but you can add them for a canvas.
procedure
Put all your widgets in a tkinter canvas
Configure canvas scrollregion
Add a scrollbar for the canvas
Example
base = tk.Canvas(window)
base.pack(fill=tk.BOTH, side=tk.LEFT, expand=True)
# change scrollregion as changes are made to the canvas
base.bind('<Configure>', lambda e: base.configure(scrollregion=base.bbox(tk.ALL)))
# add scrollbar for the canvas
scroll = tk.Scrollbar(window, command=base.yview)
scroll.pack(side=tk.LEFT, fill=tk.Y)
base.config(yscrollcommand=scroll.set)
# sample widgets
for i in range(2, 20):
btn = tk.Button(base, text=f"Button {i}")
base.create_window(200, i*30, window=btn)
For your code, you need to :
Create a scrollable canvas following above instructions
Instead of directly using grid, use canvas.create_window(x, y, window) for each widget
I have created a menu bar on the parent window. And I have made a child window as userguide.py which is assigned to one of the button on the menu that is "USER GUIDE". When I click on the button the child window opens, but when again clicked it opens one more window and so continues if clicked on the menu button. How do I disable the menu button until the child window is closed. I am sharing the code below.
Below this is code of the menu in parent window
from tkinter import *
from tkinter import ttk
from userguide import userGuide
root = Tk()
root.title("GhostTube - by RuSher")
root.iconbitmap(r"C:\Users\ayush\Desktop\BOTRAW\main\ghost.ico")
root.maxsize(400, 685)
root.minsize(400, 685)
root.geometry("400x685")
style = ttk.Style()
style.theme_use("clam")
menubar = Menu(root)
menubar.add_command(label="USER GUIDE I", command=userGuide)
menubar.add_command(label="ABOUT I")
menubar.add_command(label="CONTACT", command=contactInfo)
root.config(menu=menubar)
root.mainloop()`
Menu bar image
Below given code is the child window code i.e. userguide.py
from tkinter import *
from tkinter import ttk
def userGuide():
master = Tk()
master.title("GhostTube - by RuSher")
master.iconbitmap(r"C:\Users\ayush\Desktop\BOTRAW\main\ghost.ico")
master.maxsize(400, 685)
master.minsize(400, 685)
master.geometry("400x685")
style = ttk.Style()
style.theme_use("clam")
userLabel = Label(master, text=" HOW TO USE ", bg="black", fg="white", font=("Elephant", 18))
userLabel.grid(pady=10)
guide1Frame = LabelFrame(master, text="STEP 1 :", padx=5, pady=10)
guide1Frame.grid(row=1, column=0, padx=5)
step1label = Label(guide1Frame, text="First step is to add accounts to the bot, for that click on \n“Load Accounts” then locate the “YT accounts.txt” file and select it.\nIt will load all the accounts in the file.")
step1label.grid()
guide2Frame = LabelFrame(master, text="STEP 2 :", padx=5, pady=10)
guide2Frame.grid(row=2, column=0, padx=5)
step2label = Label(guide2Frame, text="Add the video URL of which you want to boost. Type or copy paste \nyour video URL on (Type Here) space and click on “Add”. \nOr you can make a text file of your video URLs and load it \nby clicking on “Load Video URLs” and selecting the text file.")
step2label.grid()
guide3Frame = LabelFrame(master, text="STEP 3 :", padx=5, pady=10)
guide3Frame.grid(row=3, column=0, padx=5)
step3label = Label(guide3Frame, text="Now you need to select the action you want to have \non the video to be performed, that are: LIKE, DISLIKE, \nSUBSCRIBE, UNSUBSCRIBE or COMMENT. You can select multiple \nactions at a time. After completing this Click on “START” button.")
step3label.grid()
guide4Frame = LabelFrame(master, text="STEP 4 :", padx=5, pady=10)
guide4Frame.grid(row=4, column=0, padx=5)
step4label = Label(guide4Frame, text="For Comments, You can Type or copy paste comments on\n(Type Here) of your choice, one comment at a time then click\non “Add” button and then type next comment of your choice then\nclick on “Add” and repeat if you want more. Or you can make\na text file of comments of your choice (one comment per line)\nand load it by clicking on “Load Comments”and locate your\ncomments text file and select it. Then click on “START”.")
step4label.grid()
guide5Frame = LabelFrame(master, text="STEP 5 :", padx=5, pady=10)
guide5Frame.grid(row=5, column=0, padx=5)
step5label = Label(guide5Frame, text="When the bot runs first time it can take time because of it prepares\nthe system, after the process starts please do not intercept it.\nLet it complete all the actions. The process goes in steps; \nfirst, a CMD interface will open then a Firefox window will start and\nit will complete one action then the Firefox window will close and\nthe same steps will repeat according to the actions to be taken.")
step5label.grid()
quote = Frame(master, padx=5, pady=10)
quote.grid(row=6, columnspan=2)
enjoy = Label(quote, text="Experience The Best", font=("Elephant",16), bg="black", fg="white")
enjoy.grid(padx=5)
master.mainloop()
Please help me out, because I am a fresh starter in this topic.
Try something like this:
import tkinter as tk
def create_window(root):
# Create the new window
top = tk.Toplevel(root)
# Stop the user from interacting with the main window
top.grab_set()
root = tk.Tk()
menubar = tk.Menu(root)
menubar.add_command(label="Create new window", command=lambda: create_window(root))
root.config(menu=menubar)
root.mainloop()
It uses top.grab_set() to stop the user from interacting with the main window. It blocks all events until the user closes the pop up.
I am new with tkinter.
I am trying to make GUI and for the moment I made 3 RadioBoxe and a slider. and this what I got:
The problem that I want the 3 RadioBox to be in the same line and bellow them the slider. Is it possibe?
and I want the slider to go through odd numbers only (1,3,5,7,9 ...)
This is my code so far:
window = Tk()
window.title("Welcome to LikeGeeks app")
panelA = None
menu = Menu(window)
new_item = Menu(menu)
new_item.add_command(label='Open File', command=open_file)
new_item.add_separator()
new_item.add_command(label='Save File')
new_item.add_separator()
new_item.add_command(label='Exit')
menu.add_cascade(label='File', menu=new_item)
window.config(menu=menu)
label_blur = Label(window, text="Blurring")
label_blur.pack(anchor="w", padx=10, pady=10)
blur_rad1 = Radiobutton(window, text='Average', value=0)
blur_rad2 = Radiobutton(window, text='Gaussian', value=1)
blur_rad3 = Radiobutton(window, text='Median', value=2)
blur_rad1.pack(anchor="w", padx=10, pady=0)
blur_rad2.pack(anchor="w", padx=10, pady=0)
blur_rad3.pack(anchor="w", padx=10, pady=0)
blur_slide = Scale(window, from_=1, to=31, length=600,tickinterval=5, orient=HORIZONTAL)
blur_slide.pack(anchor="w", padx=10, pady=10)
window.mainloop()
There are two simple solutions: use grid so that you can specify the row and columns, or continue to use pack, but place the radiobuttons in a separate frame.
Since you're already using pack, it's easiest to use the second method.
Create a frame for the buttons, and use pack to add it to the window where you want it to appear:
button_frame = Frame(window)
button_frame.pack(side="top", fill="x")
Make the buttons children of the frame:
blur_rad1 = Radiobutton(button_frame, ...)
blur_rad2 = Radiobutton(button_frame, ...)
blur_rad3 = Radiobutton(button_frame, ...)
Use pack to lay out the buttons left-to-right:
blur_rad1.pack(side="left", expand=True)
blur_rad2.pack(side="left", expand=True)
blur_rad3.pack(side="left", expand=True)
I am trying to build virtual numpad(with 1,2 and 3) using python and tkinter .
If I press 1 (button1) then account_number_entry should change to 1 and if i press 2 than account_number_entry should change accordingly.
I tried this code but.
import tkinter as tk
win = tk.Tk()
def handle_pin_button(event):
'''Function to add the number of the button clicked to the PIN number entry via its associated variable.'''
# Limit to 4 chars in length
# Set the new pin number on the pin_number_var
def create_login_screen():
accLabel = tk.Label(win, text="Acount Number / Pin")
accLabel.grid(row=1, column=0)
account_number_var = tk.StringVar()
account_number_entry = tk.Entry(win, textvariable=account_number_var)
account_number_entry.grid(row=1, column=1)
account_number_entry.focus_set()
pin_number_var = tk.StringVar()
account_pin_entry = tk.Entry(win, show='*', text='PIN Number', textvariable=pin_number_var)
account_pin_entry.grid(row=1, column=2)
# Buttons 1, 2 and 3 here. Buttons are bound to 'handle_pin_button' function via '<Button-1>' event.
button1 = tk.Button(text="1")
button1.bind('<Button-1>', handle_pin_button)
button1.grid(row=2, column=0, sticky="NESW")
button2 = tk.Button(text="2")
button2.bind('<Button-1>', handle_pin_button)
button2.grid(row=2, column=1, sticky="NESW")
button3 = tk.Button(text="3")
button3.bind('<Button-1>', handle_pin_button)
button3.grid(row=2, column=2, sticky="NESW")
create_login_screen()
tk.mainloop()
You need to create the account_number_var outside the function create_login_screen() or it will be garbage collected when the function exits.
The usual way to bind a button to a function is to use the argument command. When you have a single function which handles callback from many buttons the usual way is to use lambda.
Example below:
import tkinter as tk
win = tk.Tk()
account_number_var = tk.StringVar() # Create outside function
pin_number_var = tk.StringVar()
def handle_pin_button(digit):
account_number_var.set(digit)
def create_login_screen():
accLabel = tk.Label(win, text="Acount Number / Pin")
accLabel.grid(row=1, column=0)
account_number_entry = tk.Entry(win, textvariable=account_number_var)
account_number_entry.grid(row=1, column=1)
account_number_entry.focus_set()
account_pin_entry = tk.Entry(win, show='*', text='PIN Number',
textvariable=pin_number_var)
account_pin_entry.grid(row=1, column=2)
# Buttons 1, 2 and 3 here. Buttons are bound to 'handle_pin_button' function via '<Button-1>' event.
button1 = tk.Button(text="1", command=lambda:handle_pin_button("1"))
button1.grid(row=2, column=0, sticky="NESW")
button2 = tk.Button(text="2", command=lambda:handle_pin_button("2"))
button2.grid(row=2, column=1, sticky="NESW")
button3 = tk.Button(text="3", command=lambda:handle_pin_button("3"))
button3.grid(row=2, column=2, sticky="NESW")
create_login_screen()
win.mainloop()
How to do this with bind() instead of button command:
First you need to keep track of the buttons. Since they are created inside a function you must save a reference in the global scope.
Second you must calculate the button value from the list index and set the account_number_var accordingly.
Then bind the buttons to the callback handler.
import tkinter as tk
win = tk.Tk()
account_number_var = tk.StringVar() # Create outside function
pin_number_var = tk.StringVar()
button_list = [] # Global button reference list
def handle_pin_button(event):
button_number = button_list.index(event.widget) + 1
account_number_var.set(str(button_number))
def create_login_screen():
accLabel = tk.Label(win, text="Acount Number / Pin")
accLabel.grid(row=1, column=0)
account_number_entry = tk.Entry(win, textvariable=account_number_var)
account_number_entry.grid(row=1, column=1)
account_number_entry.focus_set()
account_pin_entry = tk.Entry(win, show='*', text='PIN Number',
textvariable=pin_number_var)
account_pin_entry.grid(row=1, column=2)
# Buttons 1, 2 and 3 here. Buttons are bound to 'handle_pin_button' function via '<Button-1>' event.
button1 = tk.Button(text="1")
button1.grid(row=2, column=0, sticky="NESW")
button1.bind('<Button-1>', handle_pin_button)
button_list.append(button1) # Add button to global list
button2 = tk.Button(text="2")
button2.grid(row=2, column=1, sticky="NESW")
button2.bind('<Button-1>', handle_pin_button)
button_list.append(button2) # Add button to global list
button3 = tk.Button(text="3")
button3.grid(row=2, column=2, sticky="NESW")
button3.bind('<Button-1>', handle_pin_button)
button_list.append(button3) # Add button to global list
create_login_screen()
win.mainloop()
I want to create a GUI in tkinter with two Frames, and have the bottom Frame grayed out until some event happens.
Below is some example code:
from tkinter import *
from tkinter import ttk
def enable():
frame2.state(statespec='enabled') #Causes error
root = Tk()
#Creates top frame
frame1 = ttk.LabelFrame(root, padding=(10,10,10,10))
frame1.grid(column=0, row=0, padx=10, pady=10)
button2 = ttk.Button(frame1, text="This enables bottom frame", command=enable)
button2.pack()
#Creates bottom frame
frame2 = ttk.LabelFrame(root, padding=(10,10,10,10))
frame2.grid(column=0, row=1, padx=10, pady=10)
frame2.state(statespec='disabled') #Causes error
entry = ttk.Entry(frame2)
entry.pack()
button2 = ttk.Button(frame2, text="button")
button2.pack()
root.mainloop()
Is this possible without having to individually gray out all of the frame2's widgets?
I'm using Tkinter 8.5 and Python 3.3.
Not sure how elegant it is, but I found a solution by adding
for child in frame2.winfo_children():
child.configure(state='disable')
which loops through and disables each of frame2's children, and by changing enable() to essentially reverse this with
def enable(childList):
for child in childList:
child.configure(state='enable')
Furthermore, I removed frame2.state(statespec='disabled') as this doesn't do what I need and throws an error besides.
Here's the complete code:
from tkinter import *
from tkinter import ttk
def enable(childList):
for child in childList:
child.configure(state='enable')
root = Tk()
#Creates top frame
frame1 = ttk.LabelFrame(root, padding=(10,10,10,10))
frame1.grid(column=0, row=0, padx=10, pady=10)
button2 = ttk.Button(frame1, text="This enables bottom frame",
command=lambda: enable(frame2.winfo_children()))
button2.pack()
#Creates bottom frame
frame2 = ttk.LabelFrame(root, padding=(10,10,10,10))
frame2.grid(column=0, row=1, padx=10, pady=10)
entry = ttk.Entry(frame2)
entry.pack()
button2 = ttk.Button(frame2, text="button")
button2.pack()
for child in frame2.winfo_children():
child.configure(state='disable')
root.mainloop()
Based on #big Sharpie solution here are 2 generic functions that can disable and enable back a hierarchy of widget (frames "included"). Frame do not support the state setter.
def disableChildren(parent):
for child in parent.winfo_children():
wtype = child.winfo_class()
if wtype not in ('Frame','Labelframe','TFrame','TLabelframe'):
child.configure(state='disable')
else:
disableChildren(child)
def enableChildren(parent):
for child in parent.winfo_children():
wtype = child.winfo_class()
print (wtype)
if wtype not in ('Frame','Labelframe','TFrame','TLabelframe'):
child.configure(state='normal')
else:
enableChildren(child)
I think you can simply hide the whole frame at once.
If used grid
frame2.grid_forget()
If used pack
frame2.pack_forget()
In your case the function would be
def disable():
frame2.pack_forget()
To enable again
def enable():
frame2.pack()
grid_forget() or pack_forget() can be used for almost all tkinter widgets
this is a simple way and reduces the length of your code, I'm sure it works