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

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)

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)

List of tkinter widget using a loop doesn't show up

Please allow me to explain the problem I am facing. I am a undergraduate student who started learning Python a couple of month ago. So, I am new and please bear with me if the experts found them rather naive.
The intention was very simple. I want to place 5 menu buttons in parallel (say in one row, well, this is not the pressing issue though) in a tkinter parent frame. What I did was to introduce 5 sub-frames and place the menu button on them one by one. The idea to use sub-frame was to make space for centering and better layout. Using the most straight-forward fashion, I did it one by one: Define a sub-frame and place a menu button. It all worked well.
Now I am trying to avoid the repeated codes and to lay out the menu buttons and sub-frames using for loops, since the sub-frames and buttons are technically identical except the gird locations and labels are different. I came up with the following code.
Python compiler didn't report any errors. But, only the last button ("Other") was displayed while other buttons are missing. I am having difficulty sorting out what exactly went wrong.
indBtnFrame = [tkinter.Frame(self.parent)] * 5
for i in range(len(indBtnFrame)):
column_index = (i+1)*2
indBtnFrame[i].grid(column=column_index,
row=0,
columnspan=2,
rowspan=1,
sticky="WENS")
for r in range(1): # 1 row in total.
indBtnFrame[i].rowconfigure(r, weight=1)
for c in range(1): # 1 column in total.
indBtnFrame[i].columnconfigure(c, weight=1)
# To fix the grid size.
indBtnFrame[i].grid_propagate(False)
indBtnLabel = ["Street",
"City",
"Postcode",
"Province",
"Other"]
indBtn = []
for i in range(len(indBtnLabel)):
button_label = tkinter.StringVar()
button_label.set(str(indBtnLabel[i]))
temp_widget = tkinter.Menubutton(indBtnFrame[i],
textvariable=button_label,
relief=tkinter.GROOVE)
indBtn.append(temp_widget)
for i in range(len(indBtn)):
indBtn[i].grid(column=0, row=0,
columnspan=1, rowspan=1,
sticky="WENS")
indBtn[i].menu = tkinter.Menu(indBtn[i], tearoff=0)
indBtn[i]["menu"] = indBtn[i].menu

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)

Python Tkinter: OptionMenu modify dropdown list width

I have created an OptionMenu from Tkinter with a columnspan of 2. However, the dropdown list/menu does not match the width, so it does not look good. Any idea on how to match their width?
self.widgetVar = StringVar(self.top)
choices = ['', 'wire', 'register']
typeOption = OptionMenu(self.top, self.widgetVar, *choices)
typeOption.grid(column = 0, columnspan = 2, row = 0, sticky = 'NSWE', padx = 5, pady = 5)
doing drop down name.config(width = width)
works very well with resizing the drop down box.
i managed to get it to work with.
drop1.config(width = 20)
Just letting you know width 20 is quite long.
There is no way to change the width of the dropdown.
You might want to consider the ttk.Combobox widget. It has a different look that might be what you're looking for.
One idea is to pad the right side (or left, or both) with spaces. Then, when you need the selected value, strip it with str strip. Not great, but better than nothing.
from tkinter import ttk
import tkinter as tk
root = tk.Tk()
def func(selected_item):
print(repr(selected_item.strip()))
max_len = 38
omvar = tk.StringVar()
choices = ['Default Choice', 'whoa', 'this is a bit longer'] + ['choice'+str(i) for i in range(3)]
padded_choices = [x+' '*(max_len-len(x)) for x in choices]
om = ttk.OptionMenu(root, omvar, 'Default Choice', *padded_choices, command=func)
om.config(width=30)
om.grid(row=0, column=0, padx=20, pady=20, sticky='nsew')
root.mainloop()
this answer is a little bit late but I thought in case other people are searching for it, here is my solution:
optionMenu1 = ttk.OptionMenu(btnPane, item_text, item_text.get(), "Choose item!\t\t\t\t\t\t\t\t",
*list1, *list2(), style='Custom.TMenubutton')
what I am doing here is to only set the default-value with a lot of tabs (\t). The reason for this is that all items of the dropdown are getting the same width. The width of the longest item. In this case its the Default. Now you can get the value of the other items without stripping something. And your width has changed.
How much tabs you need will you see if you test it (depending on the width of your OptionMenu).
Hope it helps someone.
Regards
Just use config()
typeOption.config(width = 50)
We can change the dropdown width by writing as follows:
typesOfSurgeries = ['Chemotherapy','Cataract']
listOfSurgeries = tkinter.OptionMenu(test_frame, variable, *typesofSurgeries)
listOfSurgeries.config(width=20)
listOfSurgeries.grid(row=14,column=1)
listOfSurgeries.config(width=20) sets the width of the OptionMenu

Categories

Resources