使用Python打开目录对话框
我正在尝试为本地服务器创建一个简单的文件对话框(最好是系统自带的那种)。
我不能使用Tkinter,因为它必须在一个子进程中运行,而在Mac上,子进程中的对话框不会保持打开状态。我也不能使用线程,因为这样最终会导致程序卡住。
有没有办法在不使用Tkinter的情况下打开系统的文件对话框呢?
第一个文件是我想要的功能的一个独立工作版本(忽略最后的空值错误)。
import Tkinter as tk
import threading
from tkFileDialog import askdirectory
def createDialog(communicationQueue):
dia = Dialog(communicationQueue)
dia.show()
class Dialog():
def __init__(self, communicationQueue):
self.communicationQueue = communicationQueue
self.root = tk.Tk()
self.root.overrideredirect(True)
self.root.geometry("0x0+%d+%d" % (0, 0))
self.root.withdraw()
print 'creating root'
print 'Root Created'
self.root.update()
self.root.deiconify()
print 'asking directory'
t = threading.Thread(target = self.show)
t.daemon = True
t.start()
self.root.mainloop()
print 'Directory found!'
def show(self):
print "show dialog"
self.root.lift()
name = askdirectory()
print name
self.communicationQueue.put(name)
if __name__ == '__main__':
createDialog(None)
print "Blocking!"
这个文件和第一个文件结合在一起,尝试在子进程中使用Tkinter。
import time
from multiprocessing import Process, Queue
def _createDialog(communicationQueue):
from src.utilities import fileDialog
fileDialog.createDialog(communicationQueue)
print 'method!'
def showDirectoryDialog():
"""A blocking method that returns the directory path to a selected directory"""
communicationQueue = Queue()
p = Process(target = _createDialog, args = (communicationQueue,))
p.start()
count = 0
while (communicationQueue.empty() and count <= 5):
print "waiting"
time.sleep(5)
count = count + 1
print 'Process should start'
time.sleep(1)
print 'Thread should have slept for 1 second'
return name
if __name__ == '__main__':
name = showDirectoryDialog()
print name
如果有人能在Mac上让这个工作,或者至少弄清楚为什么根窗口会一直保持打开状态,直到调用askDirectory(),我将非常感激。
2 个回答
1
下面这个Python函数可以打开一个MacOS的文件保存对话框。你可以通过参数来设置默认的保存位置和文件名。
from AppKit import NSSavePanel, NSApp
from Foundation import NSURL
def save_dialog(directory, filename):
panel = NSSavePanel.savePanel()
panel.setTitle_("Save your document")
myUrl = NSURL.fileURLWithPath_isDirectory_(directory, True)
panel.setDirectoryURL_(myUrl)
panel.setNameFieldStringValue_(filename)
NSApp.activateIgnoringOtherApps_(True)
ret_value = panel.runModal()
if ret_value:
return panel.filename()
else:
return ''
如果你想要打开文件的对话框,可以查看NSOpenPanel的文档(这个更简单)。
0
对于想要解决这个问题的朋友们……
我最后选择了用Java来实现。Python的文件对话框使用起来非常麻烦。它有一些奇怪的要求,还需要你创建一个第二个窗口,然后再把它隐藏,这样就不太符合用户的直觉了。(对程序员来说也不太直观)
而Java有一个内置的文件对话框系统,使用起来简单多了。你可以查看这个链接了解更多:http://docs.oracle.com/javase/7/docs/api/javax/swing/JFileChooser.html
不过,无论使用什么语言,似乎在Mac上从同一个程序多次弹出文件对话框都会有问题,而在Windows上就没有这个问题。
所以如果你的解决方案需要跨平台,这也是需要注意的一点。