I'm building a simple application with Tkinter that has two browse buttons. One needs to be able to target a file and the other one only a folder. This works, but when I browse using either one button, it fills both of the entries. I'm new to Tkinter so I don't really understand why.
I'm using code from this question:
How to Show File Path with Browse Button in Python / Tkinter
This is my browse function:
def open_file(type):
global content
global file_path
global full_path
if type == "file":
filename = askopenfilename()
infile = open(filename, 'r')
content = infile.read()
file_path = os.path.dirname(filename)
entry.delete(0, END)
entry.insert(0, file_path+filename)
return content
elif type == "path":
full_path = askdirectory()
entry2.delete(0, END)
entry2.insert(0, full_path)
#return content
And this is my GUI code:
mf = Frame(root)
mf.pack()
f1 = Frame(mf, width=600, height=250)
f1.pack(fill=X)
f2 = Frame(mf, width=600, height=250)
f2.pack(fill=X)
Label(f1, text="Select Your File (Only txt files)").grid(row=0, column=0, sticky='e')
Label(f2, text="Select target folder").grid(row=0, column=0, sticky='e')
entry = Entry(f1, width=50, textvariable=file_path)
entry2 = Entry(f2, width=50, textvariable=full_path)
entry.grid(row=0, column=1, padx=2, pady=2, sticky='we', columnspan=25)
entry2.grid(row=0, column=1, padx=(67, 2), pady=2, sticky='we', columnspan=25)
Button(f1, text="Browse", command=lambda: open_file("file")).grid(row=0, column=27, sticky='ew', padx=8, pady=4)
Button(f2, text="Browse", command=lambda: open_file("path")).grid(row=0, column=27, sticky='ew', padx=8, pady=4)
How can I solve this problem? Thanks
Notice that the full_path (local variable in open_file method) has the same name as the global varibale.
You should use StringVar for text variables.
Change the initialization of both the file_path and full_path
global file_path
global full_path
file_path = StringVar()
full_path = StringVar()
Instead of those line:
entry.delete(0, END)
entry.insert(0, file_path+filename)
You can simply write:
full_path.set(file_path+filename)
Same with entry2, instead of:
elif type == "path":
full_path = askdirectory()
entry2.delete(0, END)
entry2.insert(0, full_path)
Write:
elif type == "path":
full_path_dir = askdirectory()
full_path.set(full_path_dir)
Related
I created a GUI.
It is working fine.
This is the code.
# Run A TKinter Application Script
#Create Window
window=Tk()
window["bg"] = "gray"
window.title('SPS Automation App')
window.geometry('500x250')
def browse_files():
global filename
filename = filedialog.askopenfilename()
filename = '\"' + filename + '\"'
print(filename)
label2 = Label(window)
if len(str(filename)) > 3:
label2['text'] = filename
else:
label2['text'] = 'You didn\'t upload any file yet.'
label2.grid(column=2, row=1, sticky=E, padx=5, pady=5)
def run():
os.system('python Test6.py ' + filename)
#os.system('python Old_Test.py')
#subprocess.call(['python','Test6.py', filename])
#print('python Test6.py ' + filename)
label3 = Label(window)
label3['text'] = 'Success!'
#def run2():
# os.system('python concatenateOBM.py)
Button1 = Button(window, text='Upload SPS', fg='black', bg='white', height = 2, width = 19, command=browse_files)
Button1.grid(column=1, row=1, sticky=E, padx=5, pady=5)
Button2 = Button(window, text='Create OBM', fg='green', bg='white', height = 2, width = 19, command=run)
Button2.grid(column=1, row=4, sticky=E, padx=5, pady=5)
#Button3 = Button(window, text='Convert multiple OBMs to 1 OBM', fg='green', bg='white', height = 2, width = 19, command=run2)
#Button3.grid(column=1, row=4, sticky=E, padx=5, pady=5)
window.mainloop()
But then I create a executable by running:
pyinstaller GUI.py --noconsole
It creates all folders without error, I then go to dist folder and double click the .exe file, it starts loading, stops and nothing happens.
Why is it not working?
It looks like the problem lies here os.system('python Test6.py ' + filename) are you sure that the file Test6.py is in the same directory as the GUI executable?
I have a GUI text editor i made with tkinter. It currently opens, saves and clears the screen. I have added an encrypt and decrypt button and will eventually apply the ceasar cipher to whatever text is on the screen.
For my encrypt button i so far have
def encrypt():
text = editor.get(1.0, tk.END)
encryptList = []
for word in text:
encryptList.append(word)
random.shuffle(encryptList)
return encryptList
What i am trying to have happen is to shuffle the text on my screen from whatever i have on there (im using a test file with "Test" printed a bunch of times) After I'm able to do this I can implement a cesar cipher to the text on the screen. (I hope)
whole code:
#Import Module
import random
import tkinter as tk
from tkinter.filedialog import askopenfilename, asksaveasfilename
from tkinter import ttk
#Create Function for New File Button
def fileNew():
editor.delete(1.0, tk.END)
#Create Function For Open File Button
def fileOpen():
editor.delete(1.0, tk.END)
filepath = askopenfilename(filetypes=[("Text Files", "*.txt"), ("All Files", "*.*")])
with open(filepath, "r") as file:
text = file.read()
editor.insert(tk.END, text)
def encrypt():
text = editor.get(1.0, tk.END)
encryptList = []
for word in text:
encryptList.append(word)
random.shuffle(encryptList)
return encryptList
#Create Function For Save File Button
def fileSave():
save = asksaveasfilename(defaultextension=".*", filetypes=[("Text Files", "*.txt"), ("All Files", "*.*")])
if not save:
return
with open(save, "w") as fileOutput:
text = editor.get(1.0, tk.END)
fileOutput.write(text)
#GUI
root = tk.Tk()
root.rowconfigure(0, minsize=500, weight=1)
root.columnconfigure(1, minsize=800, weight=1)
#Title
root.title()
#Text Editor
editor = tk.Text(root)
editor.configure(background="#263D42")
editor.grid(row=0, column=1, sticky="nsew")
#Scrollbar
scrollbar = ttk.Scrollbar(root, orient='vertical', command=editor.yview)
scrollbar.grid(row=0, column=2, sticky='ns')
#Left Side Panel
sidePanel = tk.Frame(root)
sidePanel.configure(background="#232e3a")
sidePanel.grid(row=0, column=0, sticky="ns")
#Open File Button
btn_open = tk.Button(sidePanel, text="Open", command=fileOpen)
btn_open.configure(background="#867c91")
btn_open.grid(row=0, column=0, sticky="ew", padx=5, pady=5)
#New File Button
btn_new = tk.Button(sidePanel, text="New", command=fileNew)
btn_new.configure(background="#867c91")
btn_new.grid(row=1, column=0, sticky="ew", padx=5, pady=5)
#Encrypt File Button
btn_open = tk.Button(sidePanel, text="Encrypt", command=encrypt)
btn_open.configure(background="#867c91")
btn_open.grid(row=2, column=0, sticky="ew", padx=5, pady=5)
#Decrypt File Button
btn_open = tk.Button(sidePanel, text="Decrypt")
btn_open.configure(background="#867c91")
btn_open.grid(row=3, column=0, sticky="ew", padx=5, pady=5)
#Save Button
btn_saveas = tk.Button(sidePanel, text="Save As", command=fileSave)
btn_saveas.configure(background="#867c91")
btn_saveas.grid(row=4, column=0, sticky="ew", padx=5, pady=5)
root.mainloop()
Closed. I figured it out
def encrypt():
text = editor.get(1.0, tk.END)
encryptList = []
for word in text:
encryptList.append(word)
random.shuffle(encryptList)
needed to add
editor.delete(1.0, tk.END)
editor.insert(tk.END, encryptList)
When pressing "Ping test" you get a new 'main window' with input and submit button.
when Submit is clicked, a file is created on the desktop and writes the output result of ping command.
right now, when I enter an address and click submit, I only see the menu frame and the main frame, the output frame shows up when the proccess is finished.
how can I make the output frame show "Pinging..." when I click the Submit button and update the label to "Ping Complete!" when its finished?
here's my code:
import tkinter as tk
import subprocess as sub
import easygui
import os
root = tk.Tk()
root.geometry("400x300")
# ===== Frame 1 - Left Menu =====
frame = tk.LabelFrame(root, text="Menu",height=80, width=40,
padx=5, pady=5, relief="solid")
frame.place(x=10, y=0)
# Show files button
showfilesButton = tk.Button(frame, text="Show Files", padx=5, pady=5,
command=lambda: showFiles())
showfilesButton.grid(row=1, column=0)
# ConvertURL button
convertURL = tk.Button(frame, text="Ping Test", padx=5, pady=5,
command=lambda: testPing.getURL())
convertURL.grid(row=2, column=0)
# Quit Button
endProgram = tk.Button(frame, text="Quit", padx=5, pady=5,
command=lambda: terminate())
endProgram.grid(row=3, column=0)
class testPing():
def __init__(self, host):
self.host = host
self.clearFile = clearFile
self.label = label
def getURL():
frame2 = tk.LabelFrame(root, text="Main Window", height=350, width=300, padx=30, pady=30)
frame2.pack()
urlLabel = tk.Label(frame2, text="Enter URL : ", padx=5, pady=5)
urlLabel.place(x=-30, y=-30)
urlInputBox = tk.Entry(frame2)
urlInputBox.pack()
clearLabel = tk.Label(frame2, text="Clear File?", padx=5, pady=5)
clearLabel.place(x=-30, y=20)
clearFile = tk.BooleanVar()
clearFile.set(False)
clearFileRadioYes = tk.Radiobutton(frame2, text="yes", value=True, var=clearFile,
command=lambda: testPing.callback(clearFile.get()))
clearFileRadioYes.place(x=-30, y=45)
clearFileRadioNo = tk.Radiobutton(frame2, text="no", value=False, var=clearFile,
command=lambda: testPing.callback(clearFile.get()))
clearFileRadioNo.place(x=20, y=45)
urlSubmitButton = tk.Button(frame2, text="Submit",
command=lambda: testPing.pingURL(urlInputBox.get(), clearFile.get()))
urlSubmitButton.pack(side=tk.RIGHT)
def callback(clearFile):
bul = clearFile
print(bul)
def pingURL(host, clearFile):
outputLabel = tk.LabelFrame(root, text="Output", height=35, width=150,
padx=5, pady=5, relief="solid")
outputLabel.place(x=0, y=150)
file = fr'c:/users/{os.getlogin()}/Desktop/ping.txt'
label = tk.Label(outputLabel, text=f'Pinging {host} ...')
label.grid(row=0, column=0)
clear = clearFile
if clear == True:
with open(file, 'w+') as output:
output.truncate(0)
sub.call(['ping', f'{host}'], stdout=output)
else:
with open(file, 'a') as output:
sub.call(['ping', f'{host}'], stdout=output)
output.close()
# testPing.changeLabel(host)
def changeLabel(host):
myLabel = tk.Label.config(text=f"Ping to {host} Complete!")
myLabel.pack()
def terminate():
exit()
def showFiles():
path = easygui.diropenbox() # Opens a folder dialog box.
folder = path
filelocation = f"c:\\Users\\{os.getlogin()}\\Desktop\\showFilesResult.txt"
filenames = os.listdir(folder) # Get the file names in the folder.
# Writing to file
with open(filelocation, 'a') as file:
for name in filenames:
file.write(f"Name: {name}\nFolder Path: {folder}\n!------------------------------!\n")
print("Done!")
root.mainloop()
Instead of calling changeLabel(), you can simply put:
output.close()
label.configure(text=f'Ping to {host} complete!')
# testPing.changeLabel(host)
But remember about updating your label first, if you don't at the end only complete label will be visible.
label = tk.Label(outputLabel, text=f'Pinging {host} ...')
label.grid(row=0, column=0)
label.update()
An additional tip, don't use different GUI creators in one project. If you only using easygui to get the path, check Tkinter methods -> askopenfilename and asksaveasfilename.
I just cant make this load button work so that it loads the output.txt file to my listbox. im a first year 160 student with no background in coding and im trying to make this silly phone book as my first "big project" just to get kinda of an idea of what im doing and ive got everything else working besides the loading feature of my output.txt file. forgive my horrible coding im sure it could be a million times better xd
from tkinter import *
win = Tk()
def delete():
select=listbox.curselection()
index=select[0]
listbox.delete(index)
def returnEntry(arg=None):
fname = e1.get()
lname = e2.get()
number = e3.get()
listbox.insert(END, fname+ ' ' + lname+ ' ' + number)
def save():
list1=list(listbox.get(0,END))
f=open("output.txt", "w")
f.writelines(str(list1))
f.close()
def load():
with open("output.txt", "r") as f:
output=f.read()
Label(win, text="First Name").grid(row=0)
Label(win, text="Last Name").grid(row=1)
Label(win, text="Phone Number").grid(row=2)
resultLabel = Label(win, text = "")
resultLabel.grid(row=4, column=1)
resultLabel1 = Label(win, text = "")
resultLabel1.grid(row=4, column=2)
resultLabel2 = Label(win, text = "")
resultLabel2.grid(row=4, column=3)
fname=StringVar()
e1 = Entry(win, textvariable=fname)
lname=StringVar()
e2 = Entry(win, textvariable=lname)
number=StringVar()
e3 = Entry(win, textvariable=number)
scrollbar=Scrollbar(win, orient=VERTICAL)
listbox=Listbox(win, selectmode=EXTENDED, yscrollcommand=scrollbar.set,width=40)
listbox.grid(row=4, columnspan=3)
scrollbar.config(command=listbox)
b1=Button(win, text="Add", command = returnEntry)
b2=Button(win, text="Delete", command=delete)
b3=Button(win, text="Save", command=save)
b4=Button(win, text="load", command=load)
win.bind("<Return>", returnEntry)
e1.grid(row=0, column=1)
e2.grid(row=1, column=1)
e3.grid(row=2, column=1)
b1.grid(row=3, column=1, sticky=W)
b2.grid(row=3, column=1)
b3.grid(row=3, column=1, sticky=E)
b4.grid(row=3, column=2, sticky=W)
win.mainloop()
Below is code:
import os
from tkinter.filedialog import askopenfilename
from tkinter import *
#~~~~ FUNCTIONS~~~~
def open_file_1():
global file_path_1
filename_1 = askopenfilename()
file_path_1 = os.path.dirname(filename_1) + filename_1
entry_1.delete(0, END)
entry_1.insert(0, file_path_1)
return file_path_1
def open_file_2():
global file_path_2
filename_2 = askopenfilename()
file_path_2 = os.path.dirname(filename_2) + filename_2
entry_3.delete(0, END)
entry_3.insert(0, file_path_2)
return file_path_2
def title_name_1():
global title_1
title_1=str(entry_4.get())
return title_1
def title_name_2():
global title_2
title_2=str(entry_5.get())
return title_2
def process_file(content):
print(file_path_1)
print(file_path_2)
print(title_1)
print(title_2)
#~~~~~~ GUI ~~~~~~~~
root = Tk()
root.title('Test Project')
root.geometry("698x220+350+200")
mf = Frame(root)
mf.pack()
f1 = Frame(mf, width=600, height=250)
f1.pack(fill=X)
f3 = Frame(mf, width=600, height=250)
f3.pack(fill=X)
f4 = Frame(mf, width=600, height=250)
f4.pack(fill=X)
f5 = Frame(mf, width=600, height=250)
f5.pack(fill=X)
f2 = Frame(mf, width=600, height=250)
f2.pack()
file_path_1 = StringVar
file_path_2 = StringVar
title_1 = StringVar
title_2 = StringVar
Label(f1,text="Select File 1").grid(row=0, column=0, sticky='e')
Label(f3,text="Select File 2").grid(row=0, column=0, sticky='e')
Label(f4,text="Title1").grid(row=0, column=0, sticky='e')
Label(f5,text="Title2").grid(row=0, column=0, sticky='e')
entry_1 = Entry(f1, width=50, textvariable=file_path_1)
entry_1.grid(row=0,column=1,padx=2,pady=2,sticky='we',columnspan=25)
Button(f1, text="Browse", command=open_file_1).grid(row=0, column=27, sticky='ew', padx=8, pady=4)
entry_3 = Entry(f3, width=50, textvariable=file_path_2)
entry_3.grid(row=0,column=1,padx=2,pady=2,sticky='we',columnspan=25)
Button(f3, text="Browse", command=open_file_2).grid(row=0, column=27, sticky='ew', padx=8, pady=4)
entry_4 = Entry(f4, width=50,textvariable=title_1)
entry_4.grid(row=0,column=1,padx=5,pady=2,sticky='we',columnspan=25)
entry_5 = Entry(f5, width=50,textvariable=title_2)
entry_5.grid(row=0,column=1,padx=5,pady=2,sticky='we',columnspan=25)
Button(f2, text="Submit", width=32, command=lambda: process_file(content)).grid(sticky='ew', padx=10, pady=70)
root.mainloop()
I want to get these 4 fields(file_path_1, file_path_2, Title1, Title2) and store them so that can be used for further manipulation.I am using Browse to select files and user will enter text for Title1 and Title2.I am new to this, so didn't have much idea.
You are complicating your life unnecessarily by using StringVar(). StringVar's are mostly useful if you attach observer callbacks to them...
Most of the time for Entry widgets, it is better to get their content with the .get() method just before using it:
def process_file():
# Get Entry box content
filename_1 = entry_1.get()
# Do something with it
print(filename_1)