How can I get number of files uploaded in tkinter Python - python

I currently have this tkintr application that would allow you to upload a file or multiple files. I would like to be able to print to the console how many files were selected.
Currently I can only print what the files selected are with print self.uploadedfilenames
I tried to do len(self.uploadedfilenames) but I got a number of 52 for one file which I do not understand what it is
#!/usr/bin/env python
from Tkinter import *
import tkFileDialog
import tkMessageBox
class Application(object):
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.file_opt = options = {}
options['defaultextension'] = '.txt'
options['filetypes'] = [('all files', '.*'), ('text files', '.txt')]
options['initialdir'] = 'C:\\'
options['initialfile'] = 'myfile.txt'
options['parent'] = master
options['title'] = 'This is a title'
#UPLOAD SECTION
Label(frame, text='Upload: ').grid(row=1, column=1)
self.upload = Button(frame, text = "Browse", command = self.askopenfile, width = 10).grid(row=1, column=2)
def askopenfile(self):
self.uploadedfilenames = tkFileDialog.askopenfilenames(multiple=True)
if self.uploadedfilenames == '':
tkMessageBox.showinfo(message="No file was selected")
return
else:
print len(self.uploadedfilenames)
root = Tk()
root.title('application')
_ = Application(root)
root.mainloop()
Is there a way to find out how many files there is ?

The length you see is because it does not return a tuple as expected, but returns a string instead. This is due to a Windows error.
When I test your code on my PC everything is fine.
Please have a look here:
Parsing the results of askopenfilenames()?
Also, when you have issues like this, simply print
self.uploadedfilenames
Then you can see what is returned. That would have helped you out I think.

Related

Merging Files in Tkinter Search Files Application

I am trying to build a simple application using Tkinter wherein I should be able to search files in my local folders and display them. For example, if I am searching a 'test.txt' file, it will return me that file plus all txt files. Now the second part of the problem is, I have to merge all the files that was returned to me in my search into one single file (I know it sounds absurd but please forgive me). I have successfully achieved the first part but not able to implement the second part. Quite new to functions and OOPs concepts. Pasting my code below in the hope for some guidance. Please forgive me for the code quality as I am quite new.
import pandas as pd
from tkinter import *
import os
from docx import Document
doc1 = Document()
def search_file():
file_entry_name = entry.get()
answer.delete(1.0,END)
extension = file_entry_name.split('.')[1]
file_name = file_entry_name.split('.')[0]
file_entry_name = file_entry_name.lower()
for r,d,f in os.walk('/Users/kausthab/Documents/Documents – Kausthab’s MacBook Air/DSBA'):
for file in f:
file.split()
if file.startswith(file_entry_name) or file.endswith(extension):
answer.insert(INSERT,file + '\n')
def merge_file():
# files = os.listdir('/Users/kausthab/Documents/Documents – Kausthab’s MacBook Air/DSBA')
# global answer
# for i in answer:
# if i != '.DS_Store': # i kept getting an error for a hidden file. So excluded it
# doc1.add_heading(i, 2)
# doc2 = Document(i)
# for para in doc2.paragraphs:
# para_in_doc = doc1.add_paragraph(para.text)
# doc1.add_page_break()
# doc1.save('search.docx')
return
root = Tk()
root.title('Docu Search')
topframe = Frame(root)
entry = Entry(topframe)
entry.pack()
button = Button(topframe, text="search",command =search_file)
button.pack()
topframe.pack(side = TOP)
bottomframe = Frame(root)
scroll = Scrollbar(bottomframe)
scroll.pack(side=RIGHT, fill=Y)
answer = Text(bottomframe, width=80, height=50, yscrollcommand = scroll.set,wrap= WORD)
scroll.config(command=answer.yview)
merge_button = Button(bottomframe, text="merge",command =merge_file)
merge_button.pack()
answer.pack()
bottomframe.pack()
root.mainloop()

Problem creating a simple tkinter GUI that displays names of text files from a folder and their contents when clicked

