I don’t know if this is the right place for this question, but the behavior only happens in Jupyter notebooks so I thought I’d give it a try.
I’m writing a function that creates an interactive matplotlib figure inside a notebook for visualizing a stack of images. I have a couple sliders to select the image frame, to adjust contrast and brightness, and a checkbox to add a scalebar. Now I want to add a “save” button to this figure which opens a file dialog to allow the user to browse to a location to save the current view. I’m on Mac (OSX Mojave 10.14.6) and Tkinter gives me terrible problems (i.e. complete system crashes) so I was looking at PyQt’s QFileDialog
for the job. However, it seems like Jupyter doesn’t like working with Qt. When I try to open the filedialog directly from a cell in the notebook, the kernel always dies. So instead I’ve written a rather convoluted script:
from PyQt5.QtWidgets import QApplication, QFileDialog, QWidget
class SaveFileDialog(QWidget):
def __init__(self, filters="All Files (*)"):
super().__init__()
self.title = "Save file"
self.filters = filters
self.filename = self.saveFileDialog()
def saveFileDialog(self):
options = QFileDialog.Options()
options |= QFileDialog.DontUseNativeDialog
filename, _ = QFileDialog.getSaveFileName(caption=self.title,
filter=self.filters,
options=options)
return filename
def get_fname(directory='./', filters="All files (*)"):
app = QApplication([directory])
fd = SaveFileDialog(filters=filters)
return fd.filename
if __name__ == "__main__":
s = get_fname()
print(s)
When I run this from the command line, either with python script.py
or by running get_fname
in IPython, I get the expected behavior: a filename is printed in the terminal and I can interact with the dialog. The reason I wrap it in this widget is because if I directly call QFileDialog.getSaveFileName
it opens the dialog also, but it doesn’t respond to keyboard input and thus I can’t enter a filename.
Anyway, using this exact code and calling get_fname()
in a notebook does not work. It opens up the file dialog behind the browser window. It responds to mouse clicks, but not to keyboard input. Keyboard input remains directed a the notebook.
Does anyone know what the reason for this is and how to fix it? I’m open to any solution (not involving Tkinter) to opening a file dialog from a jupyter notebook and letting the user enter a save file location. Thanks.