Python TKInter how do I replace data in my frames? - python

I'm having a major issue with my code below. So here's what I'm trying to do.
The user enters certain inputs into the entry fields and the program calculates and displays a corresponding image (loaded in the frame champFrame) and it's description (in spellFrame).
What I want is to replace this image and text every time I click on the Calculate! button so that it shows me a new image and new description based on my new inputs.
However, in its current state, when I enter new input and click the Calculate! button, it just adds the new image below the old one and the old one is still there.
How do I change my code around so that I can replace these old values?
I have heard of using the pack_forget() method but it only hides the previous image, does not remove it so I can replace it with a new one.
from Tkinter import *
from PIL import ImageTk
from Calculation import getHighestScore
from ImageHandler import *
import json
import urllib2
top = Tk()
top.title("LOLSpellEfficiency")
top.geometry("600x600")
def loadInputFields(frame):
AP_Label = Label(frame, text="AP")
AD_Label = Label(frame, text="AD")
CDR_Label = Label(frame, text="CDR")
AP_Label.grid(row=0, column=0)
AD_Label.grid(row=1, column=0)
CDR_Label.grid(row=2, column=0)
AP_Entry = Entry(frame)
AD_Entry = Entry(frame)
CDR_Entry = Entry(frame)
AP_Entry.grid(row=0, column=1)
AP_Entry.insert(0, "0")
AD_Entry.grid(row=1, column=1)
AD_Entry.insert(0, "0")
CDR_Entry.grid(row=2, column=1)
CDR_Entry.insert(0, "0")
return [AP_Entry, AD_Entry, CDR_Entry]
def loadButton(frame, entries):
Enter_Button = Button(frame, text="Calculate!", command = lambda: executeProgram(entries))
Enter_Button.pack(side=TOP)
def executeProgram(entries):
AP = float(entries[0].get())
AD = float(entries[1].get())
CDR = float(entries[2].get())
data = getChampionData()
result = getHighestScore(data, AP, AD, CDR)
champPhoto = ImageTk.PhotoImage(getChampionImage(result[0]))
champLabel = Label(championFrame, image=champPhoto)
champLabel.image = champPhoto
champLabel.pack(side = TOP)
champName = Label(championFrame, text = "Champion: " + result[0])
champName.pack(side = BOTTOM)
spellPhoto = ImageTk.PhotoImage(getSpellImage(result[2]))
spellLabel = Label(spellFrame, image=spellPhoto)
spellLabel.image = spellPhoto
spellText = Text(spellFrame, wrap=WORD)
spellText.insert(INSERT, "Spell: " + result[1] + "\n")
spellText.insert(INSERT, "Spell description: " + result[3] + "\n")
spellLabel.pack(side=TOP)
spellText.pack(side=BOTTOM)
championFrame.pack()
spellFrame.pack()
def getChampionData():
URL = "https://global.api.pvp.net/api/lol/static-data/na/v1.2/champion?champData=all&api_key=8e8904b4-c112-4b0f-bd1e-641649d9e569"
return json.load(urllib2.urlopen(URL))
inputFrame = Frame(top)
inputFrame.pack()
buttonFrame = Frame(top)
buttonFrame.pack()
championFrame = Frame(top)
spellFrame = Frame(top)
championFrame.pack()
spellFrame.pack()
entries = loadInputFields(inputFrame)
loadButton(buttonFrame, entries)
top.mainloop()

Do not create widgets inside of executeProgram. Instead, create them in your main application, and simply change the widgets inside executeProgram.
All widgets have a configure method which lets you change all of the attributes of that widget. For example, to change the image on a label you would do something like this:
champPhoto = ImageTk.PhotoImage(getChampionImage(result[0]))
champLabel.configure(image=champPhoto)
champLabel.image = champPhoto

Related

I'm unable to get a string out of tkinter entrybox