I have been trying to develop a GUI for my python based voice assistant. The following is a snippet of the code that I am having problem with.What I want to do is display the name of text files from a folder and display their contents in the same window when the user clicks on one of the file names.
from tkinter import *
import os
menu_color = "#2c2b34"
frame_color = "#28262e"
font_color = "#06dff5"
ss_f_button = []
note_f_button = []
note_text = None
def note_window(): #To operate Note Window
global note_f_button
path = os.path.join(sys.path[0], "Notes/")
note_files = [f for f in os.listdir(path)]
note_f_button = []
if len(note_files)>0:
y=60
for i in range(len(note_files)):
note_f_button.append(Button(root, bg=frame_color, fg=font_color, activebackground=frame_color, activeforeground=font_color, bd ="0", text=note_files[i], font=("Helvetica Neue Bold", "10"), cursor="hand2", command=lambda: open_note(note_files[i])))
note_f_button[i].place(x=55, y=y)
y+=40
root.update()
def open_note(f_name): #To operate Note Window
global note_text
if note_text != None:
note_text.place_forget()
note_text = None
path = os.path.join(sys.path[0], "Notes/")
with open(f"{path}{f_name}", "r") as file:
note_text = file.read()
note_text = Label(root, text=note_text, bg=frame_color, fg=font_color, font=("Helvetica Neue Bold", "11"))
note_text.place(x=340, y=60)
root.update()
root = Tk()
root.title("TEST")
root.geometry("706x462")
note_window()
root.update()
root.mainloop()
Here is the output:
You would understand it best if you run it yourself!! If you try this code, be sure to change the font style as Helvetica may not be installed in your system!!
The problem I am facing is that both the files show the same text when clicked, or more specifically, both of them show the same text from the test.txt file.Can anyone please provide a way to do what I am trying to achieve and also point out where I am doing it wrong.I am using Python 3.8.3.

Tkinter updating label after using pyinstaller

