How do I check if a StringVar in an Input is empty - python

Trying to make a button to create a file name with an input of a text variable, I'm trying to make an input that would be the "default" if the actual text box is empty, my code is as follows
def makefile():
try: prefix_text.get()
except NameError: prefix_text = None
if prefix_text is None:
prefix_text=StringVar()
prefix_text.set("Kido")
ply = open(prefix_text.get()+"_Player_.uc", "w")
ply.close()
window=Tk()
l1=Label(window, text="Prefix")
l1.grid(row=0, column=0)
prefix_text=StringVar()
e1=Entry(window, textvariable=prefix_text, width=42)
e1.grid(row=0, column=1)
b1=Button(window, text="Create File", width=12, command=makefile)
b1.grid(row=1, column=1)
window.mainloop()
MakeFile is supposed to test if the input is empty before making the file and if it is empty just set the name to be Kido, however this somehow will always cause the name to be Kido instead of the input
I've tried various things to no avail and nothing I can seem to find gives me good input on how to check if that variable is null, any help would be much appreciated!

To check if the entry is empty just check the linked variable prefix_text. Also be sure to use prefix_text.get() instead of just prefix_text.
def makefile():
global prefix_text
try: prefix_text.get()
except NameError: prefix_text = None
if not prefix_text.get().strip(): # if blank entry
prefix_text.set("Kido") # set entry
ply = open(prefix_text.get()+"_Player_.uc", "w")
ply.close()

Related

Python not waiting for return function, and continuing without a response

I have a function that saves files to the user's computer in Tkinter. I am trying to create a prompt for the user if they are trying to save a file that already exists, asking them if they'd like to overwrite the existing file, or not. I'm not going to include the whole code as it is 3000+ lines, but an example of what I'm trying to do:
I understand os.path.save() is not valid, I'm using Shutil to copy an existing file from another location, this is just for example purposes.
def overWritePrompt():
promptFrame = tk.Frame(maniWin, bg=_blk)
promptFrame.place(relx=.4,rely=.2,relheight=.1,relwidth=.2)
promptHead = tk.Label(promptFrame, bg=_blk, fg=_wht, text="Overwrite existing route?")
promptHead.place(relx=0,rely=0,relheight=.4,relwidth=1)
promptYes = tk.Button(promptFrame, bg=_dgrn, fg=_wht, text="Yes", relief="sunken", activebackground=_dgrn, activeforeground=_wht, command=lambda:(selection(True)), borderwidth=0)
promptYes.place(relx=.1,rely=.5,relheight=.4,relwidth=.35)
promptNo = tk.Button(promptFrame, bg=_red, fg=_wht, text="No", relief="sunken", activebackground=_red, activeforeground=_wht, command=lambda:(selection(False)), borderwidth=0)
promptNo.place(relx=.45,rely=.5,relheight=.4,relwidth=.35)
def selection(response):
promptFrame.destroy()
return response
def saveFile(fileName):
overwrite = False
if os.path.exists(os.path.join(directory, fileName)):
overwrite = overwritePrompt()
if overwrite:
os.path.remove(fileName)
os.path.save(fileName)
else:
os.path.save(fileName)
I expect this to display the prompt to the user and wait for a response before continuing to the saving portion, however it just immediately returns None for the overwrite bool, and continues on with the rest of the code.
Why isn't overwrite = overwritePrompt() waiting for overWritePrompt() to return before continuing?
I have tried adding while loops in different places to keep the code from moving on until the user inputs their answer, but that just freezes the app completely.
The nested function selection() doesn't iteract with the outer function overwritePrompt at all so its return statement doesn't affect the value returned by the outer function. selection() is just a normal function like any other in that regard.
You could simplify the whole thing by using a built-in Tk message box:
def saveFile(fileName):
if os.path.exists(os.path.join(directory, fileName)):
overwrite = tkinter.messagebox.askokcancel("Confirm", "Overwrite file?")
if overwrite:
os.path.remove(fileName)
os.path.save(fileName)
The solution I found was having the "save" button, call on the overWritePrompt() first, then have the prompt check if the file exists, then pass the result of the user input to the saveFile() function.
def overWritePrompt(fileName):
promptFrame = ""
def clearPrompt():
promptFrame.destroy()
if os.path.exists(os.path.join(directory, fileName)):
promptFrame = tk.Frame(maniWin, bg=_blk)
promptFrame.place(relx=.4,rely=.2,relheight=.1,relwidth=.2)
promptHead = tk.Label(promptFrame, bg=_blk, fg=_wht, text="Overwrite existing route?")
promptHead.place(relx=0,rely=0,relheight=.4,relwidth=1)
promptYes = tk.Button(promptFrame, bg=_dgrn, fg=_wht, text="Yes", relief="sunken", activebackground=_dgrn, activeforeground=_wht, command=lambda:(clearPrompt, saveFile(fileName, True)), borderwidth=0)
promptYes.place(relx=.1,rely=.5,relheight=.4,relwidth=.35)
promptNo = tk.Button(promptFrame, bg=_red, fg=_wht, text="No", relief="sunken", activebackground=_red, activeforeground=_wht, command=lambda:(clearPrompt, saveFile(fileName, False)), borderwidth=0)
promptNo.place(relx=.45,rely=.5,relheight=.4,relwidth=.35)
else: saveFile(fileName, False)
def saveFile(fileName, overwrite):
if overwrite:
os.path.remove(fileName)
os.path.save(fileName)
else:
os.path.save(fileName)

