Reputation: 257
With the help of following code I am inserting the filename (file basename) in the tkinter Text widget and subsequently then trying to print the complete file path after the "Get Data" button is pressed.
import tkinter as tk
from tkinter.filedialog import askopenfilename
import os
root=tk.Tk()
ent=tk.Text(root)
ent.grid(row=1,column=0)
def addfile():
filename =askopenfilename(filetypes=(("Tiff files","*.tif"),("All files","*.*")))
ent.insert(tk.INSERT, '"' + os.path.basename(filename) + '"')
ent.insert(tk.INSERT, "\n")
def getfile():
print(ent.get("1.0", tk.END))
b=tk.Button(root,text="Select File",command=addfile)
b.grid(row=0,column=0)
b1 = tk.Button(root,text="Get Data",command=getfile)
b1.grid(row=2,column=0)
root.mainloop()
After running the above code only filenames are getting printed (without filepath).
Now basically what I want is that, after the "Get Data" button is pressed (where the contents of Text widget is read) then complete path of files should be printed.
Additional information:-
I know that if filenames would have been different then I could have used dictionary (key, value) pair to link basename of each file with its absolute path. But issue will come when different files present in different folder location but having same names are added to the Text widget.
Upvotes: 0
Views: 186
Reputation: 169
I will split my code up to try and explain what i've done.
The first 4 functions are to do the addfile():
plus the other thing you have asked for.
split_filename(path):
does what the fuction name says. It will take the path entered and create a list of the individual parts of the the path. (i.e. if you have D:/folder/example/help/test.tif
it would return ['D:/', 'folder', 'example', 'help', 'test.tif']
, you will see later that this is useful when you have 2 basenames that are the same.def split_filename(path):
allParts = []
while 1:
parts = os.path.split(path)
if parts[0] == path:
allParts.insert(0, parts[0])
break
elif parts[1] == path:
allParts.insert(0, parts[1])
break
else:
path = parts[0]
allParts.insert(0, parts[1])
return allParts
check_if_fileBasename_in_current_content(current_content, selected_file_basename):
again the function name tells you exactly what is does. This checks if the new selected file basename is already in the Text
widget.def check_if_fileBasename_in_current_content(current_content, selected_file_basename):
for line in current_content:
if line == '':
pass
elif line == selected_file_basename:
return True
if_true_split_path_for_basename(selected_file_path, selected_file_basename):
is called if the new selected file basename already exists in the Text
widget. The fuction takes the path for both the new selected file and the 1 already saved. If you have 2 files: D:/example1/help.tif
(new selected) and D:/example2/help.tif
(previously added) the new selected basename would become example2/help.tif
instead of just help.tif
. By doing this it makes it possible to distiquish the difference between the 2 files. At the end of the fuction the basename created thought the fuction is inserted into ent
and added to the dictionary dict_of_filenames
(this become useful when printing the paths when b1
is clicked.)def if_true_split_path_for_baseline(selected_file_path, selected_file_basename):
basename_for_text_widget = []
if selected_file_path in dict_of_filenames:
pass
else:
for path, basename in dict_of_filenames.items():
if basename == selected_file_basename:
duplicate_path_split = split_filename(path)
selected_file_path_split = split_filename(selected_file_path)
for i in range(len(selected_file_path_split)):
duplicate_slice = duplicate_path_split[-(i + 1)]
selected_slice = selected_file_path_split[-(i + 1)]
if duplicate_slice == selected_slice:
basename_for_text_widget.insert(0, selected_slice)
else:
basename_for_text_widget.insert(0, selected_slice)
break
ent.insert(tk.INSERT, str('/'.join(basename_for_text_widget) + '\n'))
dict_of_filenames.update({selected_file_path: '/'.join(basename_for_text_widget)})
addFile()
link all of the functions above, it: ask for a file; get the basename; get all of the current text is in the Text
widget; checks if the basename already exists and if so call fuction 3 (above), and finally if it is a new basename it inserts the basename to ent
and adds both path and basename to the dictionary.def addFile():
selected_file_path = askopenfilename(filetypes=(("Tiff files", "*.tif"), ("All files", "*.*")))
selected_file_basename = os.path.basename(selected_file_path)
current_content = ent.get("1.0", tk.END).splitlines()
check1 = check_if_fileBasename_in_current_content(current_content, selected_file_basename)
basename_for_text_widget = []
if check1:
if_true_split_path_for_baseline(selected_file_path, selected_file_basename)
else:
basename_for_text_widget.append(selected_file_basename)
dict_of_filenames.update({selected_file_path: ''.join(basename_for_text_widget)})
ent.insert(tk.INSERT, str(' '.join(basename_for_text_widget) + '\n'))
Next is the getFile():
takes the the content of ent
and then takes the basename and prints the corresponding path.
def getFile():
current_content = ent.get(1.0, tk.END).splitlines()
for path, basename in dict_of_filenames.items():
if basename in current_content:
print(path)
The final change you need to do is to create the global dictionary
by adding dict_of_filename = {}
Insert below the def getFile():
fuction, with no indentation like the Text
and Button
variables
Everything else stays as is.
Upvotes: 0
Reputation: 169
As Cool Cloud has commented it is hard to give the exact answer you need, because you havent told us what is happening and what you expect/what to happen.
The way I read it is that you either want:
askopenfilename()
to be inserted in the Text
widget.Button
b1
, but the Text
widget to be left as is.1. I would change def addfile():
to
def addfile():
filename = askopenfilename()
ent.insert(tk.INSERT, '"' + filename + '"\n')
What this does is inserts the full file path rather than just the basename, i.e. it would insert "D:/example/help.tif"
rather than just help.tif
.
2. I would use the code below
root = tk.Tk()
def addfile():
filename = askopenfilename()
list_of_filenames.append(filename)
ent.insert(tk.INSERT, '"' + os.path.basename(filename) + '"\n')
def getfile():
for i in range(len(list_of_filenames)):
print(list_of_filesnames[i])
list_of_filenames = []
ent = tk.Text(root)
ent.grid(row=1, column=0)
b=tk.Button(root,text="Select File",command=addfile)
b.grid(row=0,column=0)
b1 = tk.Button(root,text="Get Data",command=getfile)
b1.grid(row=2,column=0)
root.mainloop()
What I have done is create a global list variable named list_of_filenames
and in def addfile():
I added the line list_of_filenames.append(filename)
, this takes the file you selected, and the path, and add it to the list variable. Thus giving you a list with every file you select, and it can be accessed by any function you build because it is global.
The final change is to def getfile():
this can be done exactly how you would like to, I have written it to print each of the files individually on a seperate lines, without square brackets or quotation marks.
Using the same example as in part 1, if I selected a file with the path D:/example/help.tif
the Text
widget would read "help.tif" and when b1
is clicked D:/example/help.tif
would be printed to the consol.
Upvotes: 1