import random
import tkinter as tk
frame = tk.Tk()
frame.title("koeweils baldadige encyptor")
frame.geometry('400x200')
printButton = tk.Button(frame,text = "Print", command = lambda: zandkasteel())
printButton.pack()
freek = tk.Text(frame,height = 5, width = 20)
freek.pack()
input_a = freek.get(1.0, "end-1c")
print(input_a)
fruit = 0
fad = input_a[fruit:fruit+1]
print(fad)
schepje = len(input_a.strip("\n"))
print(schepje)
def zandkasteel():
lbl.config(text = "Ingevulde string: "+input_a)
with open("luchtballon.txt", "w") as chocoladeletter:
for i in range(schepje):
n = random.randint()
print(n)
leuk_woord = ord(fad)*n
print(leuk_woord)
chocoladeletter.write(str(leuk_woord))
chocoladeletter.write(str(n))
chocoladeletter.write('\n')
lbl = tk.Label(frame, text = "")
lbl.pack()
frame.mainloop()
I need to get the string that was entered into the text entry field freek. I have tried to assign that string to input_a, but the string doesn't show up.
Right now, input_a doesn't get anything assigned to it and seems to stay blank. I had the same function working before implementing a GUI, so the problem shouldn't lie with the def zandkasteel.
To be honest I really don't know what to try at this point, if you happen to have any insights, please do share and help out this newbie programmer in need.
Here are some simple modifications to your code that shows how to get the string in the Text widget when it's needed — specifically when the zandkasteel() function gets called in response to the user clicking on the Print button.
import random
import tkinter as tk
frame = tk.Tk()
frame.title("koeweils baldadige encyptor")
frame.geometry('400x200')
printButton = tk.Button(frame, text="Print", command=lambda: zandkasteel())
printButton.pack()
freek = tk.Text(frame, height=5, width=20)
freek.pack()
def zandkasteel():
input_a = freek.get(1.0, "end-1c")
print(f'{input_a=}')
fruit = 0
fad = input_a[fruit:fruit+1]
print(f'{fad=}')
schepje = len(input_a.strip("\n"))
print(f'{schepje=}')
lbl.config(text="Ingevulde string: " + input_a)
with open("luchtballon.txt", "w") as chocoladeletter:
for i in range(schepje):
n = random.randint(1, 3)
print(n)
leuk_woord = ord(fad)*n
print(leuk_woord)
chocoladeletter.write(str(leuk_woord))
chocoladeletter.write(str(n))
chocoladeletter.write('\n')
lbl = tk.Label(frame, text="")
lbl.pack()
frame.mainloop()

Refresh my tkinter label and lets it overwrite it with different output content

I have a Submit button that prints the output on the tkinter widget label. Everytime I change the input and click the Submit the output is displayed but not at the same place i.e. The previous content of the label is not overwritten.
from tkinter import *
from tkinter import filedialog
root = Tk()
root.title("ImageValidation ")
root.geometry("600x600+100+100")
pathlist = [None, None] # holds the two files selected
labels = []
def browse_button(index):
global filename
filename = filedialog.askopenfilename(title = "Choose your file",filetypes = (("jpeg files","*.jpeg"),("all files","*.*")))
pathlist[index] = filename
heading = Label(root, text = "Select 2 images you want to Validate",
font=("arial",15,"bold","underline"), fg="blue").pack()
label1 = Label(root, text = "Enter Image 1", font=("arial",10,"bold"),
fg="black").place(x=10, y = 100)
label2 = Label(root, text = "Enter Image 2", font=("arial",10,"bold"),
fg="black").place(x=10, y = 200)
button = Button(root,text="Choose an Sign1",width = 30,command= lambda:
browse_button(0)).place(x=250, y= 100)
button = Button(root,text="Choose an Sign2",width = 30,command=
lambda: browse_button(1)).place(x=250, y= 200)
def display():
ImageVerification(pathlist[0], pathlist[1])
l1 = Label(root,text=Scriptoutput, width = 200 )
l1.pack(side='bottom', padx=50, pady=50)
#Scriptoutput is the output variable from the main code.
submit_button = Button(text="Submit", width=15,command = display)
submit_button.pack(side='bottom', padx=15, pady=15)
root.mainloop()
A 'refresh' button that would clear the Label of its content and lets you overwrite it.
I am taking your function ImageVerification() as a blackbox and assuming it is working.
The reason this is happening is because you create a new Label, whenever the Submit button is pressed. What you have to do is to create the display Label outside the function and configure its text, whenever the button is pressed. Something like this.
l1 = Label(root, text="", width=200)
l1.pack(side='bottom', padx=50, pady=50)
def display():
ImageVerification(pathlist[0], pathlist[1])
l1.configure(text=Scriptoutput)
#Scriptoutput is the output variable from the main code.
submit_button = Button(text="Submit", width=15,command = display)
submit_button.pack(side='bottom', padx=15, pady=15)