So i am making this file encrypter and decrypter, and now i am trying to make it an application using Tkinter GUI. got this error

Long ago i watched a tutorial on how to encrypt files(of any kind) with a key/password
The original code just makes the process in the terminal, but i wanted to make it into an application using tkinter as my GUI, i've come to a problem my small brain can't solve
The original video: https://www.youtube.com/watch?v=HHlInKhVz3s
This is the error i get: TypeError: Encrypt() missing 2 required positional arguments: 'WhichFile' and 'KeyInput'
This is my code:
from tkinter.filedialog import askopenfilename
import time
root = Tk()
root.title=("Tkinter Calculator")
root.geometry("500x500")
#title
WindowTitle = Label(root, text="Choose Action", font=("Arial", 15))
WindowTitle.place(x=250, y=10,anchor="center")
### The functions
#Encrypt
def Encrypt(WhichFile, KeyInput):
file = open(WhichFile, "rb")
data = file.read()
file.close()
data = bytearray(data)
for index, value in enumerate(data):
data[index] = value ^ KeyInput
file = open("CC-" + WhichFile, "wb")
file.write(data)
file.close()
#Decrypt
def Decrypt(WhichFile, KeyInput):
file = open(WhichFile, "rb")
data = file.read()
file.close()
data = bytearray(data)
for index, value in enumerate(data):
data[index] = value ^ KeyInput
file = open(WhichFile, "wb")
file.write(data)
file.close()
#Step1 - Write the name of the file(Needs to be in the same folder(Also include ext.))
WhichFile = Entry(root, width = 20)
WhichFile.place(x=100, y=150)
WhichFile.insert(0, "Enter File name with extension")
#Step2 - Ask for a key/password
KeyInput = Entry(root, width = 20)
KeyInput.place(x=100, y=250)
KeyInput.insert(0, "Enter a key: ")
#Button for encrypt
Encryptbtn = Button(root, text="Encrypt", highlightbackground='#3E4149', command=Encrypt)
Encryptbtn.place(x=100, y=350)
#Button for decrypt
Decryptbtn = Button(root, text="Decrypt", highlightbackground='#3E4149', command=Decrypt)
Decryptbtn.place(x=200, y=350)
root.mainloop()
So the error occurs in this line:
Encryptbtn = Button(root, text="Encrypt", highlightbackground='#3E4149', command=Encrypt)
Passing a function with arguments to Button's "command"
You have to pass the arguments to the function Encrypt() which demands args "WhichFile" and "KeyInput".
You can pass arguments in Button declaration by using lambda keyword:
Button(root, text="Encrypt", highlightbackground='#3E4149', command=lambda:Encrypt(file,input))
It will take the values of "file" and "input" just when you click on the button, remember it cause sometime it is not that what you actually want (e.g. Python Tkinter button callback).
If you want the arguments to be "remembered" as they was at moment of creating button, use currying
(What is 'Currying'? ,
More about "lambda").
So, for first you have to pass arguments to that function. As I can see, you slightly don't understand how it works, cause you're trying to use the arguments in declaration of a funtion like they were a global variables of something (def Encrypt(WhichFile, KeyInput) and then as an "assignment" WhichFile = Entry(...)) but it doesn't work like that, arguments that are passed to function are specified in function's call, e.g. foo(argument1,argument2), not at the moment of defining it.
Getting text from Entry :
You have to know, that WhichFile = Entry(root, width = 20) is not assigning the value of Entry to WhichFile variable, but the Entry itself (check it by using print(WhichFile)). I propose changing the name of that variable for e.g. "user_input_file" or sth.
If you want to get the text typed in the Entry use user_input_file.get().
Excatly the same thing with KeyInput Entry.
Next, you have to create a variable that will point to that value (python varaibles are pointers), and assign it in that function in a way I mentioned before (with that lambda:).
Just write it as a global variable, for example:
WhichFile = user_input_file.get()
KeyInput = user_input_key.get()
Of course after declaring user_input_file and user_input_key.
I think that'll solve ur problem, feel free to ask 'bout more.