When I run the .py file, the program runs fine as in self.error updates as robocopy is running. However after I've changed it to a .exe file using pyinstaller -F -w Shortcutsv2.1.py I've noticed that the tkinter label which shows how many files it has updated (self.error) doesn't update until after the terminal is closed. Is there a way to have it work like the script? I'm assuming this is due to a setting in pyinstaller but I may be wrong
CODE:
from subprocess import PIPE, run
import tkinter as tk
from tkinter import ttk
import tkinter.messagebox as mb
import tkinter.font as tkFont
from os import path
from os import listdir
from os import mkdir
from os import walk
from glob import glob
import threading
import pandas as pd
from datetime import datetime
class Windows(threading.Thread):
def __init__(self, master):
threading.Thread.__init__(self)
self.width = 400
self.height = 150
master.geometry(f"{self.width}x{self.height}")
master.title("Shortcuts")
#master.iconbitmap(r'ip.ico')
self.frame = tk.Frame(master,bg="white")
self.frame.place(relx=0, rely=0, relwidth=1, relheight=1)
self.font = ('Helvetica', '10')
#Source path label and text entry
self.srcLabel = tk.Label(self.frame, text="Source Path:", font=self.font, bg="white")
self.srcLabel.place(relx=0.001, rely=0.026, relwidth=0.31, relheight=0.2)
self.srcEntry = tk.Entry(self.frame, font=self.font, bg="white")
self.srcEntry.place(relx=0.31, rely=0.026, relwidth=0.68, relheight=0.2)
#Destination path label and text entry
self.dstLabel = tk.Label(self.frame, text="Destination Path:", font=self.font, bg="white")
self.dstLabel.place(relx=0.001, rely=0.246, relwidth=0.31, relheight=0.2)
self.dstEntry = tk.Entry(self.frame, font=self.font, bg="white")
self.dstEntry.place(relx=0.31, rely=0.246, relwidth=0.68, relheight=0.2)
#New Folder to be created label and text entry
self.nfLabel = tk.Label(self.frame, text="New Folder:", font=self.font, bg="white")
self.nfLabel.place(relx=0.001, rely=0.466, relwidth=0.31, relheight=0.2)
self.nfEntry = tk.Entry(self.frame, font=self.font, bg="white")
self.nfEntry.place(relx=0.31, rely=0.466, relwidth=0.68, relheight=0.2)
#Submit
self.submit = tk.Button(self.frame, text="Submit", bg="white", font=self.font,
command = self.threadCmd)
self.submit.place(relx=0.5, rely=0.733, relwidth=0.3, relheight=0.2)
#Errors
self.error = tk.Label(self.frame, text="", font=self.font, bg="white", fg="red")
self.error.place(relx=0.001, rely=0.733, relwidth=0.53, relheight=0.2)
def findFile(self, dirPath):
#finds the full path of all files including within the subdirectories
i = 0
temp = []
filesInDir = [f"{dirPath}\\{a}" for a in listdir(dirPath)]
for a in filesInDir:
i += 1
fullPath = path.join(dirPath, a)
if path.isdir(fullPath):
temp = temp + self.findFile(fullPath)
else:
temp.append(fullPath)
return temp
def lowestFolder(self, direc):
#finds the lowest last folder if any and creates the ~~~~.txt in there to ensure it is the last file to be copied
subdir = [x[0] for x in walk(direc)]
subdir.sort()
if subdir[-1] == direc:
f = open(path.join(direc,"~~~~.txt"),"w+")
f.close()
else:
self.lowestFolder(str(path.join(direc,subdir[-1])))
def Run(self):
if not path.exists(self.srcEntry.get()):
self.error.config(text="Can't find src path", fg="red")
elif not path.exists(self.dstEntry.get()):
self.error.config(text="Can't find dstn path", fg="red")
else:
dest = self.dstEntry.get() + "\\" + self.nfEntry.get()
if path.isdir(dest):
self.error.config(text="Folder Exists", fg="red")
else:
self.error.config(text="")
self.filename = "logs.xlsx"
self.listOfFiles = glob(path.join(".",self.filename))
self.lowestFolder(self.srcEntry.get())
filesTransferred = self.findFile(self.srcEntry.get())
length = len(filesTransferred)
mkdir(dest)
date = datetime.now()
run(f"start cmd /K RoboCopy.exe \"{self.srcEntry.get()}\" \"{dest}\" *.* /E /Z", stdout=PIPE, stdin=PIPE, stderr=PIPE, shell=True)
#Checks if all files have been transferred before moving on
i = 0
while(i < length):
fullPath = filesTransferred[i].replace(self.srcEntry.get(), dest)
if path.exists(fullPath):
i += 1
self.error.config(text=f'Transferring file(s): {i}/{length}', fg='black')
temp2 = self.findFile(dest)
temp2 = [x.replace(dest, "..") for x in temp2]
if length == len(temp2):
#Creates log file if not created
if not self.listOfFiles:
writer = pd.ExcelWriter(self.filename, engine='xlsxwriter')
writer.save()
df = pd.read_excel(self.filename)
#creates file if it doesn't exist else apppends
df2 = pd.DataFrame({"Started" : [date],
"Source": [self.srcEntry.get()],
"Destination": [self.dstEntry.get()],
"Files": [", ".join(temp2)]})
df = df.append(df2, sort=False)
df.to_excel(self.filename, index=False)
self.error.config(text="Files copied successfully.", fg="green")
#IF ROBOCOPY FREEZES WHEN YOU CLICK ON IT THEN JUST PRESS TAB AND IT SHOULD RESUME
else:
self.error.config(text="All files were not copied.", fg="red")
def threadCmd(self):
self.result = None
y = threading.Thread(target=self.Run)
y.start()
if __name__ == "__main__":
root = tk.Tk()
x = threading.Thread(target=Windows, args=(root,))
x.start()
x.join
root.mainloop()
EDIT 1
"There are couple problems here. 1. Inherit class Windows(threading.Thread): but don't use this object. 2. Passing a class definition as .Thread(target=Windows. 3. Useless x.join without calling it. 4. Accessing tkinter objects, e.g.self.srcEntry.get(), from a Thread."
I've changed the code to the below so now:
1) Can't make this change as I'm using .start()
2) Changed this to an instance
3) called the function
4) Didn't make this change as wasn't sure what the issue was. Needs more clarification
The issue which I had posted for still persists however I appreciate the help to tidy up my code :)
if __name__ == "__main__":
root = tk.Tk()
x = Windows(root)
x.start()
x.join()
root.mainloop()
I was using subprocess.run instead of subprocess.Popen, subprocess.run waits for the terminal command to complete before moving on with the script. Whereas subprocess.Popen doesn't.
Edit: What I find strange is that when I would run it as a .py file subprocess.run worked the same as subprocess.Popen however when I had used pyinstaller then subprocess.run worked how it's supposed to.