Python display variable with tkinter inside a method

The program I just wrote is my playground for finding out how Tkinter works.
My question is how do I display my variable "timelabel" as a Label.
I allready made a label called timerefresher yet it doesnt show up.
I am aware that the DigitalClock class isn't written efficiently. I am new to this ;).
def Clockupdate(time):
timelabel = time
timerefresher = Label(root, textvariable=timelabel)
timerefresher.pack()
#print(timelabel) To test if variable made it this far.
class DigitalClock:
def secondrefesher(self):
newtime = ""
while 1 == 1:
oldtime = datetime.datetime.now()
a = str(oldtime.hour)
b = str(oldtime.minute)
c = str(oldtime.second)
curtime = (a+":"+b+':'+c)
if curtime != newtime:
newtime = curtime
#print("made it here")
Clockupdate(newtime)
else:
time.sleep(0.20)
DC = DigitalClock()
root = Tk()
mainlabel = Label(root, text="Hey this is working!")
Pressme = Button(root, text="Press me!", command=Presstoshowtextandpic,
bg='red', fg='white')
Clock = Button(root, text="Clock?", command=DC.secondrefesher, bg='blue',
fg='white')
Photo = PhotoImage(file="test.png")
ShowPhoto = Label(root, image=Photo)
mainlabel.pack()
Pressme.pack()
Clock.pack()
root.mainloop()
Ok so Here is what I would do with your code to accomplish what you are trying to do.
First lets make sure we have the correct imports.
from tkinter import *
import datetime
import time
I created this doNothing() function as a place holder for any commands I am not currently testing.
def doNothing():
pass
Now the way you had your Clockupdate(time): function would cause the label to be added every time you click the clock button. so this is probably not what you want as it just keeps adding new labels instead of replacing the existing one. Take a look at this function. All I do in this is .config() the text to be the time argument from the function. Note you do not need to redefine the time to timelabel or anything of the sort, just use time as your varable.
def Clockupdate(time):
timerefresher.config(text = time)
I don't know if you wanted to use a class for a specific reason but I think you should just use a function here. Also try to keep your quotes consistent. I know they are interchangeable but its good practice to keep them consistent.
def secondrefesher():
newtime = ""
oldtime = datetime.datetime.now()
a = str(oldtime.hour)
b = str(oldtime.minute)
c = str(oldtime.second)
curtime = (a + ":" + b + ":" + c)
if curtime != newtime:
newtime = curtime
Clockupdate(newtime)
Note I always place commands at the end of any config of a button. It helps when managing code so you can just check the end of each line as you scroll through your code. I also changed the command for Pressme to doNothing so I could test the code. You didn't provide the code for Presstoshowtextandpic and would not be able to test the code with out that part. Remember when asking a question here to use MCVE.
root = Tk()
mainlabel = Label(root, text="Hey this is working!")
Pressme = Button(root, text = "Press me!", bg = "red", fg = "white", command = doNothing)
Clock = Button(root, text = "Clock?", bg = "blue", fg = "white", command = secondrefesher)
Photo = PhotoImage(file = "test.png")
ShowPhoto = Label(root, image = Photo)
Here I created the time label just once and then you can call the update function all you want to change the text to current time.
timerefresher = Label(root, text = "")
timerefresher.pack()
mainlabel.pack()
Pressme.pack()
Clock.pack()
root.mainloop()
Here is what I think the completed code should look like for you.
from tkinter import *
import datetime
import time
def Clockupdate(time):
timerefresher.config(text = time)
def secondrefesher():
newtime = ""
oldtime = datetime.datetime.now()
a = str(oldtime.hour)
b = str(oldtime.minute)
c = str(oldtime.second)
curtime = (a + ":" + b + ":" + c)
if curtime != newtime:
newtime = curtime
Clockupdate(newtime)
root = Tk()
mainlabel = Label(root, text = "Hey this is working!")
Pressme = Button(root, text = "Press me!", bg = "red", fg = "white", command = Presstoshowtextandpic)
Clock = Button(root, text = "Clock?", bg = "blue", fg = "white", command = secondrefesher)
Photo = PhotoImage(file = "test.png")
ShowPhoto = Label(root, image = Photo)
timerefresher = Label(root, text = "")
timerefresher.pack()
mainlabel.pack()
Pressme.pack()
Clock.pack()
root.mainloop()
Edit:
In case you are trying to create a clock that is always active and does not require you to click the button you can use .after().
Take a look at this example.
from tkinter import *
import datetime
import time
root = Tk()
mainlabel = Label(root, text = "Hey this is working!")
Photo = PhotoImage(file = "test.png")
timerefresher = Label(root, text = "")
timerefresher.pack()
status_time = ""
def tick():
global status_time
time2 = time.strftime("%H:%M:%S")
if time2 != status_time:
status_time = time2
timerefresher.config(text = time2)
timerefresher.after(200, tick)
tick()
mainlabel.pack()
root.mainloop()
You should have written an MCVE so that one can test your code, especially that things are missing (such as Presstoshowtextandpic()).
When reading the rest of your code, I think you need to read about variable classes and modify Clockupdate() as follows:
def Clockupdate(time):
timelabel = StringVar() # modified
timelabel.set(time) # added
timerefresher = Label(root, textvariable=timelabel.get()) #modified
timerefresher.pack()
P.S. You should write clock_update() instead of Clockupdate()

