dra*_*ega 3 python macos tkinter matplotlib python-2.7
我是Tkinter的新手.我尝试使用下一个代码打开文件tkFileDialog.askopenfilename
,然后使用Matplotlib绘制一些内容:
import matplotlib.pyplot as plt
import Tkinter, tkFileDialog
root = Tkinter.Tk()
root.withdraw()
file_path = tkFileDialog.askopenfilename()
x = range(10)
plt.plot(x)
plt.show()
Run Code Online (Sandbox Code Playgroud)
运行上面的脚本后,我得到一个对话窗口来打开我的文件.文件选择后,我会重复对话窗口打开文件,并在屏幕底部打开一个新窗口.我知道问题是因为plt.show()
.会发生什么以及如何避免重新打开对话框窗口?我应该为我的任务设置Matplotlib后端吗?
我的版本:
Tcl/Tk 8.5.9
Matplotlib 1.3.1
Tkinter $ Revision:81008 $
OS X 10.9.4
我找到了两个相关的stackoverflow问题:
pyplot-show-reopens-old-tkinter-dialog和
matplotlib-figures-not-working-after-tkinter-file-dialog
但没有答案.这似乎root.destroy()
对我不起作用.
运行时python test.py
,以下似乎对我有用:
import matplotlib.pyplot as plt
import Tkinter, tkFileDialog
root = Tkinter.Tk()
root.withdraw()
file_path = tkFileDialog.askopenfilename()
root.destroy()
print file_path
x = range(10)
plt.plot(x)
plt.show()
Run Code Online (Sandbox Code Playgroud)
我认为它的工作原理是因为文件对话框的Tk实例在matplotlib激活它之前就被销毁了.有趣的是,它在运行时也适用于我
ipython --pylab=tk
Run Code Online (Sandbox Code Playgroud)
我希望在两次启动事件循环时遇到问题.在这种情况下,规范的解决方案是在启动之前检查Tk是否已经运行(再次).
我在MacOSX 10.7.5上,定制的matplotlib(应该没关系).
我唯一注意到的是,经过实验,我的Mac上的触摸板滑动手势不再有效......看着这个.
编辑
以下是执行的Tk命令的细分tkFileDialog.askopenfilename()
:
# breakdown of tkFileDialog.askopenfilename()
import Tkinter as Tk
window = Tk.Tk()
window.withdraw()
w = Tk.Frame(window)
s = w.tk.call('tk_getOpenFile', *w._options({}))
print s
w.destroy()
window.destroy()
Run Code Online (Sandbox Code Playgroud)
当我运行它(with python test.py
)时,我得到文件打开对话框,我可以在其中选择一个文件.单击"确定"后,将打印文件名并退出.这在我的系统上每次都有效.但是,有时我的触摸板上的三指手势在运行此程序时停止工作!程序退出后他们不会回来!! 甚至在我终止程序运行之后!
我发现将它们带回来的唯一方法是将以下matplotlib代码添加到test.py
:
import matplotlib
matplotlib.use('tkagg')
import matplotlib.pyplot as plt
plt.figure() # simplified from plt.plot(range(10))
plt.show()
Run Code Online (Sandbox Code Playgroud)
然后单击"图1"的标题栏.这会立即恢复3指手势.我怀疑这只是一个错误Tkinter
.(顺便说一下,我在Tcl/Tk 8.5)
我无法重现文件打开对话框在我的系统上不断重新启动的行为.
如果你启动test.py
,没有任何matplotlib命令,你能描述一下你的系统会发生什么吗?
另外,由于Tkinter很老而且显然有些问题,我可以建议使用Qt吗?它不仅看起来更好,它也更快捷,我没有任何问题的bug.
编辑2
我已经分解了matplotlib在非交互式环境中执行上述命令时所采取的Tk操作(即使用python test.py
和不使用iPython).这些是必不可少的后端调用:
import matplotlib.backends.backend_tkagg as backend
figManager = backend.new_figure_manager(1)
figManager.show()
backend.show.mainloop()
Run Code Online (Sandbox Code Playgroud)
这些仍然是后端独立的.即,对于Qt数字,只需使用:
import matplotlib.backends.backend_qt4agg as backend
Run Code Online (Sandbox Code Playgroud)
如果我们将其进一步分解为特定于后端的层,我们有:
import matplotlib.backends.backend_tkagg as backend
import Tkinter as Tk
window = Tk.Tk()
window.withdraw()
# uncomment this to use the same Tk instance for tkFileDialog and matplotlib
#import tkFileDialog
#fname = tkFileDialog.askopenfilename(master=window)
#print fname
# figManager = backend.new_figure_manager(1)
from matplotlib.figure import Figure
figure = Figure()
canvas = backend.FigureCanvasTkAgg(figure, master=window)
figManager = backend.FigureManagerTkAgg(canvas, 1, window)
# figManager.show()
window.deiconify()
# backend.show.mainloop()
Tk.mainloop()
Run Code Online (Sandbox Code Playgroud)
首先,在注释掉tkFileDialog调用的情况下运行,并检查matplotlib图是否出现并且行为正确.然后取消注释tkFileDialog调用,看看你是否最终获得了预期的行为.
如果没有,人们必须继续打破FigureCanvasTkAgg
并FigureManagerTkAgg
了解发生了什么......
编辑3
好的,既然问题仍然存在,那就让我们进一步分解matplotlib的Tk调用.以下代码完全隔离了我认为必不可少的所有matplotlib的Tk操作(因此不再需要从matplotlib导入任何内容!).请注意,我遗漏了生成工具栏并分配了大量回调和按键事件.如果下面的代码现在有效,那么问题在于这些问题.如果它不起作用,我们可以得出结论,这纯粹是一个Tk问题,而且很可能是一个应该报告的错误.这是代码:
import Tkinter as Tk
window = Tk.Tk()
window.withdraw()
# uncomment this to use the same Tk instance for tkFileDialog and matplotlib
#w = Tk.Frame(window)
#fname = w.tk.call('tk_getOpenFile', *w._options({}))
#print fname
#w.destroy()
# canvas = backend.FigureCanvasTkAgg(figure, master=window)
_tkcanvas = Tk.Canvas(master=window, width=640, height=480, borderwidth=4)
_tkphoto = Tk.PhotoImage(master=_tkcanvas, width=640, height=480)
_tkcanvas.create_image(320, 240, image=_tkphoto)
_tkcanvas.focus_set()
# figManager = backend.FigureManagerTkAgg(canvas, 1, window)
window.wm_title("Figure 1")
window.minsize(480, 360)
_tkcanvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
# figManager.show()
window.deiconify()
# backend.show.mainloop()
Tk.mainloop()
Run Code Online (Sandbox Code Playgroud)
请玩一下注释掉一些线条,看看你是否可以正常工作.如果没有,我会得出结论,这是一个错误Tkinter
,应该报告.
归档时间: |
|
查看次数: |
2320 次 |
最近记录: |