This is a feature that I have wanted to see in Jupyter notebook for quite some time. I'm sure that others have built similar things but I haven't been able to find them on SO, Github, CodeReview or the rest of the searchable internet.
ipywidgets.Button as a base class and added a traitlet called files. This traitlet receives a list of files as strings from
tkinter.filedialog.askopenfilename. When the button is clicked the file dialog pops up the user selects files and then can access that list of strings as an attribute/traitlet on the button instance.
import traitlets from ipywidgets import widgets from IPython.display import display from tkinter import Tk, filedialog class SelectFilesButton(widgets.Button): """A file widget that leverages tkinter.filedialog.""" def __init__(self): super(SelectFilesButton, self).__init__() # Add the selected_files trait self.add_traits(files=traitlets.traitlets.List()) # Create the button. self.description = "Select Files" self.icon = "square-o" self.style.button_color = "orange" # Set on click behavior. self.on_click(self.select_files) @staticmethod def select_files(b): """Generate instance of tkinter.filedialog. Parameters ---------- b : obj: An instance of ipywidgets.widgets.Button """ # Create Tk root root = Tk() # Hide the main window root.withdraw() # Raise the root to the top of all windows. root.call('wm', 'attributes', '.', '-topmost', True) # List of selected fileswill be set to b.value b.files = filedialog.askopenfilename(multiple=True) b.description = "Files Selected" b.icon = "check-square-o" b.style.button_color = "lightgreen"
Displaying the button
my_button = SelectFilesButton() my_button # This will display the button in the context of Jupyter Notebook
Retrieving the file list from the button.
# In a different cell of the same Jupyter Notebook You can access the file list by using the following: my_button.files
These are just some suggestions.
1) Does this work on your machine? If so throw me an upvote! If not please specify what versions you are working with so I can extend.
2) Are there any general overall improvements that can be made?
3) Is there any redundancy that I missed?
4) Does this code follow best practices?