Python Prints List Object [tkinter.StringVar object at 0x01FEAD50], But Not Items in List *Tkinter*

I am trying to create a GUI that will be able to monitor the integrity of files using their MD5 hashes (the actual monitoring of updates log can be in the command prompt).
I got the initial command line program to work perfectly, but am having an issue when converting it to a GUI based version using tkinter.
I use the GUI to create a list of files that I want to monitor in the 'addFiles' function, but when I try to pass that list to the 'checkForIntegrity' function (or print the list with my test print(listOfFiles) code in that function), all I get is [tkinter.StringVar object at 0x01FEAD50], but do not get the actual list.
I have searched far and wide for an answer and have tried using various implementations of 'listOfFiles.get()' in different locations but have had no success.
I have no idea why I only get the actual list object but no listed items, my code is below.
Thank you in advance everyone.
edit: Just to be clear, my 'GUI()' function creates a window that asks how many files the user would like to monitor and passes that to the 'addFiles()' function which allows input for the amount of files they specify. I need to be able to pass the files they specify in that GUI to the program via a list. Thanks again.
import hashlib
import time
from tkinter import *
def main():
GUI()
def GUI():
window = Tk()
window.title("Integrity Checker")
frame1 = Frame(window)
frame1.pack()
label1 = Label(frame1, text = "***Proof Of Concept Program That Monitors the Integriry of Files***")
label1.grid(row = 1, column = 1)
frame2 = Frame(window)
frame2.pack()
getNumberOfFiles = Label(frame2, text = "Insert Number of Files You Would Like to Check: ")
getNumberOfFiles.grid(row = 2, column = 1)
numberOfFiles = IntVar()
NumberOfFilesOption = Entry(frame2, textvariable = numberOfFiles)
NumberOfFilesOption.grid(row = 2, column = 2)
button = Button(frame2, text = "OK", command = lambda : addFiles(numberOfFiles))
button.grid(row = 2, column = 3)
window.mainloop()
def addFiles(numberOfFiles):
listOfFiles = []
window = Tk()
window.title("Add Files")
frame1 = Frame(window)
frame1.pack()
label1 = Label(frame1, text = "***Select The Files You Want To Monitor***")
label1.grid(row = 1, column = 1)
for i in range (numberOfFiles.get()):
AddFile = Label(frame1, text = "Add File:")
AddFile.grid(row = (i + 3), column = 1)
FileName = StringVar()
FileNameOption = Entry(frame1, textvariable = FileName)
FileNameOption.grid(row = (i + 3), column = 2)
button = Button(frame1, text = "OK", command = lambda : listOfFiles.append(FileName))
button.grid(row = (i + 3), column = 3)
button2 = Button(frame1, text = "Done", command = lambda : checkforINTEGRITY(numberOfFiles, listOfFiles))
button2.grid(row = (i + 4), column = 2)
window.mainloop()
def checkforINTEGRITY(numberOfFiles, listOfFiles):
#Number = numberOfFiles.get()
#listOfFiles = []
#count = 0
#numberOfFiles = eval(input("How many files would you like to monitor?: "))
#while count < Number:
# filename = input("Enter the name of the file you would like to check: ")
# count += 1
# listOfFiles.append(filename)
print(listOfFiles)
i = 0
originalList = []
for file in listOfFiles:
original_md5 = hashlib.md5(open(listOfFiles[i],'rb').read()).hexdigest()
originalList.append(original_md5)
i += 1
print(originalList)
while True:
i = 0
while i < Number:
md5_returned = hashlib.md5(open(listOfFiles[i],'rb').read()).hexdigest()
print(md5_returned)
if originalList[i] == md5_returned:
print("The file", listOfFiles[i], "has not changed")
else:
print("The file", listOfFiles[i], "has been modified!")
i += 1
time.sleep(5)
main()
It looks like you want to call the get method on FileNameOption:
button = Button(frame1, text = "OK", command = lambda : listOfFiles.append(FileNameOption.get()))
With this change I was able to get a list of strings in listOfFiles.

