使用Python打开目录对话框

0 投票
2 回答
1375 浏览
提问于 2025-04-18 14:55

我正在尝试为本地服务器创建一个简单的文件对话框(最好是系统自带的那种)。

我不能使用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上就没有这个问题。

所以如果你的解决方案需要跨平台,这也是需要注意的一点。

撰写回答