I want to have a calculator with 4 buttons and 2 entry. What is my problem? I don't know how to fix that it can't multiply sequence by non-int of type str nor can't multiply entry * entry.
Also I don't know where is my output and how use that.
from tkinter import ttk
from tkinter import *
import tkinter as tk
#the environment
calc=tk.Tk()
calc.title("Calculator")
#-------------------------------------
#lables and their data entry
tk.Label(calc,text="enter your first number:").grid(row=0)
tk.Label(calc,text="enter your second number:").grid(row=1)
e1=tk.Entry(calc)
e2=tk.Entry(calc)
e1.grid(row=0, column=1)
e2.grid(row=1, column=1)
x1=e1.get()
x2=e2.get()
tk.Label(calc,text="your result is:").grid(row=3)
# a free variable for get output,is this really need?
lbl=list()
#---------------------------
#the functions but my entry are entry type
def prod():
lbl=print(x1*x2)
def div():
lbl=print(x1/x2)
def sum():
lbl=print(x1+x2)
def min():
lbl=print(x1-x2)
#-------------------------------
#buttons and function in them as a command
btn1=tk.Button(calc,text="*",command=prod()).grid(row=0,column=2)
btn2=tk.Button(calc,text="/",command=div()).grid(row=1,column=2)
btn3=tk.Button(calc,text="+",command=sum()).grid(row=2,column=2)
btn4=tk.Button(calc,text="-",command=min()).grid(row=3,column=2)
#--------------------------------------------------------------------
#The answer which i need it
print("your answer is:")
calc.mainloop()
In GUI programming, you need to get the value of widgets at the time you need them, not at the time you create them.
Also, widgets return string values. If you are doing math on them, you need to convert them to numbers first.
If you want to display the result in the window, you can update a label widget with the configure method
For example, your prod definition could look something like this:
def prod():
x1 = int(e1.get())
x2 = int(e2.get())
result = x1 * x2
result_label.configure(text=str(result))
You then need to do two other things. First, you need to create the label for the result, and store the widget in a variable. To do that you must separate the creation of the widget from the layout since calling grid would cause the variable to be set to None
result_label = tk.Label(calc,text="your result is:")
result_label.grid(row=3)
Finally, your buttons need to be given a reference to the function. What you're currently doing is calling the function and assigning the result to the command attribute.
Your button should look like the following. Notice that prod does not have () after it:
btn1 = tk.Button(calc, text="*", command=prod)
...
btn1.grid(row=0,column=2)
On a side note, I think that for all widgets with a common parent, grouping all widget creation code together and then all calls to grid or pack together makes the code easier to read, easier to maintain, and easier to visualize.
For example:
btn1 = tk.Button(...)
btn2 = tk.Button(...)
btn3 = tk.Button(...)
btn4 = tk.Button(...)
btn1.grid(row=0,column=2)
btn2.grid(row=1,column=2)
btn3.grid(row=2,column=2)
btn4.grid(row=3,column=2)
Related
I am learning python. I am not new to programming, so this is frustrating and a little embarrassing too: I I want to check if the random number is 20 - and if it is, change the background color. If I change comparison to != it works. But I cannot seem to check for a value. I tried making the result a string/int as random generates a float. Any ideas..?
The code follows:
import random
import tkinter as tk
temp_result = 0
pickedColor = ""
def d20roll():
temp_result = random.randint(1, 20) # generates a float
lbl_result["text"] = str(temp_result) # makes the float a string for display
print(temp_result) #shows me the result
if temp_result == 20:# if the rnd is 20, make the color red.
pickedColor = "red"
else:
pickedColor = "black"
window = tk.Tk()
window.columnconfigure(0, minsize=150)
window.rowconfigure([0, 1], minsize=50)
frame = tk.Frame(
master=window,
relief=tk.RAISED,
borderwidth=2)
frame.grid(row=0, column=0, padx=2,pady=2)
btn_d20roll = tk.Button(master=frame, text="D20 Roll", command=d20roll)
lbl_result = tk.Label(fg="white", bg=pickedColor)
btn_d20roll.grid(row=0, column=0, sticky="nsew")
lbl_result.grid(row=1, column=0)
window.mainloop() '''
You're setting the value of temp_result inside a function, and testing that value outside of that function. Without diving too far in your code, I see 2 problems with that:
At the moment you test the value of temp_result, the function has not been called yet. The value of temp_result is therefore still the initial value.
When you assign to a variable inside of a function, Python considers that variable local to the function and no change will be visible outside of the function. You could change that by using global temp_result in the function, but it's generally not recommended to communicate values from inside a function to outside of it. It's better to return a value instead.
You're going to have to arrange your code so that a button press will result in:
a random number being generated
that random number being compared to some value
and the background color being set to some value based on that
I'm not familiar with Tkinter so I can't really help with that.
It seems that I explained my problem very terribly, but I have a problem with the grid function on my label. The label does show up but, I cant change the row/column of it or do any function inside of the brackets.
I put the code of how to replicate the problem there. Putting anything inside of the .grid() brackets does nothing as stated earlier
from tkinter import *
root = Tk()
#To actually see that it does not work
root.geometry("800x600")
Var = StringVar()
Label = Label(root, textvariable=Var)
#Location of problem, adding stuff into the brackets does not change anything. For example: sticky = "ne"
Label.grid()
Var.set("Ha")
root.mainloop()
To get the label to show up on the right side, you can specify the number of columns in the grid and then place the label in the last column. For example, try adding this just after your "#Location of problem" comment:
cols = 0
while cols < 4:
root.columnconfigure(cols, weight=1)
cols += 1
Label.grid(column=3)
I'm making a program with Tkinter where I'd need to use a "for i in range" loop, in order to create 81 Text Widgets named like :
Text1
Text2
Text3
...
and dispose them in a square (actually to make a grill for a sudoku game of a 9*9 size). After I created these 81 Text Widgets I need to place them (using .place() ) and entering their position parameters.
After this, I will need to collect the values that the user entered in these Text Widgets.
I'm a newbie and I don't really know how to code this.
Here is my actual code but the problem is I can't modify the parameters once the dictionnary is created and i don't know how to access to the Text Widgets parameters. Maybe using a dictionnary is not the appropriate solution to do what I want.
d = {}
Ypos = 100
for i in range(9):
Xpos = 100
for j in range(9):
d["Text{0}".format(i)]= Text(window, height=1, width=1,relief = FLAT,font=("Calibri",16))
d["Text{0}".format(i)].place(x = Xpos+,y = Ypos)
Xpos += 35
yPos += 35
Thanks for helping
Don't use a complex key for the dictionary, it makes the code more complex without adding any benefit.
Since you're creating a grid, use row and column rather than i and j. This will make your code easier to understand. Also, don't use place if you're creating a grid. Tkinter has a geometry manager specifically for creating a grid.
Since you're creating a text widget with a height of one line, it makes more sense to use an entry widget.
Here's an example:
import Tkinter as tk
root = tk.Tk()
d = {}
window = tk.Frame(root, borderwidth=2, relief="groove")
window.pack(fill="both", expand=True)
for row in range(9):
for column in range(9):
entry = tk.Entry(window, width=1, relief="flat", font=("Calibri",16))
entry.grid(row=row, column=column, sticky="nsew")
d[(row,column)] = entry
root.mainloop()
Whenever you need to access the data in a cell, you can use the row and column easily:
value = d[(3,4)].get()
print("row 3, column 4 = %s" % value)
I wrote my first py code. This code to create a lotto number generator.The problem is that my variable nums will not change. Please help me.
I understand this is not as good as it can be so please tell me how to improve, any comments will be appreciated.I wanted the random numbers to come up in the ladle so i could press the submit button and 5 new numbers to come up.The problem is my veritable "nums" wont change.Thank you for helping.
import random
from tkinter import *
#TK()
window = Tk()
window.title("Lottery Nummber Generator")
#Def Click
def click():
global nums
global numsgen
numsgen = random.sample(range(1, 49), 5)
nums = " ".join(str(x) for x in numsgen)
print(nums)
numsgen = random.sample(range(1, 49), 5)
nums = " ".join(str(x) for x in numsgen)
#Fake just to make it look nice
Label(window,text="").grid(row=1, column=0,sticky=W)
Label(window,text="").grid(row=2, column=1,sticky=W)
Label(window,text="").grid(row=2, column=3,sticky=W)
#Submit button
Button(window, text="Submit", width=5,command=click).grid(row=3, column=1, sticky=W)
#Label
group = LabelFrame(window, text="Lottery Numbers:", padx=5, pady=5,fg="dark orange")
group.pack(padx=10, pady=10,)
group.grid(row=2, column=1,sticky=W)
w = Label(group, text=nums)
w.pack()
mainloop()
To get a label to update, you must do one of two things:
Associate a StringVar with the label. When you update the variable (via its set method), any labels associated with it will automatically change. This is a great solution if more than one widget needs to display the same value.
Directly configure the label. This requires that you save a reference to the widget(s) so that you can later reconfigure them. For example, you could put w.configure(text=nums) in your click function. This solution is a bit simpler than using a StringVar, simply because it requires one less object.
Using the tkinter module, suppose I create a grid with 50 button widgets and each of those widgets has different text. I need to be able to specify some way of typing in a row and column so I can get that widget's text at that location.
For example, if I need the widget's text at the third row in the second column of the grid. I've searched the docs but that tells me how to get info about widgets, when I need info about the grid.
There's no need to create your own function or keep a list/dictionary, tkinter already has a built-in grid_slaves() method.
It can be used as frame.grid_slaves(row=some_row, column=some_column)
Here's an example with a grid of buttons showing how grid_slaves() retrieves the widget, as well as displaying the text.
import tkinter as tk
root = tk.Tk()
# Show grid_slaves() in action
def printOnClick(r, c):
widget = root.grid_slaves(row=r, column=c)[0]
print(widget, widget['text'])
# Make some array of buttons
for r in range(5):
for c in range(5):
btn = tk.Button(root, text='{} {}'.format(r, c),
command=lambda r=r, c=c: printOnClick(r, c))
btn.grid(row=r, column=c)
tk.mainloop()
You got a previous answer relative to a method to save button objects in a dictionary in order to recover them using their (column, row) position in a grid.
So if self.mybuttons is your dictionary of lists of buttons as described in previous answer, then you can get the text at position row, col as this:
abutton = self.mybuttons[arow][acolumn]
text_at_row_col = abutton["text"]
On the other hand, if what you need is to get the text from the button callback:
button.bind("<Button-1>", self.callback)
then you can get the button text from the event, you do not need to know its row/col position, only to press it:
def callback(self, event):
mybutton = event.widget
text_at_row_col = mybutton["text"]