My Tkinter label dissapeared when i put in the buttons

I am trying to create a simple hangman game using tkinter with python. While creating the GUI, the first thing I put in were the dashes.lbl = tkinter.Label(window, text= xhash). When I put in my buttons, the label disappeared. I have tried making the window bigger, but it still didn't come back.
Here is my full code:
#importing modules
import tkinter
import random
#creating the dashes
f = open(r'C:\Users\Gareth\Documents\hangman\words.txt', 'r')
word = f.readlines()
guess = random.choice(word)
hash = []
xhash = ""
while len(hash) < len(str(guess)):
hash.append('_ ')
def rejoin():
xhash = "".join(hash)
xhash.strip("[]")
xhash.strip(",")
xhash.strip("'")
#creating the window
window = tkinter.Tk()
window.minsize(300, 300)
#commands for buttons a-z
def acmd():
for i in list(guess):
if i == 'a':
hash[guess.index(i)] = 'a'
rejoin()
lbl.configure(text= xhash)
abtn.configure(bg = 'red')
#label
lbl = tkinter.Label(window, text= xhash)
#buttons for letters a-z
abtn = tkinter.Button(window, text = 'a', command = acmd)
bbtn = tkinter.Button(window, text = 'b')
cbtn = tkinter.Button(window, text = 'c')
dbtn = tkinter.Button(window, text = 'd')...
#placing lbl and buttons
lbl.grid(row = 1, column = 1)
abtn.grid(row = 3 , column = 1)
bbtn.grid(row = 3 , column = 2)
cbtn.grid(row = 3 , column = 3)...
window.mainloop()
You would need to position them correctly, most probably either you are not positioning them or positioning them on top of each other. You would need to use grid() to position them
Example -
lbl = tkinter.Label(window, text= xhash)
lbl.grid(row=0,column=1)
abtn = tkinter.Button(window, text = 'a', command = acmd)
abtn.grid(row=0,column=2)
The problem did not lie within the label, but within the text.
def rejoin():
xhash = "".join(hash)
xhash.strip("[]")
xhash.strip(",")
xhash.strip("'")
the only adjustment needed was a global statement...
without that, whatever was done in the function had nothing to do with anything else, so, the previously assigned xhash = '', was simply left blank...

Categories