奇怪的行为:使用tkfiledialog的python应用程序,对话框没有第二次打开

时间:2015-08-06 07:49:46

标签: python python-2.7 tkinter

我有一个python应用程序控制某些技术设备的测试平台。 Python本身并没有使用GUI,所有内容都显示在浏览器中,我们使用套接字连接进行通信。

有一点,操作员必须保存协议文件,我们需要一个对话框来选择这个文件。为此,我决定使用Tkinter插件。

所以现在我有一个小模块dialogs.py用于所有GUI的东西,这可能相当过分,但是nvm。这是:

from Tkinter import Toplevel, Tk
from tkFileDialog import asksaveasfilename, askopenfilename, askdirectory

class Getter:

    def _create(self):
        self.gui = Tk() # create instance
        self.gui.wm_attributes('-topmost', 1) # ensure it is on top
        self.gui.geometry('0x0+0+0') # minimize

    def _destroy(self):
        self.gui.destroy() # destroy instance

    def get(self):
        pass


class SaveFileGetter(Getter):

    def get(self, ext=None, dir=None, file=None):
        self._create()
        filename = asksaveasfilename(parent=self.gui, defaultextension=ext, initialdir=dir, initialfile=file) # show the dialog
        self._destroy()
        return filename

然后在另一个模块中有某处:

from helpers.dialogs import SaveFileGetter

# lots of code

def saveOnRemote(self):
    # code
    protocolFilePath = SaveFileGetter().get(ext='.html')
    # more code

# even more code

当应用程序第一次运行时,一切都很好。但是当第二次运行时,程序到达

self.gui = Tk()

没有任何反应。没有对话框打开,没有例外,没有哔哔声,没有。该计划可以说是冻结的。 CPU使用率保持很高,所以很明显后台发生了一些事情,但应用程序本身并没有向前发展。

使事情变得奇怪:如果我使用Toplevel()而不是Tk(),对话框会多次打开,但偶尔会在同一行代码中出现异常:

self.gui = Toplevel()

显示的错误是:

File "C:/path/to/my/project/somepythonfile.py", line 324, in saveOnRemote
protocolFilePath = SaveFileGetter().get(ext='.html')
File "C:/path/to/my/project/dialogs.py", line 22, in get
self._create()
File "C:/path/to/my/project/dialogs.py", line 8, in _create
self.gui = Toplevel()
File "C:\Python27\lib\lib-tk\Tkinter.py", line 2129, in __init__
BaseWidget.__init__(self, master, 'toplevel', cnf, {}, extra)
File "C:\Python27\lib\lib-tk\Tkinter.py", line 2086, in __init__
(widgetName, self._w) + extra + self._options(cnf))
TclError: out of stack space (infinite loop?)

对于大师的怪异,这可能发生在任何时候,第三次执行,第十次......或更晚。稍后运行它可能每小时使用一次,但我无法接受,因为操作员必须重新启动程序才能使其再次正常工作,并且btw无法在此时保存协议文件。

我已经写了一个小的独立脚本,在无限循环中请求保存文件对话框。即使没有self.gui.destroy()部分,一切都按照需要使用Tk()或Toplevel()。

因此,我的应用程序中必须有其他内容导致此行为。当然我无法显示整个代码(太多,公司工作等),我想你很难猜到。我的同事们都没有任何线索,我自己刚刚开始担任软件开发人员的第3个月并且也很无能为力。

所以如果你有一个想法的最微小的方法,可能是什么原因,请告诉我。

受到rolika评论的启发,我将我的Getter课程改为:

class Getter:

    def __init__(self):
        self.gui = Tk()
        self.gui.wm_attributes('-topmost', 1)
        self.gui.geometry('0x0+0+0')

    def __del__(self):
        self.gui.destroy()

不幸的是,它并没有明显地改变任何东西。

2 个答案:

答案 0 :(得分:0)

这只是一个建议:

您是否在未提供父母的情况下尝试过?家长是可选的,如果您不提供,则会在您应用的根窗口上弹出对话框。

请在此处查看:http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/tkFileDialog.html

答案 1 :(得分:0)

仅仅是为了记录,虽然它不是真正的答案,但是一个解决方案。我现在正在使用wxPython而不是Tkinter。所以这是我的Getter课程:

import wx

class Getter():

    def __init__(self):

        self.app = wx.App()
        self.frame = wx.Frame(None, -1, style=wx.CAPTION, size=(0, 0))

    def __del__(self):

        self.app.Destroy()

    def saveFile(self, ext='*.*', dir='', file='', title=''):

        dialog = wx.FileDialog(self.frame, title, dir, file, '|'+ext, wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT)
        dialog.ShowModal()
        return dialog.GetPath()

每次都有效。