This is my first venture into tkinter programming, so far I have the following code that increases or decreases a number by pressing either button. As you may notice I have started adding an update definition that I'd like to update a results table with the label value each time a button is pressed. I've recently found the lambda expression to add two commands to each button press but can't find an example to build the list:
import tkinter as tk
window = tk.Tk()
def increase():
value = int(lbl_value["text"])
lbl_value["text"] = f"{value + 1}"
def decrease():
value = int(lbl_value["text"])
lbl_value["text"] = f"{value - 1}"
def update():
result_table = []
window.rowconfigure(0, minsize = 100, weight = 1)
window.columnconfigure([0,1,2], minsize = 100, weight = 1)
btn_decrease = tk.Button(master = window, text = "-", command = lambda:[decrease(), update()], bg = 'red', fg = 'white')
btn_decrease.grid(row = 0, column = 0, sticky = "nsew")
lbl_value = tk.Label(master = window, text = "0")
lbl_value.grid(row = 0, column = 1)
btn_increase = tk.Button(master = window, text = "+", command = lambda:[increase(), update()], bg = 'green', fg = 'white')
btn_increase.grid(row = 0, column = 2, sticky = "nsew")
window.mainloop()
, bg = 'black', fg = 'white')
btn_decrease.grid(row = 0, column = 0, sticky = "nsew")
lbl_value = tk.Label(master = window, text = "0")
lbl_value.grid(row = 0, column = 1)
btn_increase = tk.Button(master = window, text = "+", command = increase, bg = 'red', fg = 'white')
btn_increase.grid(row = 0, column = 2, sticky = "nsew")
window.mainloop()
I'd like to add a graph of the count to the display ultimately. Any help greatly appreciated.
Matt
I have written the following code to get the user input. But I am not able to add a scrollbar to it. I want to place a vertical scrollbar because I am not able to view all the input labels on my screen.
I first tried:
v = Scrollbar(root, orient='vertical')
v.config(command=root.yview)
It gave me the following error:
File "/Users/aaditya/Desktop/Blender_software/Blender_algo_exp/testing.py", line 235, in <module>
label1.grid(row = 1, column = 0, padx = 10, pady = 10)
File "/opt/anaconda3/envs/blender_env/lib/python3.9/tkinter/__init__.py", line 2486, in grid_configure
self.tk.call(
_tkinter.TclError: cannot use geometry manager grid inside . which already has slaves managed by pack
After that I tried the following:
myscroll = Scrollbar(root)
myscroll.pack(side = RIGHT, fill = Y)
Which resulted in the following error:
AttributeError: '_tkinter.tkapp' object has no attribute 'yview'
How can I fix this?
This is my entire code:
# Driver code
if __name__ == "__main__" :
root = Tk()
# v = Scrollbar(root, orient='vertical')
# v.config(command=root.yview)
# myscroll = Scrollbar(root)
# myscroll.pack(side = RIGHT, fill = Y)
root.configure(background = 'light gray')
root.geometry("700x700")
root.title("Blender Software")
label1 = Label(root, text = "Total Quantity: ",
fg = 'black', bg = 'white')
label2 = Label(root, text = "Percentage of Solid Scrap : ",
fg = 'black', bg = 'white')
label3 = Label(root, text = "Cr min : ",
fg = 'black', bg = 'white')
label4 = Label(root, text = "Cr max : ",
fg = 'black', bg = 'white')
label1.grid(row = 1, column = 0, padx = 10, pady = 10)
label2.grid(row = 2, column = 0, padx = 10, pady = 10)
label3.grid(row = 3, column = 0, padx = 10, pady = 10)
label4.grid(row = 4, column = 0, padx = 10, pady = 10)
# Create a entry box
# for filling or typing the information.
total_quantity = Entry(root)
per_solid_scrap = Entry(root)
Cr_min_input = Entry(root)
Cr_max_input = Entry(root)
# grid method is used for placing
# the widgets at respective positions
# in table like structure .
total_quantity.grid(row = 1, column = 1, padx = 10, pady = 10)
per_solid_scrap.grid(row = 2, column = 1, padx = 10, pady = 10)
Cr_min_input.grid(row = 3, column = 1, padx = 10, pady = 10)
Cr_max_input.grid(row = 4, column = 1, padx = 10, pady = 10)
button1 = Button(root, text = "Submit", bg = "red",
fg = "black", command = calculate_op)
button1.grid(row = 21, column = 1, pady = 10)
# Start the GUI
root.mainloop()
Pack and grid cannot be used at the same time. So since you called the pack for the scrollbar, you cannot manage the following widgets by grid anymore. An easy fix is to place the scrollbar with grid function instead. Apart from that, try using a function or class to make your code less lengthy because now it seems hard to read and purposeless.
Original Code:
import tkinter as tk
from tkinter import ttk
win = tk.Tk()
home_frame = tk.Frame(win)
home_frame.grid(column = 0, row = 0)
home_frame.config(bg = 'blue', relief = 'raised')
logo = tk.Label(home_frame)
logo.grid(column = 0, row = 0)
logo.config(text = 'Widget', font = ('Helvetica', 30), fg = 'red')
win.config(bg ='white')
win.mainloop()
Note that:
home_frame.config(bg = 'blue', relief = 'raised')
From this, I would expect the background of the frame to turn blue, yet it doesn't. It remains grey.
Output:
As far as I'm concerned, tk.Frame() does have bg as an option.
Explanation:
If we do the following changes to logo background, we get the following:
Code:
logo.config(text = 'Widget', font = ('Helvetica', 30), bg = 'green', fg = 'red')
Also, adding another widget, like an entry widget, to home_frame will yield this:
Code:
search = tk.Entry(home_frame)
search.grid(column = 1, row = 0)
From the above, we can tell logo covers home_frame background.
Question:
How would you make logo background not cover home_frame background when logo background is not defined?
By this I mean:
logo.config(text = 'Widget', font = ('Helvetica', 30), fg = 'red') #No background option included.
In this case, I set logo background to blue. I want no bg option included in logo.config(). But still display an output as above.
I am attempting to create a relatively simple survey like form in Tkinter, and I'm relatively new to the GUI framework. I'm having real issues trying to figure out why there are so many inconsistencies, especially when working with grid placement+frames+multiple widgets in same row. Especially this specific example. I'm tying together all my questions into a single frame, and it seems to work out... sort of half. Though the rows seem to cooperate nicely, the columns are where the whole thing gets erupted.
qframe1 = Frame(question, bg='black')
qframe1.grid(row=1, padx = 20, sticky = W)
q1l = Label(qframe1, text = 'Question 1: How often do you eat at Mcdonalds?', font = ('Calibri', 14), bg = 'azure')
q1l.grid(columnspan = 4, pady = 5, sticky = W)
q1 = StringVar()
q1.set('None')
q1r1 = Radiobutton(qframe1, text = 'Everyday!', font = ('Calibri', 12), bg = 'azure', variable = q1, value = 'Always')
q1r1.grid(row=1, column = 0, pady = 5, sticky = W)
q1r2 = Radiobutton(qframe1, text = 'Sometimes', font = ('Calibri', 12), bg = 'azure', variable = q1, value = 'Sometimes')
q1r2.grid(row=1, column = 1, pady = 5, sticky = W)
q1r3 = Radiobutton(qframe1, text = 'Not Frequently', font = ('Calibri', 12), bg = 'azure', variable = q1, value = 'Infrequent')
q1r3.grid(row=1, column = 2, pady = 5, sticky = W)
q1r4 = Radiobutton(qframe1, text = 'Never', font = ('Calibri', 12), bg = 'azure', variable = q1, value = 'Never')
q1r4.grid(row=1, column = 3, pady = 5, sticky = W)
This is the bare code for the section that's messing up.
Also, I have made sure that it's not the length of each radio button that is causing the issue. When I change the text of the radio buttons, they still get placed in the same irregular positions.
Here's the code for another section of the trivia.
q2l = Label(qframe1, text = 'Question 2: What meal do you normally order?', font = ('Calibri', 14), bg = 'azure')
q2l.grid(row=2, columnspan = 4, pady = 5, sticky = W)
q2 = StringVar()
q2.set('None')
q2r1 = Radiobutton(qframe1, text = 'Fries', font = ('Calibri', 12), bg = 'azure', variable = q2, value = 'Fries')
q2r1.grid(row=3, column = 0, pady = 5, sticky = W)
q2r2 = Radiobutton(qframe1, text = 'Hamburgers', font = ('Calibri', 12), bg = 'azure', variable = q2, value = 'Hamburgers')
q2r2.grid(row=3, column = 1, pady = 5, sticky = W)
q2r3 = Radiobutton(qframe1, text = 'Chicken Nuggets', font = ('Calibri', 12), bg = 'azure', variable = q2, value = 'Chicken Nuggets')
q2r3.grid(row=3, column = 2, pady = 5, sticky = W)
q2r4 = Radiobutton(qframe1, text = 'Coffee', font = ('Calibri', 12), bg = 'azure', variable = q2, value = 'Coffee')
q2r4.grid(row=3, column = 3, pady = 5, sticky = W)
This again causes an irregular spacing. But this time, the spacing is completely different from the radio buttons in question 1. And rinse and repeat with every new question set of radio buttons.
There are no issues with the buttons on the right side. Perhaps it's because they're aligned in rows and not columns which are causing the spacing issue.
bframe = Frame(question, bg='black')
bframe.grid(row=1, padx = 20, sticky = E)
audioq1 = Button(bframe, text = ' Listen to Audio', font = ('Calibri', 14), bg = 'brown1', fg = 'azure', image = sound, relief = SUNKEN, compound = LEFT, command = q1audio)
audioq1.grid(ipadx = 5, pady = 20)
audioq2 = Button(bframe, text = ' Listen to Audio', font = ('Calibri', 14), bg = 'brown1', fg = 'azure', image = sound, relief = SUNKEN, compound = LEFT, command = q2audio)
audioq2.grid(row = 1, ipadx = 5, pady = 20)
audioq3 = Button(bframe, text = ' Listen to Audio', font = ('Calibri', 14), bg = 'brown1', fg = 'azure', image = sound, relief = SUNKEN, compound = LEFT, command = q3audio)
audioq3.grid(row = 2, ipadx = 5, pady = 20)
audioq4 = Button(bframe, text = ' Listen to Audio', font = ('Calibri', 14), bg = 'brown1', fg = 'azure', image = sound, relief = SUNKEN, compound = LEFT, command = q4audio)
audioq4.grid(row = 3, ipadx = 5, pady = 20)
audioq5 = Button(bframe, text = ' Listen to Audio', font = ('Calibri', 14), bg = 'brown1', fg = 'azure', image = sound, relief = SUNKEN, compound = LEFT, command = q5audio)
audioq5.grid(row = 4, ipadx = 5, pady = 20)
Any help would be greatly appreciated!
If, as mentioned in the comments, "weight isn't necessarily the problem", the placement of the radiobuttons can be realized using pack instead of grid.
This gives something like this (on a mac):
If you want a more evenly placed buttons to fill the available width, you can achieve this with grid:
I also rewrote a portion of the code to make it easier to add questions to the form. Each question is now in its own frame, allowing for more flexibility.
import tkinter as tk
class QFrame(tk.Frame):
id = 1
def __init__(self, master, question):
self.master = master
super().__init__(self.master)
self.id = QFrame.id
QFrame.id += 1
self.q = tk.StringVar()
self.q.set('None')
self.question, self.choices = question
self.q_label = tk.Label(self, text=f'Question {self.id}: {self.question}')
self.q_label.pack(expand=True, anchor=tk.W)
self.choose = []
for idx, choice in enumerate(self.choices):
txt, value = choice
qr = tk.Radiobutton(self, text=txt, variable=self.q, value=value)
self.choose.append(qr)
qr.pack(side=tk.LEFT)
class App(tk.Tk):
def __init__(self, questions):
self.questions = questions
super().__init__()
for question in questions:
self.qframe = QFrame(self, question)
self.qframe.pack(fill=tk.X)
q1 = ['How often do you eat at Mcdonalds?',
(('Everyday!', 'Always'),
('Sometimes', 'Sometimes'),
('Not Frequently', 'Infrequent'),
('Never', 'Never'))]
q2 = ['What meal do you normally order?',
(('Fries!', 'Fries'),
('Hamburgers', 'Hamburgers'),
('Chicken Nuggets', 'Chicken Nuggets'),
('Coffee', 'Coffee'))]
q3 = ['how large is your usual party?',
(('alone!', 'alone'),
('two', 'two'),
('less than 5', 'less than 5'),
('5 or more', '5 or more'))]
questions = [q1, q2, q3]
app = App(questions)
app.mainloop()
The code for grid geometry manager:
class QFrame(tk.Frame):
id = 1
def __init__(self, master, question):
self.master = master
super().__init__(self.master)
self.id = QFrame.id
QFrame.id += 1
self.q = tk.StringVar()
self.q.set('None')
self.question, self.choices = question
self.grid_rowconfigure(0, weight=1)
for idx in range(4):
self.grid_columnconfigure(idx, weight=1)
self.q_label = tk.Label(self, text=f'Question {self.id}: {self.question}')
self.q_label.grid(row=0, column=0, columnspan=4, sticky="w")
self.choose = []
for idx, choice in enumerate(self.choices):
txt, value = choice
qr = tk.Radiobutton(self, text=txt, variable=self.q, value=value)
self.choose.append(qr)
qr.grid(row=1, column=idx, columnspan=1, sticky="ew")
This question already has answers here:
Why is my Button's command executed immediately when I create the Button, and not when I click it? [duplicate]
(5 answers)
Closed 4 years ago.
I am trying to create a counter for Jeopardy so that my Mom and I can keep score. Currently the program that I am creating is assigning the values to variables and then not performing the command when I press the button in the window. I am running Python 2.7.13.`
import Tkinter as tk
root = tk.Tk()
root.title("Jeopardy Scores")
def ChangeScore(User,Value):
if User == 1:
Score = int(JScore.get())
JScore.set(Score + Value)
#J = JScore.get()
#print J
#SayHi()
else:
Score = int(MScore.get())
MScore.set(Score + Value)
#M = MScore.get()
#print M
#SayHi()
#def SayHi(*args):
#print 'hi'
MainFrame = tk.Frame(root)
MainFrame.grid(column=0, row=0)
MainFrame.columnconfigure(0, weight=1)
MainFrame.rowconfigure(0, weight=1)
JScore = tk.StringVar()
MScore = tk.StringVar()
JScore.set(0)
MScore.set(0)
JL = tk.Label(MainFrame, text = "Joey's Score", padx = 10, pady = 2)
JL.config(bg = 'blue', fg = 'yellow', font = ('Arial',30, 'bold'))
JL.grid(column = 0, row = 0)
ML = tk.Label(MainFrame, text = "Mom's Score", padx = 10, pady = 2)
ML.config(bg = 'blue', fg = 'yellow', font = ('Arial',30, 'bold'))
ML.grid(column = 1, row = 0)
JSS = tk.Label(MainFrame, textvariable=JScore ,padx = 122)
JSS.config(bg = 'blue', fg = 'yellow', font = ('Arial',30, 'bold'))
JSS.grid(column = 0, row = 1)
MSS = tk.Label(MainFrame, textvariable = MScore,padx = 122)
MSS.config(bg = 'blue', fg = 'yellow', font = ('Arial',30, 'bold'))
MSS.grid(column = 1, row = 1)
for i in range(1,6):
Score = tk.IntVar()
Score.set(i*200)
Score1 = 200*i
JButton = tk.Button(MainFrame, textvariable = Score, command =
ChangeScore(1,Score1))
JButton.grid(column = 0, row = 1+i)
MButton = tk.Button(MainFrame, textvariable = Score, command =
ChangeScore(2,Score1))
MButton.grid(column = 1, row = 1+i)
JButton = tk.Button(MainFrame, text = '400', command = ChangeScore(1,400))
JButton.grid(column = 0, row = 7)
root.mainloop()
The code runs and produces this Window
Note that no buttons have been pressed when the picture was taken. It appears that all the buttons are 'being pressed' when the code runs and then nothing happens when i press the buttons afterwards.
I have no experience with Tkinter beyond the small information that has allowed me to do this and I have a bit more experience with Python. I am mainly doing this as an excerise for myself to improve my coding and to acutally use for Jeopardy!. Any help would be appreciate
Here the command parameter for Button should be a callable. You should not call the function yourself and pass the return value to it. Instead, you provide a function that is to be called later.
So change you code to things like
command=lambda: ChangeScore(1, 400)
to create a lambda to be called later will solve the problem.