我想做什么
我正在尝试为Jupyter笔记本做一个交互式绘图。这些功能全部写在不同的文件中,但它们的预期用途是在交互式笔记本会话中使用。我在matplotlib图形上有一个Button小部件,单击该按钮时,我想打开一个文件对话框,用户可以在其中输入文件名来保存图形。我使用的是Mac OSX(Mojave 10.14.6),Tkinter给我带来了主要问题(完整的系统崩溃),因此我尝试使用PyQt5来实现。
代码
-----------
plotting.py
-----------
from . import file_dialog as fdo
import matplotlib.pyplot as plt
import matplotlib.widgets as wdgts
def plot_stack(stack):
fig, ax = plt.subplots(figsize=(8, 6))
plt.subplots_adjust(bottom=0.25, left=-0.1)
... # plotting happens here
# button for saving
def dosaveframe(event):
fname = fdo.save()
fig.savefig(fname) # to be changed to something more appropriate
savea = plt.axes([0.65, 0.8, 0.15, 0.05], facecolor=axcolor)
saveb = Button(savea, "save frame", hovercolor="yellow")
saveb.on_clicked(dosaveframe)
savea._button = saveb # for persistence
plt.show()
--------------
file_dialog.py
--------------
import sys
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import (QWidget, QFileDialog)
class SaveFileDialog(QWidget):
def __init__(self, text="Save file", types="All Files (*)"):
super().__init__()
self.title = text
self.setWindowTitle(self.title)
self.types = types
self.filename = self.saveFileDialog()
self.show()
def saveFileDialog(self):
options = QFileDialog.Options()
options |= QFileDialog.DontUseNativeDialog
filename, _ = (
QFileDialog.getSaveFileName(self, "Enter filename",
self.types, options=options))
return filename
def save(directory='./', filters="All files (*)"):
"""Open a save file dialog"""
app = QApplication([directory])
ex = SaveFileDialog(types=filters)
return ex.filename
sys.exit(app.exec_())
什么不起作用
保存对话框打开,它响应鼠标,但不响应键盘。不管我是否选择小窗口,键盘都保持与笔记本电脑的连接,因此当我按“ s”时,它将保存笔记本电脑。因此,用户无法输入文件路径。我该如何工作?我有Anaconda,PyQt 5.9.2,matplotlib 3.1.1,jupyter 1.0.0。
我发现了一种非常糟糕,不干净的解决方案,但它似乎可以工作。由于某些原因,直接打开QFileDialog
不允许我激活它。它在被调用的活动窗口(Jupyter Notebook中的终端窗口或浏览器)后面打开,并且不响应键盘。因此,以下块中的save
功能在Mac上无法正常运行:
from PyQt5.QtWidgets import QApplication, QFileDialog
def save(directory='./', filters="All files (*)"):
app = QApplication([directory])
path, _ = QFileDialog.getSaveFileName(caption="Save to file",
filter=filters,
options=options)
return path
起作用的是从小部件打开文件对话框。因此,至少在命令行中,使用永远不会显示在屏幕上的虚拟小部件确实对我有用:
from PyQt5.QtWidgets import (QApplication, QFileDialog, QWidget)
class DummySaveFileDialogWidget(QWidget):
def __init__(self, title="Save file", filters="All Files (*)"):
super().__init__()
self.title = title
self.filters = filters
self.fname = self.savefiledialog()
def savefiledialog(self):
filename, _ = QFileDialog.getSaveFileName(caption=self.title,
filter=self.filters,
options=options)
return filename
def save(directory='./', filters="All files (*)"):
app = QApplication([directory])
form = DummySaveFileDialogWidget()
return form.fname
如果有人找到了更有效的解决方案,请告诉我
编辑:当从命令行调用它时有效,但是仍然不是从Jupyter笔记本中。也尝试过this,没有成功。文件对话框位于浏览器窗口的后面,并且不响应键盘。