Saving the value of a checkbox if it's on Tkinter

I need help. While I'm saving the value of "box" it just writes ".!checkbutton" instead of the value I want. Why does this happen and how to fix it.
So I want it to write the onvalue in the txt instead of .!checkbutton if the box is ticked
how to fix this
Also if there is a way to make the checkbox bigger I would appreciate it :)
# -*- coding: utf8 -*-
from tkinter import *
from tkinter import messagebox
import os
root = Tk()
root.title('Feedback')
root.geometry("400x400")
organizerlist = [
"213",
"1231",
"123",
"123",
"123",
"123",
"123",
"."
]
eventsnames = [
"Rocket League"
]
def run():
# getting the name
filename = filename_ent.get()
if filename == '':
# to show an error that boxes are empty
messagebox.showerror(
'File exists', 'File already exists, try some other name thas is not used before')
if os.path.exists(f'{filename}.txt'):
# to show an error if the file already exists
messagebox.showerror(
'File exists', 'File already exists, try some other name not used before')
else:
# to open the file for python
new = open(f'{filename}.txt', '+w', encoding='utf-8')
# to write the name and email inside the file
new.write(f'''Admin of the event: {clicked.get()}\n{responsible.get()} \n{box}''')
lfilename.config(text=f'The Feedback has been written successfully!') # to change the label to the name
os.startfile(f'{filename}.txt') # to open the file in a new window
lfilename = Label(root,text="What do you want to call the file?", font = ("helvatica, 14"))
lfilename.grid(row=0, column=0)
filename_ent = Entry(root)
filename_ent.grid(row=1, column=0)
clicked = StringVar()
clicked.set("Who is Admin?")
drop = OptionMenu(root, clicked, "User", "#User2", "#User3", "#User")
drop.grid(row=2, column=0)
eventname = StringVar()
eventname.set("Which event was it?" )
eventname_drop = OptionMenu(root, eventname, *eventsnames, )
eventname_drop.grid(row=3,column=0, )
responsible = StringVar()
responsible.set("Who is the responsible?")
responsible_drop = OptionMenu(root, responsible, *organizerlist)
responsible_drop.grid(row=4,column=0)
responsible_drop.config(width=30, font=("helvatica", 14))
var = StringVar()
box = Checkbutton(root,text="test", variable=var, onvalue="Working", offvalue="Not Working")
box.grid(row=3,column=3)
b = Button(root, text='Done', command=run)
b.grid(row=20, column=0)
root.mainloop()
Try changing function to to below:
def run():
# getting the name
filename = filename_ent.get()
if filename == '':
# to show an error that boxes are empty
messagebox.showerror('Empty Box', 'Make sure to to fill the filename box.')
elif os.path.exists(f'{filename}.txt'):
# to show an error if the file already exists
messagebox.showerror(
'File exists', 'File already exists, try some other name not used before')
else:
# to open the file for python
new = open(f'{filename}.txt', '+w', encoding='utf-8')
# to write the name and email inside the file
new.write(f'Admin of the event: {clicked.get()}\n{responsible.get()} \n{var.get()}')
lfilename.config(text=f'The Feedback has been written successfully!') # to change the label to the name
os.startfile(f'{filename}.txt') # to open the file in a new window
In short, you forgot to call var.get() and you said box instead, which was the checkbutton itself.
Also Ive changed your second if statement to elif because having multiple if will lead to the second if getting executed, no matter what the conditions on first if was. Just try saying an empty filename with your code, and you can see the problem.
Hope this helped, do let me know if any errors or doubts.

How to store the input from the text box in python?

