在Mac OS X上使用Tkinter和Matplotlib的重复对话框窗口 [英] Repeated dialog window with Tkinter and Matplotlib on Mac OS X

查看:115
本文介绍了在Mac OS X上使用Tkinter和Matplotlib的重复对话框窗口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Tkinter的新手.我尝试使用下一个代码使用tkFileDialog.askopenfilename打开文件,然后使用Matplotlib进行绘制:

I'm newbie in Tkinter. I try to use next code to open a file using tkFileDialog.askopenfilename and then plot something with 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()

运行上述脚本后,我将打开对话框窗口以打开文件.选择文件后,我得到重复的对话框窗口以打开文件,并在屏幕底部看到一个新窗口.我知道问题是由于plt.show()引起的.会发生什么,以及如何避免重新打开对话框窗口?我应该为我的任务设置Matplotlib后端吗?

After running the above script I get dialog window to open my file. After file selection I get repeated dialog window to open the file and a new window at the bottom of my screen. I know that the problem is because of plt.show(). What happens and how to avoid dialog window reopening? Should I set a Matplotlib backend for my task?

我的版本:

Tcl/Tk 8.5.9

Tcl/Tk 8.5.9

Matplotlib 1.3.1

Matplotlib 1.3.1

Tkinter $修订:81008 $

Tkinter $Revision: 81008 $

OS X 10.9.4

OS X 10.9.4

我发现了两个相关的stackoverflow问题: pyplot-show-reopens-old-tkinter-dialog matplotlib-figures-not-working-after-tkinter-file-dialog 但没有答案.似乎root.destroy()对我不起作用.

I have found two related stackoverflow questions: pyplot-show-reopens-old-tkinter-dialog and matplotlib-figures-not-working-after-tkinter-file-dialog but no answers. It seems that root.destroy() is not working for me.

推荐答案

python test.py一起运行时,以下内容似乎对我有用:

When run with python test.py, the following seems to work for me:

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()

我认为这是可行的,因为文件对话框的Tk实例在matplotlib启动之前已被销毁.有趣的是,它从运行时对我也有用

I think it works because the Tk instance for the file dialog is destroyed before matplotlib fires up its own. Interestingly, it also works for me when run from

ipython --pylab=tk

我曾预计两次启动事件循环会出现问题.在这种情况下,典型的解决方案是在再次启动Tk之前检查Tk是否已经在运行.

where I would have expected a problem with starting the event loop twice. The canonical solution in this case would be to check if Tk is already running before firing it up (again).

我使用的是MacOSX 10.7.5,自定义的matplotlib(无关紧要).

I'm on MacOSX 10.7.5, custom built matplotlib (shouldn't matter).

我唯一注意到的是,在对此进行了试验之后,我的Mac上的触摸板划动手势不再起作用...正在对此进行调查.

The only thing I noticed was that after experimenting with this, the touchpad swipe gestures on my Mac no longer work... Looking into this.

修改

以下是tkFileDialog.askopenfilename()执行的Tk命令的细分:

Here is a breakdown of the Tk commands executed by 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()

运行此命令(使用python test.py)时,出现文件打开对话框,从中可以选择文件.单击确定"后,将打印文件名并退出.这在我的系统上每次都有效.但是,有时在运行此程序时,触摸板上的三指手势会停止工作!而且他们不会在程序退出后回来!甚至在我杀死终端后程序就没有运行!!!

When I run this (with python test.py), I get the file open dialog, where I can choose a file. Upon "OK" it prints the file name and exits. This works every time on my system. However, sometimes the 3-finger gestures on my touchpad stop working while running this program! And they don't come back after the program exits!! Not even after I kill the terminal the program was running in!!!

我发现带回它们的唯一方法是将以下matplotlib代码添加到test.py:

The only way I found to bring them back is to add the following matplotlib code to test.py:

import matplotlib
matplotlib.use('tkagg')
import matplotlib.pyplot as plt
plt.figure()     # simplified from plt.plot(range(10))
plt.show()

,然后单击图1"的标题栏.这会立即恢复三指手势.我怀疑这只是Tkinter中的错误. (顺便说一下,我使用的是Tcl/Tk 8.5)

and then click on the title bar of "Figure 1". This instantly brings back the 3-finger gestures. I suspect this is simply a bug in Tkinter. (I'm on Tcl/Tk 8.5, by the way)

我无法重现文件打开对话框在我的系统中不断重新启动的行为.

I cannot reproduce the behavior that the file open dialog is constantly relaunched on my system.

能否请您描述一下在没有任何matplotlib命令的情况下启动test.py时系统会发生什么情况?

Could you please describe what happens on your system if you launch test.py, without any matplotlib commands?

或者,由于Tkinter很老,而且显然是越野车,我可以建议改用Qt吗?它不仅看起来更好,而且还更加简单,而且我在bug方面也没有任何问题.

Alternatively, since Tkinter is old and apparently buggy, may I suggest to use Qt instead? Not only does it look much nicer, it is also snappier and I didn't have any problems with bugs.

编辑2

我已经分解了在非交互式环境(即使用python test.py而不是来自iPython)中执行上述命令时matplotlib采取的Tk动作.这些是基本的后端调用:

I have broken down the Tk actions that matplotlib takes when executing the above commands in a non-interactive environment (i.e. with python test.py and not from iPython). These are the essential backend calls:

import matplotlib.backends.backend_tkagg as backend
figManager = backend.new_figure_manager(1)
figManager.show()
backend.show.mainloop()

这些仍然独立于后端.即,对于Qt数字,只需使用:

These are still backend independent. I.e., for a Qt figure, simply use:

import matplotlib.backends.backend_qt4agg as backend

如果将其进一步细分到特定于后端的层,我们将:

If we break this down further to the backend-specific layer, we have:

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()

首先,在注释掉tkFileDialog调用的情况下运行,并检查matplotlib图是否出现并正常运行.然后取消对tkFileDialog调用的注释,看看是否最终得到了预期的行为.

First, run with the tkFileDialog calls commented out and check if the matplotlib figure appears and behaves correctly. Then uncomment the tkFileDialog calls and see if you finally get the expected behavior.

如果没有,则必须继续分解FigureCanvasTkAggFigureManagerTkAgg才能了解正在发生的事情...

If not, one has to continue breaking down FigureCanvasTkAgg and FigureManagerTkAgg to understand what is going on...

编辑3

好的,因为问题仍然存在,所以让我们进一步分析一下matplotlib的Tk调用.以下代码完全隔离了我认为必不可少的所有matplotlib的Tk动作(因此不再需要从matplotlib导入任何内容!).请注意,我省去了生成工具栏以及分配大量回调和按键事件的麻烦.如果下面的代码现在可以正常工作,那么问题就出在这些地方.如果它不起作用,我们可以得出结论,这纯粹是一个Tk问题,并且很可能应该报告一个错误.这是代码:

OK, since the problem persisted, let's break down matplotlib's Tk calls even further. The following code completely isolates all of matplotlib's Tk actions that I consider essential (so it is no longer necessary to import anything from matplotlib!). Note that I left out generating the toolbar and assigning lots of callbacks and keypress events. If the code below works now, then the problem lies with these. If it doesn't work, we can conclude that it is purely a Tk problem, and most likely a bug that should be reported. Here is the code:

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()

请随便注释掉一些行,看看是否可以使其正常工作.如果没有,我会得出结论,这是Tkinter中的错误,应该报告.

Please play around with commenting out some lines and see if you can get it working correctly. If not, I would conclude that this is a bug in Tkinter, which should be reported.

这篇关于在Mac OS X上使用Tkinter和Matplotlib的重复对话框窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