Placing a label in another label tkinter - python

im making a machine for Geometric volumes but i have a problem: my problem is When the user enters a number to perform calculations, a label shows the result, but what happens if the user wants to get the volume of the cylinder? Exactly >>23 >>34 It gives two numbers, one for the previous volume and one for the current volume, and this creates a problem because the program page is limited, and if the user performs more operations than one number, it will exit the page and you have to open that window again.
Visual example:
In simple words, I want the label to show the result when the user performs the first operation, but in the second operation, the label replaces the first label and shows the result.
my code:
def cube():
def jerm_1():
a = int(text.get())
b = int(text_1.get())
c = int(text_2.get())
jerm=a * b * c
Label(top,text=jerm,font=20).pack()
def ostevane():
text_2.destroy()
a = int(text.get())
b = int(text_1.get())
jerm = a * b
Label(top,text=jerm,font=20).pack()
def taghir():
mohasebe.config(command=ostevane)
def taghir_1():
mohasebe.config(command=jerm_1)
top = Toplevel()
top.maxsize(300,300)
menu_top = Menu()
menu_select = Menu(menu_top,tearoff=0)
menu_top.add_cascade(label="اشکال دیگر",menu=menu_select)
menu_select.add_command(label="استوانه",command=taghir)
menu_select.add_command(label="مکعب و مستطیل مکعب",command=taghir_1)
top.minsize(300,300)
text = Entry(top,font=20)
text.pack()
text_1 = Entry(top,font=20)
text_1.pack()
text_2 = Entry(top,font=20)
text_2.pack()
mohasebe=Button(top,text="حجم",font=20)
mohasebe.pack()
top.config(menu=menu_top)

its fixed!
step 1:first you need to create a Label then do this:
label = Label(.......)
label.pack_forget()
step 2: create a def and do what do you want then do this:
label.pack()
label.config(text = *what you have done*)
now its fixed!

Related

why command function of tkinter radiobuttons in a loop only works for the last iteration properly