How to retrieve file name after choosing in dialog box using Python Tkinter

Please advise on how to retrieve a file's full path into a variable after i pick one using tkinter
The whole idea of my GUI is to:
1. Have few buttions
2. Have address bar with file's full address
Once user clicks the button and picks the file >> file's path is displayed in the address bar as well as stored in a separate variable for future usage later in code
I've done some testing, but when checking for retrieved value - I get None.
def file_picker():
"""Pick enova .xlsx file"""
path = filedialog.askopenfilename(filetypes=(('Excel Documents', '*.xlsx'), ('All Files', '*.*')))
return path
file_button = tkinter.Button(root, text='Users File', width=20, height=3,
bg='white', command=custom_functions.file_picker).place(x=30, y=50)
Apart form that I found another code snippet, but this simply captures line onto the GUI interface, not saving file path in any variable though:
def browsefunc():
filename = filedialog.askopenfilename()
pathlabel.config(text=filename)
print(pathlabel)
browsebutton = tkinter.Button(root, text="Browse", command=browsefunc).pack()
pathlabel = tkinter.Label(root).pack()
Expected result: https://imgur.com/a/NbiOPzG - unfortunatelly I cannot post images yet so uploaded one onto imgur
To capture the full path of a file using Tkinter you can do the following. The output of your full file path will be displayed in the "Entry" field / your address bar as per your requirement in your original post.
Update
import tkinter
from tkinter import ttk, StringVar
from tkinter.filedialog import askopenfilename
class GUI:
def __init__(self, window):
# 'StringVar()' is used to get the instance of input field
self.input_text = StringVar()
self.input_text1 = StringVar()
self.path = ''
self.path1 = ''
window.title("Request Notifier")
window.resizable(0, 0) # this prevents from resizing the window
window.geometry("700x300")
ttk.Button(window, text = "Users File", command = lambda: self.set_path_users_field()).grid(row = 0, ipadx=5, ipady=15) # this is placed in 0 0
ttk.Entry(window, textvariable = self.input_text, width = 70).grid( row = 0, column = 1, ipadx=1, ipady=1) # this is placed in 0 1
ttk.Button(window, text = "Enova File", command = lambda: self.set_path_Enova_field()).grid(row = 1, ipadx=5, ipady=15) # this is placed in 0 0
ttk.Entry(window, textvariable = self.input_text1, width = 70).grid( row = 1, column = 1, ipadx=1, ipady=1) # this is placed in 0 1
ttk.Button(window, text = "Send Notifications").grid(row = 2, ipadx=5, ipady=15) # this is placed in 0 0
def set_path_users_field(self):
self.path = askopenfilename()
self.input_text.set(self.path)
def set_path_Enova_field(self):
self.path1 = askopenfilename()
self.input_text1.set(self.path1)
def get_user_path(self):
""" Function provides the Users full file path."""
return self.path
def get_enova_path1(self):
"""Function provides the Enova full file path."""
return self.path1
if __name__ == '__main__':
window = tkinter.Tk()
gui = GUI(window)
window.mainloop()
# Extracting the full file path for re-use. Two ways to accomplish this task is below.
print(gui.path, '\n', gui.path1)
print(gui.get_user_path(), '\n', gui.get_enova_path1())
Note: I added a comment to point you to where the full file path is stored, in my example it's 'path' & 'path1'.

