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)
Related
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)
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 have been working on a program which can generate a matrix of a user-defined size, and can then perform operations on the matrix. The program is divided into a few parts.
First, the user enters the rows and columns, which, when submitted, will open a tkinter window with a matrix of entry boxes.
Each of these entry boxes is a value in a dynamic entries dictionary. The lists gridrows and gridcols are used to give coordinates for the .grid method for arranging the entry boxes.
The issue I am having is assigning a command to get the user input after typing their values into the matrix. I have tried creating a function storevals which will append all matrix entries to the matrixinput list.
When I run this program, I get the the matrix entry window, and after typing in the values into each box of the matrix, I get the same error message from line 50: AttributeError:"NoneType" object has no attribute "get". It appears that the entry boxes have no type, which seems to be lost after the .grid arranging of the windows.
Is there any way to assign the user entries in these windows to a list? Any help would be hugely appreciated.
Thanks!
from matplotlib import pyplot as plt
from tkinter import *
#Take user input for matrix size and store in matrixrows and matrixcols variables as integers.
master = Tk()
master.title("Matrix Size")
Label(master, text = "Rows").grid(row=0)
Label(master, text = "Columns").grid(row=1)
def storevals():
matrixrows.append(int(rows.get()))
matrixcols.append(int(cols.get()))
master.quit()
matrixrows = []
matrixcols = []
rows = Entry(master)
cols = Entry(master)
rows.grid(row = 0, column = 1)
cols.grid(row =1, column = 1)
Button(master, text= "Enter", command = storevals).grid(row=3, column =0, sticky=W, pady=4)
mainloop()
norows = matrixrows[0]
nocols = matrixcols[0]
matrixlist =[]
for i in range(0,norows):
matrixlist.append([])
for i in range(0,norows):
for j in range(0,nocols):
matrixlist[i].append(nocols*0)
#Generate a matrix entry window with entries correpsonding to the matrix
master2 = Tk()
master2.title("Enter Matrix Values")
matrixinput=[]
def storevals():
for key in entries:
matrixinput.append(entries[key].get())
print(matrixinput)
Button(master2, text= "Submit Matrix", command = storevals).grid(row=norows+1, column =round(nocols/2), sticky=W, pady=4)
gridrows=[]
gridcols=[]
#creates two lists, gridcols and gridrows which are used to align the entry boxes in the tkinter window
for i in range(0,norows):
for j in range(0,nocols):
gridrows.append(i)
for i in range(0,norows):
for j in range(0,nocols):
gridcols.append(j)
entries ={}
for x in range(0,nocols*norows):
entries["Entrybox{0}".format(x)]=Entry(master2).grid(row=gridrows[x], column=gridcols[x])
print(entries)
mainloop()
You probably haven't looked at the content of entries, that you print just before mainloop()
entries ={}
for x in range(0,nocols*norows):
entries["Entrybox{0}".format(x)]=Entry(master2).grid(row=gridrows[x], column=gridcols[x])
print(entries)
grid(), pack() and place() all return None.
If you want to keep the widget you need to assign it to a variable and then call grid().
entries ={}
for x in range(0,nocols*norows):
widget = Entry(master2)
widget.grid(row=gridrows[x], column=gridcols[x])
entries["Entrybox{0}".format(x)] = widget
print(entries)
Hy All,
I'm creating a layout for a database, and made a big canvas which are the lines, spawning smaller canvas inside them (as cells) to contain labels for the data. It looks nice, but the problem is, that due to this "mass-creation" of canvas and label widgets, none of them stays uniqly addressable, they are all named after the same variable when created in a for loop. Any idea how to tag/address them during the creation so I can edit them later?
for f in range(15)
z = z+1
f = Label(someFrame, width = 45 if z < 4 else 12, text = f, borderwidth=2, relief="groove", bg = "#E5E5E5" if Color == True else "#B2B2B2" )
f.pack(side = LEFT)
It may look a bit messy, but you have a picture at least how the widgets are being created and what is my issue.
You can store your widgets in a dictionary. Something like this:
widget_dict = {}
for idx in range(10):
widget_dict['abc' + str(idx)] = label(root, ...)
Then you can access each widget through its dictionary key:
widget_dict[abc2].config(text='Banana')
Before your for loop create a list. Then inside of the for loop just append every label to the list. Or you can use a dictionary to store them, depending on how you want to deal with that.
I want to create something like this image, so each time I click the radio button, the column above it is colored blue.
I need guidance on how to get started using tkinter on python
This is my code so far:
from Tkinter import *
the_window = Tk()
def color_change():
L1.configure(bg = "red")
v =IntVar()
R1 = Radiobutton(the_window, text="First", variable=v, value=1, command = color_change).pack()
R2 = Radiobutton(the_window, text="Second", variable=v, value=2, command = color_change).pack()
R2 = Radiobutton(the_window, text="Third", variable=v, value=3, command = color_change).pack()
L1 = Label(the_window,width = 10, height =1, relief = "groove", bg = "light grey")
L1.grid(row = 2, column = 2)
L1.pack()
L2 = Label(the_window,width = 10, height =1, relief = "groove", bg = "light grey")
L2.grid(row = 2, column = 2)
L2.pack() # going to make 10 more rectangles
the_window.mainloop()
I'm just getting started and I don't know what I'm doing.
Programming is more than just throwing code around until something works, you need to stop and think about how you are going to structure your data so that your program will be easy to write and easy to read.
In your case you need to link one button to a list of widgets which need to change when that button is selected. One way to accomplish this is by having a dictionary with keys that represent the button values, and values that are a list of the labels associated with that radiobutton. Note that this isn't the only solution, it's just one of the simpler, more obvious solutions.
For example, after creating all your widgets you could end up a dictionary that looks like this:
labels = {
1: [L1, L2, L3],
2: [l4, l5, l6],
...
}
With that, you can get the value of the radiobutton (eg: radioVar.get()), and then use that to get the list of labels that need to be changed:
choice = radioVar.get()
for label in labels[choice]:
label.configure(...)
You can create every widget individually, or you could pretty easily create them all in a loop. How you create them is up to you, but the point is, you can use a data structure such as a dictionary to create mappings between radiobuttons and the labels for each radiobutton.