I am trying to figure out how to walk a tree and then display the output in a window that a user can navigate through much like that on the left hand side of my computer. Eventually I plan to have a fully browsable window just like you have on the right hand side. Here is what I have so far, I guess it is a mix of pseudo and actual code. This is for use on a Linux machine using python. I'm not looking for any code but mainly help as to how I can accomplish this with tkinter. Perhaps it is just me but I cannot find much help that helps me solve my problem - most just tell me how to display the directories etc. Any help would be greatly appreciated.
I want this window to look like this
My Documents <--------starting directory
My pictures<------subdirectory
picture1.jpg<-inside of subdirectoy
picture2.jpg
1234.exe<---------random file inside of my documents
I want to have a small folder picture next to a directory or a subdirectory also.
start at root
create window with tk
for dirname,subdirList,filelist in os.walk(root)
create new item(dirname)
for i in subdirList: #not sure what I would have to do to only
have subdirs showing once the directory was
clicked once
append i to item 1
for fname in fileList:
append fname to item 1
else:
item +=1
You can do it using the widget ttk.Treeview, there is a demo dirbrowser.py that does that. So all I can do here is give a stripped version of it and explain how it works. First, here is the short version:
import os
import sys
import Tkinter
import ttk
def fill_tree(treeview, node):
if treeview.set(node, "type") != 'directory':
return
path = treeview.set(node, "fullpath")
# Delete the possibly 'dummy' node present.
treeview.delete(*treeview.get_children(node))
parent = treeview.parent(node)
for p in os.listdir(path):
p = os.path.join(path, p)
ptype = None
if os.path.isdir(p):
ptype = 'directory'
fname = os.path.split(p)[1]
oid = treeview.insert(node, 'end', text=fname, values=[p, ptype])
if ptype == 'directory':
treeview.insert(oid, 0, text='dummy')
def update_tree(event):
treeview = event.widget
fill_tree(treeview, treeview.focus())
def create_root(treeview, startpath):
dfpath = os.path.abspath(startpath)
node = treeview.insert('', 'end', text=dfpath,
values=[dfpath, "directory"], open=True)
fill_tree(treeview, node)
root = Tkinter.Tk()
treeview = ttk.Treeview(columns=("fullpath", "type"), displaycolumns='')
treeview.pack(fill='both', expand=True)
create_root(treeview, sys.argv[1])
treeview.bind('<<TreeviewOpen>>', update_tree)
root.mainloop()
It starts by listing the files and directories present in the path given by sys.argv[1]. You don't want to use os.walk here as you show only the contents directly available in the given path, without going into deeper levels. The code then proceeds to show such contents, and for directories it creates a dummy children so this Treeview entry will be displayed as something that can be further expanded. Then, as you may notice, there is a binding to the virtual event <<TreeviewOpen>> which is fired whenever the user clicks an item in the Treeview that can be further expanded (in this case, the entries that represent directories). When the event is fired, the code ends up removing the dummy node that was created earlier and now populates the node with the contents present in the specified directory. The rest of the code is composed of details about storing additional info in the Treeview to make everything work.
I think tkinter would be a bad choice for this. Other libraries like wxPython, PyQt or GTK does have GUI components which will help you achieve this with minimum effort.
Related
I would like to open a new browser by clicking Button from python tkinker GUI and new directory need to be saved and display on GUI.
I am able to open current directory with command below;
import os
subprocess.Popen('explorer "C:\temp"')
cur_path = os.path.dirname(__file__)
my question is how to save the active browser dir and display on GUI after Step A/B above?
First of all, the imports needed for this answer:
import os
import tkinter as tk # if using Python 3
import Tkinter as tk # if using Python 2
Let's say that your button has been defined.
Here is some sample code which will get the current directory:
curr_directory = os.getcwd() # will get current working directory
If you're looking to set up a GUI to ask the user to select a file, use:
name = tkinter.tkFileDialog.askopenfilename(initialdir = curr_directory,title = "Select file",filetypes = (("jpeg files","*.jpg"),("all files","*.*")))
print(name)
Which will store the file that they have chosen, with the directory they start at set to curr_directory which is the current directory.
If you are instead looking to set up a GUI in which the user chooses a directory, you can use:
dir_name = tk.tkFileDialog.askdirectory()
This will store the name of the directory they have chosen in the dir_name variable.
For more information, check out this link on how to use the file dialog. Alternatively, you can check the general tkinter documentation here (for Python 2) and here (for Python 3). If you need a reference to the file dialog, this is a good source.
Didn't quite know how to word this but here i go,
This part of the program displays the folders found in a directory and subdirectorys in a QTreeWidget (It loads them fine) I would like the ability to create new folders no matter the depth in the tree. For example say i have the directory:
data\examples\folders\
and i right click in the empty space in the QTreeWidget below the folders branch, i want the ability to create a folder below it so the directory becomes:
data\examples\folder\untitled\
I have the context menu working but cannot understand how to implement a way to place the new folder item at a specific depth as i do not know the parent of the area i clicked
Here is my code (only retentive parts):
self.treelist = QtGui.QTreeWidget()
self.treelist.setHeaderLabels(["Name"])
self.treelist.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.treelist.customContextMenuRequested.connect(self.openContextMenu)
And the openContextMenu function
def openContextMenu(self,point):
addFolder = QtGui.QAction(QtGui.QIcon("data\\icons\\folder.png"), "&New Folder", self)
addFolder.triggered.connect(self.addFolderToList)
item = self.treelist.itemAt(point)
#Current Mouse Pos
cpos = QtGui.QCursor()
#Context Menu
contextMenu = QtGui.QMenu(self)
#Context Menu Actions
contextMenu.addAction(self.addFolder)
contextMenu.exec_(cpos.pos())
What i want to happen is when the addFolder action is triggered a folder will be created beneath the parent of the area i clicked.
Thank you for taking the time to read this!
I am having trouble searching for the method to assign to a Push Button the ability to choose a directory. I found this how to have a directory dialog in Pyqt, but I am still unsure about the method.
For example, I have a push button called new_directory and I have this code self.new_directory.clicked.connect(self.pick_new). What do I need to put into the function pick_new so that when new directory is clicked I can choose a new directory and have this stored in a variable?
Thanks!
I think this might help you.
With this you can get the directory.
def pick_new():
dialog = QtGui.QFileDialog()
folder_path = dialog.getExistingDirectory(None, "Select Folder")
return folder_path
I wrote a little application, that saves small videos it generates. The code pasted should do the following:
show dialog to the user to choose a directory
if directory is not empty show widget that has a circle running around so there's a feedback that something is going on
then generate the movies (which takes some time and most if it has handled with multiprocessing pool)
(not included in snippet, but the code would go on to do more background stuff, so the loading widget would stay on for a while
Code:
def saveMovie(self):
self.pause()
if not os.path.exists("outputs"):
os.makedirs("outputs")
dir = QtGui.QFileDialog.getExistingDirectory(self,dir="outputs",options=QtGui.QFileDialog.ShowDirsOnly)
if not dir == '':
self.loading = True
self.loadingWidget.show()
name = os.path.basename(dir) + "_"
settings = sm.fetch_settings()
swarms,l,l1,l2 = self.generate_movies()
Now instead of this, what happens is that the dialog disappears and the loading widget is shown only after the program has existed from self.generate_movies(). What am I missing?
I'm writing a python script that takes a file one at a time or recursively through folders and moves them to a new location. The script takes one parameter (the current path of the file). I want to be able to use the selected item in an explorer window as the variable.
I am making a contextual menu through the regedit files that is labeled "Send to Server". I currently have the appropriate regedit files created and pointed to the location of the command python.exe "path\to\python\file.py
long story short, I want a contextual menu to pop up that says "Send to Server" when a file is right clicked and when executed uses the selected file's or folder's path as the only variable I need. So far I have come across tkFileDialog (not quite what I want) ctypes and win32 modules but I can't quite figure out the last three modules or whether or not they will help
As a side note. I have created a python script that does this exact thing on mac osx. Much easier with macs 'services' feature.
If you put a shortcut to this script (written for Python 3) in the user's "SendTo" folder (%USERPROFILE%\SendTo), it will pop up a directory dialog when selected from the right-click SendTo menu. The dialog works for network locations as well. When the script runs, the full path to the selected file/folder is in sys.argv[1]. Currently it just shows the selected destination path in a message box. You can change the extension to pyw if you don't want a console.
import os, sys
from tkinter import Tk, filedialog
from tkinter.messagebox import showinfo
class Dialog:
def __init__(self, path):
self.path = path
self.dst_path = ''
self.root = root = Tk()
root.iconify()
root.after_idle(self.askdirectory)
root.mainloop()
def askdirectory(self):
self.dst_path = filedialog.askdirectory(initialdir=self.path)
showinfo('Selected Path', self.dst_path)
self.root.destroy()
if __name__ == '__main__':
if len(sys.argv) > 1:
path = sys.argv[1]
if os.path.isfile(path):
path = os.path.dirname(path)
dialog = Dialog(path)
#if dialog.dst_path: do_something(dialog.dst_path)