My Variable will not change out side the definition - python

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.

Related

In Python3.8, Cannot get a variable to be checked in an if statement

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.

A calculator using tkinter library

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)

Certain label wont work with .grid() function from tkinter

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)

Python tkinter create buttons with loop and edit their parameters

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)

Why can't the contents in these three entries change simultaneously?

Firstly let's look at this program:
def entry_simutaneously_change():
from Tkinter import *
root=Tk()
text_in_entry.set(0)
Entry(root, width=30, textvariable= text_in_entry).pack()
Entry(root, width=30, textvariable= text_in_entry).pack()
Entry(root, width=30, textvariable= text_in_entry).pack()
root.mainloop()
The contents in these three entries can change simultaneously. If I change the value of any of them, the other two would change at the same time. However, for the following program:
def entry_simutaneously_change():
from Tkinter import *
root=Tk()
text_in_entry_list=[IntVar() for i in range(0,3)]
text_in_entry_list[0].set(0)
text_in_entry_list[1].set(text_in_entry_list[0].get() ** 2)
text_in_entry_list[2].set(text_in_entry_list[0].get() ** 3)
Entry(root, width=30, textvariable= text_in_entry_list[0]).pack()
Entry(root, width=30, textvariable= text_in_entry_list[1]).pack()
Entry(root, width=30, textvariable= text_in_entry_list[2]).pack()
root.mainloop()
When I change the content in the first entry, the contents in the other two do not change. Why?
In the first program, you have one source of data, text_in_entry. You could consider it as one box where you're placing a single value that's read by each Entry.
In the second program, you have three sources of data, text_in_entry[0, 1, and 2]. The lines that set the initial value are called only once. It's like you have three boxes where data is placed; to set the initial values, you do look at the value inside the first, but there is no association between the three.
If you would like to achieve the same type of result as with the first program (when the three entries update simultaneously) then you will need to bind on an event. I note that Tkinker does not have an on-change style event but there are various hacks, however you could bind to the FocusOut event. The general idea is to ask for a function to be called when a change occurs to an entry (binding a callback). Inside that function you update the other two values based on the new value in the entry that was changed.

Categories

Resources