I have three functions; with dirBut the user selects a directory the output of which goes into dirname and updates an Entry box. In the third function, dataInput, the user selects a file. I would like the open file dialog to open in the directory previously selected by the user and defined by dirname, however, I'm not sure how to pass dirname to a handle so I can use it in askopenfilename since askdirectory is called from a button.
def UserFileInput(self,status,name):
row = self.row
optionLabel = tk.Label(self)
optionLabel.grid(row=row, column=0, sticky='w')
optionLabel["text"] = name
text = status
var = tk.StringVar(root)
var.set(text)
w = tk.Entry(self, textvariable= var)
w.grid(row=row, column=1, sticky='ew')
self.row += 1
return w, var
def askdirectory(self):
dirname = tkFileDialog.askdirectory()
if dirname:
self.directoryEntry.delete(0, tk.END)
self.directoryEntry.insert(0, dirname)
def askfilename(self):
filename = tkFileDialog.askopenfilename(initialdir=dirname)
if filename:
self.dataInput.delete(0, tk.END)
self.dataInput.insert(0, filename)
currentDirectory = os.getcwd()
directory,var = self.UserFileInput(currentDirectory, "Directory")
self.directoryEntry = directory
dirBut = tk.Button(self, text='Select directory...', command = self.askdirectory)
dirBut.grid(row=self.row-1, column=2)
dataInput, var = self.UserFileInput("", "Data input")
self.dataInput = dataInput
fileBut = tk.Button(self, text='Select input file...', command = self.askfilename)
fileBut.grid(row=self.row-1, column=2)
Assuming askdirectory and askfilename belong to the same class, try assigning the directory to self.dirname instead of dirname. Then the variable will be visible anywhere within the class.
def askdirectory(self):
self.dirname = tkFileDialog.askdirectory()
if self.dirname:
self.directoryEntry.delete(0, tk.END)
self.directoryEntry.insert(0, self.dirname)
def askfilename(self):
filename = tkFileDialog.askopenfilename(initialdir=self.dirname)
if filename:
self.dataInput.delete(0, tk.END)
self.dataInput.insert(0, filename)
Related
The script below makes a treeview of files in a folder and when I double click a file, it is copied to the clipboard which works perfectly for my use case.
The filenames (photos) in the folder are stored anonymously while I have a another txt file that contains the names to each ID:
How can I, in the treeview in the GUI, get it to display the names from the ID txt file instead of the filename but continue to copy the file when I double click it?
import os
import subprocess
import shutil
import tkinter as tk
import tkinter.ttk as ttk
class App(tk.Frame):
def __init__(self, master, path):
tk.Frame.__init__(self, master)
self.tree = ttk.Treeview(self, show='tree')
ysb = ttk.Scrollbar(self, orient='vertical', command=self.tree.yview)
xsb = ttk.Scrollbar(self, orient='horizontal', command=self.tree.xview)
self.tree.configure(yscroll=ysb.set, xscroll=xsb.set)
self.tree.heading('#0', text=path, anchor='w')
self.abspath = os.path.abspath(path)
self.tree.bind("<Double-Button-1>",self.copy_to_clipboard)
self.tree.grid(row=0, column=0)
ysb.grid(row=0, column=1, sticky='ns')
xsb.grid(row=1, column=0, sticky='ew')
self.grid()
self.store_path = []
self.reload()
def copy_to_clipboard(self,event,*args):
item = self.tree.focus()
self.store_path.append(self.tree.item(item,"text"))
absolute_path = self.find_absolutePath(item)
cmd = r"ls '{}' | Set-Clipboard".format(absolute_path) # if you only want the contents of folder to be copied
subprocess.run(["powershell", "-command", cmd], shell=True) # windows specific
print("copied")
def find_absolutePath(self, item):
parent_id = self.tree.parent(item)
if parent_id:
parent = self.tree.item(parent_id, 'text')
self.store_path.append(parent)
return self.find_absolutePath(parent_id)
else:
absolute_path = os.path.join(*self.store_path[::-1])
self.store_path = []
return absolute_path
def reload(self):
self.tree.delete(*self.tree.get_children())
root = self.tree.insert('', 'end', text=self.abspath, open=True)
self.process_directory(root, self.abspath)
def process_directory(self, parent, path):
try:
for p in os.listdir(path):
abspath = os.path.join(path, p)
isdir = os.path.isdir(abspath)
oid = self.tree.insert(parent, 'end', text=p, open=False)
if isdir:
self.process_directory(oid, abspath)
except PermissionError:
pass
root = tk.Tk()
path_to_my_project = r'Path\to\project '
app = App(root, path=path_to_my_project)
app.mainloop()
You can store the ID text in the Treeview item's text attribute, and the filename as a column value , then just hide the additional column
self.tree = ttk.Treeview(self, show='tree', columns='hide_me')
self.tree.item(item, text=id_text, values=path_to_file)
self.tree.column(0, width=0, minwidth=0)
Then you can just query the text or values separately as needed
How do I force the button to change its text to the filename? Everything works fine, a dialog box opens and files open too. But I still can't change the button name to the file name and save it.
Here is the code:
import tkinter.filedialog as tfd
import tkinter as tk
import os
window = tk.Tk()
window.title("Op")
window.geometry("600x400")
window.resizable(False, False)
file_name = ""
def open():
global file_name
file_name = tfd.askopenfilename()
os.startfile(file_name) #open file
btn1 = tk.Button(window, text=f"Open {file_name}", command=open) #button
btn1.place(x = 20, y = 25)
You can set the buttons text property using.
button['text'] = fileName
You can also read the button text propeerty to make sure it has been set to the file name in code, I.e. with an if statement.
bText = button['text']
Try using .config -
import tkinter.filedialog as tfd
import tkinter as tk
import os
window = tk.Tk()
window.title("Op")
window.geometry("600x400")
window.resizable(False, False)
file_name = ""
def open():
global file_name
file_name = tfd.askopenfilename()
btn1.config(text=file_name) # Configure the button's text
os.startfile(file_name) #open file
btn1 = tk.Button(window, text=f"Open {file_name}", command=open) #button
btn1.place(x = 20, y = 25)
But if you run this code, the button name gets changed to the complete pathname (e.g. - C:/.../Choosen.file), so if you want only the file name ('Choosen.file') then use this -
btn1.config(text=file_name.split('/')[-1])
You can use:
window = tk.Tk()
window.title("Op")
window.geometry("600x400")
window.resizable(False, False)
file_name = ""
def open():
global file_name
file_name = tfd.askopenfilename()
btn1["text"] += " '" + file_name + "'"
os.startfile(file_name)
btn1 = tk.Button(window, text="Open file", command=open) # button
btn1.place(x=20, y=25)
tk.mainloop()
This uses the old text of the button and appends '{file_path}' to it -> Open file '{file_path}'
You could define a new class that maintains state. This way you can avoid the global, and will be able to make multiple buttons each with their own files.
class FileButton(tk.Button):
def __init__(self, window, file_name=""):
super().__init__(window, command=self.open)
self.set_text(file_name)
def set_text(self, file_name):
self.file_name = file_name
self["text"] = f"Open {self.file_name}"
def open(self):
if self.file_name == "":
self.set_text(tfd.askopenfilename())
os.startfile(self.file_name)
window = tk.Tk()
window.title("Op")
window.geometry("600x400")
window.resizable(False, False)
btn1 = FileButton(window)
btn1.place(x=20, y=25)
window.mainloop()
This is probably a newbie question but I'm having issues figuring out how to get a value from a function, to be used as input in another.
I would also like to have some tips about code organization.
In this example I'm trying to get the filePath and outPut Folder path to be used in the function processFile.
Thank you
Code:
from tkinter import *
from tkinter import ttk
from tkinter.filedialog import askopenfilename
from tkinter.filedialog import askdirectory
import PyPDF2
from PyPDF2 import PdfFileWriter, PdfFileReader
version = "v0.0.01"
root = Tk()
def window (main):
main.title("File Opener " + version)
width = main.winfo_width()
main.geometry('500x200')
numero = str(1)
def OpenFile():
fileName = askopenfilename(initialdir="C:/",
filetypes =(("PDF File", "*.pdf"),("All Files","*.*")),
title = "Select PDF File",
)
labelName = Label(text="File Path: " + fileName)
labelName.pack()
print(fileName)
return fileName
def outputFolder(): #Bug, label keeps adding paths
outPath = askdirectory()
labelName2 = Label(text="Output Folder: " + outPath)
labelName2.pack()
print(outPath)
return outPath
def processFile(inFile,outFolder):
''' print(fileName) get input name and output variables
print(outPath)'''
label = ttk.Label(root, text ="",foreground="black",font=("Helvetica", 16))
label.pack()
#Button Open-----------
button1 = Button (text = "Open File", command = OpenFile)
button1.pack()
#Button Start---------
buttonStart = Button (text = "Start Process", command = processFile)#give as parameter inputFile and link
buttonStart.place(height=50, width=100)
#Button Open-----------
button3 = Button (text = "Output Folder", command = outputFolder)
button3.pack()
#Menu Bar ----------------
menu = Menu(root)
root.config(menu=menu)
file = Menu(menu)
file.add_command(label = 'Open', command = OpenFile)
file.add_command(label = 'Exit', command = lambda:exit())
menu.add_cascade(label = 'File', menu = file)
window(root)
root.mainloop()
If you use the function in a variable the returned result from the function is stored in the variable.
def Function1(x):
return x*2
var1 = Function1(5)
Then var1 = 10.
But about your buttons, do you want to take input from the user that will be saved when the button is pressed or do you want the button to send a set value?
from tkinter import *
from tkinter import ttk
from tkinter.filedialog import askopenfilename
from tkinter.filedialog import askdirectory
import PyPDF2
from PyPDF2 import PdfFileWriter, PdfFileReader
version = "v0.0.01"
root = Tk()
def window (main):
main.title("File Opener " + version)
width = main.winfo_width()
main.geometry('500x200')
main.configure(background = 'black')
numero = str(1)
#openFile
def OpenFile():
global fileName
fileName = askopenfilename(initialdir="C:/",
filetypes =(("PDF File", "*.pdf"),("All Files","*.*")),
title = "Select PDF File",
)
labelName = Label(text="File Path: " + fileName)
labelName.pack()
print(fileName)
return str(fileName)
#getOutputPath
def outputFolder(): #Bug, label keeps adding paths
outPath = askdirectory()
labelName2 = Label(text="Output Folder: " + outPath)
labelName2.pack()
print(outPath)
return outPath
#testFunct
def printFilename(inArg):
print(inArg)
x = OpenFile()
print (OpenFile())
lambda: printFilename(fileName)
#processRealDeal
def processFile(): #THIS IS THE MAIN FUNC
''' print(fileName) get input name and output variables
print(outPath)'''
print (OpenFile)
label = ttk.Label(root, text ="",foreground="black",font=("Helvetica", 16))
label.pack()
#Button Open-----------
button1 = Button (text = "Open File", command = OpenFile)
button1.pack()
#Button Start---------
buttonStart = Button (text = "Start Process", command = lambda: printFilename("Hello World!!!"))#give as parameter inputFile and link
buttonStart.place(height=50, width=100)
#Button Open-----------
button3 = Button (text = "Output Folder", command = outputFolder)
button3.pack()
#Menu Bar ----------------
menu = Menu(root)
root.config(menu=menu)
file = Menu(menu)
file.add_command(label = 'Open', command = OpenFile)
file.add_command(label = 'Exit', command = lambda:exit())
menu.add_cascade(label = 'File', menu = file)
window(root)
root.mainloop()
I cant see that you have declared the global fileName variabel outside the function.
I did this
from tkinter import *
from tkinter import ttk
from tkinter.filedialog import askopenfilename
from tkinter.filedialog import askdirectory
import PyPDF2
from PyPDF2 import PdfFileWriter, PdfFileReader
version = "v0.0.01"
root = Tk()
fileName = "test"
def window (main):
main.title("File Opener " + version)
width = main.winfo_width()
main.geometry('500x200')
main.configure(background = 'black')
numero = str(1)
#openFile
def OpenFile():
global fileName
fileName = askopenfilename(initialdir="C:/",
filetypes =(("PDF File", "*.pdf"),("All Files","*.*")),
title = "Select PDF File",
)
labelName = Label(text="File Path: " + fileName)
labelName.pack()
test()
return str(fileName)
#getOutputPath
def test():
print(fileName)
def outputFolder(): #Bug, label keeps adding paths
outPath = askdirectory()
labelName2 = Label(text="Output Folder: " + outPath)
labelName2.pack()
print(outPath)
return outPath
#testFunct
def printFilename(inArg):
print(inArg)
x = OpenFile()
print (OpenFile())
lambda: printFilename(fileName)
#processRealDeal
def processFile(): #THIS IS THE MAIN FUNC
''' print(fileName) get input name and output variables
print(outPath)'''
print (OpenFile)
label = ttk.Label(root, text ="",foreground="black",font=("Helvetica", 16))
label.pack()
#Button Open-----------
button1 = Button (text = "Open File", command = OpenFile)
button1.pack()
#Button Start---------
buttonStart = Button (text = "Start Process", command = lambda: printFilename("Hello World!!!"))#give as parameter inputFile and link
buttonStart.place(height=50, width=100)
#Button Open-----------
button3 = Button (text = "Output Folder", command = outputFolder)
button3.pack()
#Menu Bar ----------------
menu = Menu(root)
root.config(menu=menu)
file = Menu(menu)
file.add_command(label = 'Open', command = OpenFile)
file.add_command(label = 'Exit', command = lambda:exit())
menu.add_cascade(label = 'File', menu = file)
window(root)
root.mainloop()
And the test function prints the chosen file. So the global variable is now containing the correct value.
So just declare it at the top and you will be able to retrieve the value
I have a tkinter Entry box in which the user can insert a path to the directory. Alternatively the user can click a button to select the directory. How can I set the output from the button to fill the Entry box? I have tried the following but dirname is not a global variable and so is not recognised by UserFileInput. Also how can I bind the button next to the entry field.
from Tkinter import *
import tkFileDialog
def askdirectory():
dirname = tkFileDialog.askdirectory()
return dirname
def UserFileInput(status,name):
optionFrame = Frame(root)
optionLabel = Label(optionFrame)
optionLabel["text"] = name
optionLabel.pack(side=LEFT)
text = str(dirname) if dirname else status
var = StringVar(root)
var.set(text)
w = Entry(optionFrame, textvariable= var)
w.pack(side = LEFT)
optionFrame.pack()
return w
if __name__ == '__main__':
root = Tk()
dirBut = Button(root, text='askdirectory', command = askdirectory)
dirBut.pack(side = RIGHT)
directory = UserFileInput("", "Directory")
root.mainloop()
Your UserFileInput should return var, not w. Then you can use var.set(dirname) in your askdirectory function which doesn't have to return anything.
I'm not sure however what you try to achieve with text = str(dirname) if dirname else status. Why not just use text = status since dirname can't yet be defined there?
Edit:
This should work the way you want it to. The 'print entry text' button shows that you can retreive whatever is in the entry box, either written by the user or put there by the code.
from Tkinter import *
import tkFileDialog
def askdirectory():
dirname = tkFileDialog.askdirectory()
if dirname:
var.set(dirname)
def UserFileInput(status,name):
optionFrame = Frame(root)
optionLabel = Label(optionFrame)
optionLabel["text"] = name
optionLabel.pack(side=LEFT)
text = status
var = StringVar(root)
var.set(text)
w = Entry(optionFrame, textvariable= var)
w.pack(side = LEFT)
optionFrame.pack()
return w, var
def Print_entry():
print var.get()
if __name__ == '__main__':
root = Tk()
dirBut = Button(root, text='askdirectory', command = askdirectory)
dirBut.pack(side = RIGHT)
getBut = Button(root, text='print entry text', command = Print_entry)
getBut.pack(side = BOTTOM)
w, var = UserFileInput("", "Directory")
root.mainloop()
Working with Python and Tkinter, I have been trying to find out the way to show the file_path beside the Browse Button but unable to do so.
Here is my code:
import os
from tkFileDialog import askopenfilename
from Tkinter import *
content = ''
file_path = ''
#~~~~ FUNCTIONS~~~~
def open_file():
global content
global file_path
filename = askopenfilename()
infile = open(filename, 'r')
content = infile.read()
file_path = os.path.dirname(filename)
return content
def process_file(content):
print content
#~~~~~~~~~~~~~~~~~~~
#~~~~~~ GUI ~~~~~~~~
root = Tk()
root.title('Urdu Mehfil Ginti Converter')
root.geometry("598x120+250+100")
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()
file_path = StringVar
Label(f1,text="Select Your File (Only txt files)").grid(row=0, column=0, sticky='e')
Entry(f1, width=50, textvariable=file_path).grid(row=0,column=1,padx=2,pady=2,sticky='we',columnspan=25)
Button(f1, text="Browse", command=open_file).grid(row=0, column=27, sticky='ew', padx=8, pady=4)
Button(f2, text="Process Now", width=32, command=lambda: process_file(content)).grid(sticky='ew', padx=10, pady=10)
root.mainloop()
#~~~~~~~~~~~~~~~~~~~
Kindly guide me as how I can show the file path along with the "Browse Button" button after the user selects the file as shown in this image.
Thanks in advance!
First, change this line:
Entry(f1, width=50, textvariable=file_path).grid(row=0,column=1,padx=2,pady=2,sticky='we',columnspan=25)
to this:
entry = Entry(f1, width=50, textvariable=file_path)
entry.grid(row=0,column=1,padx=2,pady=2,sticky='we',columnspan=25)
Then, in the open_file() function, add these two lines, just before the return:
entry.delete(0, END)
entry.insert(0, file_path)
Explanation:
First, we give the entry a name, so that it can be modified.
Then, in the open_file() function we clear it and add the text for the file-path.
Here is a diff that fixes instead the file_path, i.e. the StringVar() usage:
--- old.py 2016-08-10 18:22:16.203016340 +0200
+++ new.py 2016-08-10 18:24:59.115328029 +0200
## -4,7 +4,6 ##
content = ''
-file_path = ''
#~~~~ FUNCTIONS~~~~
## -16,7 +15,7 ##
filename = askopenfilename()
infile = open(filename, 'r')
content = infile.read()
- file_path = os.path.dirname(filename)
+ file_path.set(os.path.dirname(filename))
return content
def process_file(content):
## -40,7 +39,7 ##
f2 = Frame(mf, width=600, height=250)
f2.pack()
-file_path = StringVar
+file_path = StringVar(root)
Label(f1,text="Select Your File (Only txt files)").grid(row=0, column=0, sticky='e')