I hope I can explain the problem properly enough... so basically, I am in the progress of creating a Gui.
In this extracted piece of code I want to iterate over my port_str list and make a frame with the name of each element and some radio buttons in the frame;
and for three of these buttons R1_wire, R2_wire, etc. I call another function sel_wire_1 with 'command' to either make the buttons (e.g.R1_discipline) active or disabled.
The problem is now that if I want to print the value of the selected radio button in one of the first frames it always shows me the name of the last element in the list and the value(either 1 or two) of the last element of the port_str list and this depended on activation in sel_wire__1 also only works for the last frame (the last element of the list port_str). Also this dependend selection of sel_wire_1 does inly work for the last created frame.
So I have several identical frames in front of me with different 'labels'(out of the list) but the command function only works correctly for the last frame(last element).
I tried so many things but I still don't know how to fix that as I'm new to tkinter and not that good with OOP. I did exactly the same thing in functional programming and it worked perfectly. So what is the problem in this oop case then?
Thanks to everyone who can help in advance
class MSM:
def __init__(self,top):
#create main frame, holds everything
self.main_frame= Frame(self.top,width = 50, height = 100, bd = 1)
self.main_frame.pack(fill=BOTH, expand=1)
#creat a canvas
self.my_canvas = Canvas(self.main_frame)
self.my_canvas.pack_propagate(0)
self.my_canvas.pack(side = LEFT, fill = BOTH, expand = 1)
self.second_frame = Frame(self.my_canvas)
port_str = [port1,port2,port3,port4,port5]
for port in port_str:
self.pins(port) #here i call the pins() function in a for loop to create s frame with some radiobuttons for each element of the port_str list
def pins(self,port):
#here im defining a frame and the label of each frame which are elements of the port_str list
self.frame_portdetails = Frame(self.frame_portdetails_top)
self.frame_portdetails.pack(fill= 'both', expand = 1)
self.var_wiretype = IntVar()
self.R1_wiretype = Radiobutton(self.frame_portdetails, text= ("wire",port),variable=self.var_wiretype, value=1,command= self.sel_wiretype_1)
self.R1_wiretype.grid( row=1,column=1,sticky='W')
self.R2_wiretype = Radiobutton(self.frame_portdetails, text=("wreal",port),variable=self.var_wiretype, value=2,command=self.sel_wiretype_1)
self.R2_wiretype.grid( row=1,column=2,sticky= 'W' )
#discipline here just more buttons are being defined
self.var_discipline = IntVar()
self.R1_discipline = Radiobutton(self.frame_portdetails, text="logic", variable=self.var_discipline, value=1 )
self.R1_discipline.grid(row=2,column=1,sticky='W')
self.R2_discipline = Radiobutton(self.frame_portdetails, text="vreal", variable=self.var_discipline, value=2)
self.R2_discipline.grid(row=2,column=2,sticky='W')
self.R3_discipline = Radiobutton(self.frame_portdetails, text="ireal", variable=self.var_discipline, value=3)
self.R3_discipline.grid(row=2,column=3,sticky='W')
self.R4_discipline = Radiobutton(self.frame_portdetails, text="other", variable=self.var_discipline, value=4 )
self.entry1 = ttk.Entry (self.frame_portdetails, width = 10 )
self.entry1.grid(row=3,column=2)
self.R4_discipline.grid(row=3,column=1,sticky='W')
def sel_wiretype_1(self): #this should either make a button active or
#disabled but is seems this is only being applied to the last element
#of the list/ the last frame(and the buttons inside) that is being
#created
if(self.var_wiretype.get()==1):
self.R1_discipline['state']='active'
self.R2_discipline['state']='disabled'
self.R3_discipline['state']='disabled'
self.var_discipline.set(1)
else:
self.R1_discipline['state']='disabled'
self.R2_discipline['state']='active'
self.R3_discipline['state']='active'
self.var_discipline.set(2)
if __name__ == "__main__":
root = tk.Tk()
app = MSM(root)
root.mainloop(

Using a for loop to create buttons in tkinter and give them each a unique input

Hello I am working on a screenshot project. For part of it I would like to open up a window with a button for every screenshot then be able to click on one and get the image to show up.
I so far used this function to create the buttons when it opens the window.
def create_secondwindow_button():
x = 1
y = 0
mypath = "C:\\Users\\Link\\OneDrive\\Desktop\\python stuff\\screenshot example\\All snapshot images"
for I in listdir(mypath):
btp = mypath +"\\"+str(I)
print(btp)
screenshot_snap = Button(sec_window,text = str(I), bg = "chocolate3",activebackground = "white",padx= 80,pady =10,command =lambda: image_replacer(y))
screenshot_snap.grid(column = 4, row = int(x),rowspan = 5,columnspan = 5,padx = 50,pady =10)
x += 10
if y < 3:
y += 1
The problem is the input for all the buttons just remains at the last value of y for all of them.
I need to have a variable input as the amount of images are going to be constantly changing.
Does anyone know how I can solve this issue. Thanks a bunch!

How to update variables from a text file in a GUI in real time? Python and tkinter

I have a script that continuously updates numbers on a text file in the same directory. I made a GUI using tkinter to display these numbers. I'm having a hard time getting the GUI to update the numbers in real time. It will display the numbers as they were when the GUI first started, but will not update the display as the text file changes. Here's some basic code to demonstrate:
def read_files(file, line):
old = open(f'{file}.txt', 'r').readlines()[line]
new = old.replace('\n', '')
return new
number = read_files('Statistics', 0)
number_label = Label(frame1, text=f'{number}')
number_label.grid(row=0, column=0)
The above code shows the number from the text file as it was when the GUI first opened. However, it does not update the number as its value in the text file changes. I did some reading around and also tried the following:
def read_files(file, line):
old = open(f'{file}.txt', 'r').readlines()[line]
new = old.replace('\n', '')
return new
number = read_files('Statistics', 0)
number_label = StringVar()
number_label.set(number)
number_display = Label(frame1, text=f'{number_label.get()}')
number_display.grid(row=0, column=0)
This has the same effect. It shows the value retrieved from the text file at the moment the GUI was opened, but does not update it as the text file is updated. Any help is appreciated.
Since there is no complete code, take a look at this example:
from tkinter import *
root = Tk()
def update_gui():
number = read_files('Statistics', 0) # Call the function
number_display.config(text=number) # Change the text of the label, also same as text=f'{number}'
root.after(1000,update_gui) # Repeat this function every 1 second
def read_files(file, line):
old = open(f'{file}.txt', 'r').readlines()[line]
new = old.replace('\n', '')
return new
number_display = Label(root) # Empty label to update text later
number_display.grid(row=0, column=0)
update_gui() # Initial call to the function
root.mainloop()
Here the label is created outside the function but the text is not given, but inside the function we are repeating the function every 1 second, with after, and changing the text of the label with config method. I have avoided the use of StringVar() as it's of no use here, you can just store it in a normal variable and use it.
Here is a plagiarized look at how after should be used:
def after(self, ms, func=None, *args):
"""Call function once after given time.
MS specifies the time in milliseconds. FUNC gives the
function which shall be called. Additional parameters
are given as parameters to the function call. Return
identifier to cancel scheduling with after_cancel."""

How to create a letter counter with Tkinker?

I just started to learn Python and I'm trying to create a mineral counter by only using letters for microscopic petrography, but I am having problems passing my python code to Tkinker. Can you guys give tips about how to get my output to work? I'm finding it challenging to use theget() method even with online tutorials.
Can you guys teach this noob? Thank you!
My original code:
# define sample
sample = "qreqqwer"
# mineral q:
mineralq= "q"
countq = sample.count(mineralq)
# print count of q
print("The quantity of q is: ", countq)
The structure I made with Tkinker:
from tkinter import *
import tkinter as tk
# Window
window=tk.Tk()
window.title("Mineral Counter")
window.geometry("800x1000")
window.configure(bg="#00090F")
inputUser=tk.Text(window,width=225,height=5,font=("Arial bold",12),wrap="word", bg="#00090F", fg="white")
inputUser.pack()
# define sample
# mineral q:
countq = inputUser.count("q")
# print count of q
output.insert(tk.INSERT,countq)
output=tk.Text(window,width=20,height=2,font=("Arial bold",12), bg="#00090F", fg="white")
output.pack()
window.mainloop()
You need a button to update your code, becuase initially the Text boxes are empty and hence there is no occurence for q so nothing can be inserted.
Try this out:
First create a button with a function to click onto after the data is entered
b = tk.Button(window, text='Click Me', command=click)
b.pack()
Then now define the function that the button calls when is clicked onto
def click():
sample = inputUser.get('1.0', 'end-1c') #getting value from text box 1
mineralq = 'q' #letter to be counted
countq = sample.count(mineralq) #counting the letter
output.insert('1.0', f'The quantity of q is: {countq}') #inserting the output to text box 2
Hope it cleared your doubt, if any errors do let me know
Cheers

.set in function is not being found in other function so it's creating an error tkinter python

I'm trying to create a GUI, in the nav menu you can click a cascade option to open another window where you can click roll to generate a set of numbers. It comes up with error. I think it's because the function is called from another function I just don't know how to get that function to call it/ if there is any other ways to fix this. I've tried global functions and looking it up but haven't found anything other than using classes so far, which I don't know how to do.
line 147, in totalRolls
txtresultsOut.set(totalRollResults)
NameError: name 'txtresultsOut' is not defined
Here is the code that is relevant to it. I've called the function to skip having to input all the other code for the main gui window.
def rollSix():
s = 0
numbers = [0,0,0,0]
for i in range(1,5):
numbers[s] = randrange(1,7)
s += 1
numbers.remove(min(numbers))
Result = sum(numbers)
totalRollResults.append(Result)
def totalRolls():
rollOne()
rollTwo()
rollThree()
rollFour()
rollFive()
rollSix()
txtresultsOut.set(totalRollResults)
def rollw():
rollWindow = tix.Tk()
rollWindow.title("Dice Rolls")
diceLabel = Label(rollWindow, text = "Click Roll for your Stats")
diceLabel.grid(row = 0, column = 0)
rollBtn = Button(rollWindow, text = "Roll Stats", command = totalRolls)
rollBtn.grid(row = 1, column = 0)
txtresultsOut = StringVar()
resultsOut = Entry(rollWindow, state = "readonly", textvariable = txtresultsOut)
resultsOut.grid(row = 2, column = 0)
rollw()
first of all I would NOT recommend using StringVar(). You can use the .get() method of Entry to obtain the value inside the same. Try this way and make a global declaration of the Entry whose values you want to get in other functions.
EDIT------------
#you can use the following code to make your entry active to be edited.
entry.configure(state='normal')
# insert new values after deleting old ones (down below)
entry.delete(0,END)
entry.insert(0, text_should_be_here)
# and finally make its state readonly to not let the user mess with the entry
entry.configure(state='readonly')

Categories