Using Tkinter to create a GUI that creates a folder and unwrap a ZIP file

Hello fellow programmers,
Im trying to make a GUI with Tkinter. This is the first time that Ive used Tkinter, and Ive run into some issues. The script and GUI should do the following:
Ask user (via entry and 'ok' button) to enter the name of the working folder. Result -> Create the newly made folder on the desktop of the system.
Select an OWL file (which is a zip-file) via TkFileDialog.
Result -> unwrap the selected zip-file in the folder that has been created in step 1.
The script Ive written so-far using online tutorials:
import Tkinter
import Tkconstants
import tkFileDialog
import zipfile
from Tkinter import *
import os
class TkFileDialogExample(Tkinter.Frame):
def __init__(self, root):
Tkinter.Frame.__init__(self, root)
root.configure(background='lightgrey')
root.wm_title("Audit tool: Thickness of pavement")
root.geometry('{}x{}'.format(500, 500))
Label_1 = Message(root, text="Step 1. Please fill in the name of the output folder and click on 'create'. The output folder will be created in the desktop folder:", width=380,)
Label_1.grid(row=1, columnspan=5)
Entry1 = Entry(root)
Entry1.grid(row=2, sticky=E)
folder_location = '~/Desktop/' + Entry1.get()
def createname():
return os.mkdir(os.path.expanduser(folder_location))
button_1 = Button(root, text="Create", command=createname)
button_1.grid(row=2, column =1, sticky=W)
Label_3 = Message(root, text="Step 2. Please select the OWL file:", width=300,)
Label_3.grid(row=5, sticky=W)
button_2 = Button(self, text='Click here to select the OWL file', command=self.askopenfilename)
button_2.grid(row=4,column=1, sticky=W)
self.file_opt = options = {}
options['defaultextension'] = '.owl'
options['filetypes'] = [('all files', '.*'), ('owl files', '.owl')]
options['initialdir'] = 'C:\\'
options['initialfile'] = 'Title_of_OWL-file.ccr'
options['parent'] = root
options['title'] = 'This is a title'
self.dir_opt = options = {}
options['initialdir'] = 'C:\\'
options['mustexist'] = False
options['parent'] = root
def askopenfile(self):
return tkFileDialog.askopenfile(mode='r', **self.file_opt)
def askopenfilename(self):
filename = tkFileDialog.askopenfilename(**self.file_opt)
zip_ref = zipfile.ZipFile(filename, 'r')
if filename:
return zip_ref.extractall(folder_location)
if __name__=='__main__':
root = Tkinter.Tk()
TkFileDialogExample(root).grid()
root.mainloop()
The problem probably lies within the third use of 'folder_location'. Since I am relatively new to the Python language, I cannot seem to find a solution to this problem.
Thank you for your help and time!
Yours truly,
Ruben van der Heijden
The issue is that you have defined the variable folder_location only in the local scope of your TkFileDialogExample.__init__ method. As a result, it is not accessible to any of the other methods of your class. If you do want it to be accessible, then you'll want to set it as an attribute of your class using the self keyword.
def __init__(self, root):
# Stuff
self.folder_location = os.path.join('~', 'Desktop', Entry1.get())
Then you can access it from your TkFileDialogExample.askopenfilename method:
def askopenfilename(self):
filename = tkFileDialog.askopenfilename(**self.file_opt)
zip_ref = zipfile.ZipFile(filename, 'r')
if filename:
return zip_ref.extractall(self.folder_location)
Side Note: In general, it is best to use os.path.join to construct file paths from strings.

Categories

Resources