I want to make a program that show me the divisors of the number introduced in a text box using python tkinter GUI and store the results into a plain text file.
I don't how to get the value from the text box. I understood that is something linked with get() , I read something but I still don't get it.
Here is the code:
from tkinter import *
def create_file():
file_object = open("C:/Users/valis/Desktop/Divisors.txt","w+")
def evaluate():
show_after= Label(text= "Check your Desktop !")
show_after.pack(pady=2, anchor=SW)
create_file()
#Windows size and Title
window = Tk()
window.title("Show Divisors")
window.geometry("300x100")
message = Label(window, text="Enter a number : ")
message.pack(pady=2, anchor=NW)
textbox_input = Text(window,height=1, width=11)
textbox_input.pack(padx= 2,pady= 2, anchor=NW)
window.mainloop()
The code isn't complete, so what should I do ?
As you said, you will use the get() function but with some additional attributes.
If we have a text box textbox_input, then you can return its input using this line:
test_input = textbox_input.get("1.0",END)
The first part, "1.0" means that the input should be read from line one, character zero (ie: the very first character). END is an imported constant which is set to the string "end". The END part means to read until the end of the text box is reached.
Reference: This answer.

How can i make the browsed file the target for process, instead of it being hard coded in?

Instead of "mbox = ?????????" in the def start_processing(self) section, how do i make it the file that has been uploaded. This was originaly hard coded however have changed it to a file upload? Thanks
class App:
def __init__(self, master):
self.master = master
# call start to initialize to create the UI elemets
self.start()
def start(self):
self.master.title("Extract Email Headers")
self.now = datetime.datetime.now()
# CREATE A TEXT/LABEL
# create a variable with text
label01 = "Please select the .mbox file you would like to analyse"
# put "label01" in "self.master" which is the window/frame
# then, put in the first row (row=0) and in the 2nd column (column=1),
# align it to "West"/"W"
tkinter.Label(
self.master, text=label01).grid(row=0, column=0, sticky=tkinter.W)
# CREATE A TEXTBOX
self.filelocation = tkinter.Entry(self.master)
self.filelocation["width"] = 60
self.filelocation.focus_set()
self.filelocation.grid(row=1, column=0)
# CREATE A BUTTON WITH "ASK TO OPEN A FILE"
# see: def browse_file(self)
self.open_file = tkinter.Button(
self.master, text="Browse...", command=self.browse_file)
# put it beside the filelocation textbox
self.open_file.grid(row=1, column=1)
# now for a button
self.submit = tkinter.Button(
self.master, text="Execute!", command=self.start_processing,
fg="red")
self.submit.grid(row=3, column=0)
def start_processing(self):
date1= "Tue, 18 Jan 2015 15:00:37"
date2="Wed, 23 Jan 2015 15:00:37"
date1 = parser.parse(date1)
date2 = parser.parse(date2)
f = open("results.txt","w")
mbox = ????????????????????
count = 0
for msg in mbox:
pprint.pprint(msg._headers, stream = f)
tempdate = parser.parse(msg['Date'])
print(tempdate)
f.close()
print(count)
pass
def browse_file(self):
# put the result in self.filename
self.filename = filedialog.askopenfilename(title="Open a file...")
# this will set the text of the self.filelocation
self.filelocation.insert(0, self.filename)
I'm assuming you want to store the file path in a StringVar. TK uses special control variables to provide functionality for Entry objects. You can create a string control variable by calling the function tk.StringVar().
You want to create the variable when you initialize your UI, so in your start() method:
# CREATE A TEXTBOX
self.filepath = tkinter.StringVar() # This will hold the value of self.filelocation
# We set it to the "textvariable" option of the new entry
self.filelocation = tkinter.Entry(self.master, textvariable=self.filepath)
self.filelocation["width"] = 60
self.filelocation.focus_set()
self.filelocation.grid(row=1, column=0)
Now when we want to retrieve the value of it we use the get() method. In your start_processing() method:
# Here it opens the file, but you may want to do something else
mbox = open(self.filepath.get(),'r')
The way you set the value in your browse_file() method can be updated to use the control variable quite easily. Instead of inserting into the entry box directly, we'll set the value of our control variable and it will automatically update in the text entry field. In browse_file():
# this will set the text of the self.filelocation
self.filepath.set( self.filename )
Now you can properly set and retrieve the value of self.filelocation the intended way. You can change the name of self.filepath to whatever you want, of course.
For more information:
Tkinter 8.5 Reference - Control Variables
TkDocs - Tk Tutorial - Basic Widgets - Entry
I don't know for certain if mbox is supposed to be an open file, a list, a tuple, or some custom object. I'm going to assume it's an open file, since you have a function to pick a filename.
If that's the case, all you need to do is call the get method of the entry widget to get whatever the user typed:
mbox_name = self.filelocation.get()
mbox = open(mbox_name, "r")
for msg in mbox:
...

Categories