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.